diff --git a/teensy3/Arduino.h b/teensy3/Arduino.h
new file mode 100644
index 0000000000000000000000000000000000000000..298e0a2db85583c848e7eb314c759310fe4f7fe8
--- /dev/null
+++ b/teensy3/Arduino.h
@@ -0,0 +1,2 @@
+#include "WProgram.h"
+#include "pins_arduino.h"
diff --git a/teensy3/Client.h b/teensy3/Client.h
new file mode 100644
index 0000000000000000000000000000000000000000..da8556a8c3cf7363554c83e856bfb68af7266aa1
--- /dev/null
+++ b/teensy3/Client.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
diff --git a/teensy3/HardwareSerial.h b/teensy3/HardwareSerial.h
new file mode 100644
index 0000000000000000000000000000000000000000..1554cf109d9c5eede55eff4c329347c65764f490
--- /dev/null
+++ b/teensy3/HardwareSerial.h
@@ -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
diff --git a/teensy3/HardwareSerial1.cpp b/teensy3/HardwareSerial1.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9ac972ed68a7a8bbb503b3d3ad9fa9442acade00
--- /dev/null
+++ b/teensy3/HardwareSerial1.cpp
@@ -0,0 +1,4 @@
+#include "HardwareSerial.h"
+
+HardwareSerial Serial1;
+
diff --git a/teensy3/HardwareSerial2.cpp b/teensy3/HardwareSerial2.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d9fc3b87ff46d6f6ebaa08053ad692a6b46a812d
--- /dev/null
+++ b/teensy3/HardwareSerial2.cpp
@@ -0,0 +1,4 @@
+#include "HardwareSerial.h"
+
+HardwareSerial2 Serial2;
+
diff --git a/teensy3/HardwareSerial3.cpp b/teensy3/HardwareSerial3.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..553b732748b698b754a293a71b151d5f9a0e9be3
--- /dev/null
+++ b/teensy3/HardwareSerial3.cpp
@@ -0,0 +1,4 @@
+#include "HardwareSerial.h"
+
+HardwareSerial3 Serial3;
+
diff --git a/teensy3/IPAddress.cpp b/teensy3/IPAddress.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..673ed8ceb8eb681feecefb575fa27baf72b76ce4
--- /dev/null
+++ b/teensy3/IPAddress.cpp
@@ -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
diff --git a/teensy3/IPAddress.h b/teensy3/IPAddress.h
new file mode 100644
index 0000000000000000000000000000000000000000..7738eca8e6193ad3c066799cb8d87e17211b5c41
--- /dev/null
+++ b/teensy3/IPAddress.h
@@ -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
diff --git a/teensy3/IntervalTimer.cpp b/teensy3/IntervalTimer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6a0021a17b119220f1d2c3fcc6e88cff68a8b04a
--- /dev/null
+++ b/teensy3/IntervalTimer.cpp
@@ -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();
+  
+}
+
+
diff --git a/teensy3/IntervalTimer.h b/teensy3/IntervalTimer.h
new file mode 100644
index 0000000000000000000000000000000000000000..fa5d4eeb9ce5dbfbf7de5412d75bf8027b974c43
--- /dev/null
+++ b/teensy3/IntervalTimer.h
@@ -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
diff --git a/teensy3/Makefile b/teensy3/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..5cc1efcea66039fddcfaa4b2276428b2303142c1
--- /dev/null
+++ b/teensy3/Makefile
@@ -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)
+
+%.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
+
+
diff --git a/teensy3/Print.cpp b/teensy3/Print.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..695d3a125294105a26d05c4ad2415308386b9a7f
--- /dev/null
+++ b/teensy3/Print.cpp
@@ -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;
+}
+
+
diff --git a/teensy3/Print.h b/teensy3/Print.h
new file mode 100644
index 0000000000000000000000000000000000000000..1f0a5506d5a8b04b1a71d2d17ba139bb083bdb27
--- /dev/null
+++ b/teensy3/Print.h
@@ -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
diff --git a/teensy3/Printable.h b/teensy3/Printable.h
new file mode 100644
index 0000000000000000000000000000000000000000..2ac5117a7a59bb97325987974320d2ce6f59413e
--- /dev/null
+++ b/teensy3/Printable.h
@@ -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
diff --git a/teensy3/Server.h b/teensy3/Server.h
new file mode 100644
index 0000000000000000000000000000000000000000..167adacbf8269838b0f3102179c52bbafd852b09
--- /dev/null
+++ b/teensy3/Server.h
@@ -0,0 +1,12 @@
+#if ARDUINO >= 100
+
+#ifndef server_h
+#define server_h
+
+class Server : public Print {
+public:
+  virtual void begin() =0;
+};
+
+#endif
+#endif
diff --git a/teensy3/Stream.cpp b/teensy3/Stream.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..186b60851abed35571627a712478d1aebcb97ee1
--- /dev/null
+++ b/teensy3/Stream.cpp
@@ -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;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/teensy3/Stream.h b/teensy3/Stream.h
new file mode 100644
index 0000000000000000000000000000000000000000..29d202016779bfd4dcc3805d67c32525488c1f08
--- /dev/null
+++ b/teensy3/Stream.h
@@ -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	
diff --git a/teensy3/Tone.cpp b/teensy3/Tone.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a3b4bab999a6a20fab85ecac0950fa3f099a1bc6
--- /dev/null
+++ b/teensy3/Tone.cpp
@@ -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
+
+
+
+
+
+
+
+
+
diff --git a/teensy3/Udp.h b/teensy3/Udp.h
new file mode 100644
index 0000000000000000000000000000000000000000..15d821ae8b794f9c897cfab4ee90b9477467af2b
--- /dev/null
+++ b/teensy3/Udp.h
@@ -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
diff --git a/teensy3/WCharacter.h b/teensy3/WCharacter.h
new file mode 100644
index 0000000000000000000000000000000000000000..79733b50a535b2cc17119168acb51a92c37fa610
--- /dev/null
+++ b/teensy3/WCharacter.h
@@ -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
\ No newline at end of file
diff --git a/teensy3/WConstants.h b/teensy3/WConstants.h
new file mode 100644
index 0000000000000000000000000000000000000000..3e19ac44aac6f8327b75922c2396ea52001cf6b7
--- /dev/null
+++ b/teensy3/WConstants.h
@@ -0,0 +1 @@
+#include "wiring.h"
diff --git a/teensy3/WMath.cpp b/teensy3/WMath.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..927633edefecab30952564901330cca1071fa96f
--- /dev/null
+++ b/teensy3/WMath.cpp
@@ -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; }
+
diff --git a/teensy3/WProgram.h b/teensy3/WProgram.h
new file mode 100644
index 0000000000000000000000000000000000000000..f1fe195d001a87eda74b892fabf840919479d166
--- /dev/null
+++ b/teensy3/WProgram.h
@@ -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
diff --git a/teensy3/WString.cpp b/teensy3/WString.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f18fa922004ec813433daa9f07b5ca9fba3624cb
--- /dev/null
+++ b/teensy3/WString.cpp
@@ -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;
+}
+
+
diff --git a/teensy3/WString.h b/teensy3/WString.h
new file mode 100644
index 0000000000000000000000000000000000000000..e979a8b617afed99b539a1cafa80e860d555dd19
--- /dev/null
+++ b/teensy3/WString.h
@@ -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
diff --git a/teensy3/analog.c b/teensy3/analog.c
new file mode 100644
index 0000000000000000000000000000000000000000..f8d33b0fb5e163b38f9a01422c4b6e829d489acb
--- /dev/null
+++ b/teensy3/analog.c
@@ -0,0 +1,258 @@
+/* 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(".");
+	}
+	//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;
+}
+
+// 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
+};
+
+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
+
+	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;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/teensy3/arm_common_tables.h b/teensy3/arm_common_tables.h
new file mode 100644
index 0000000000000000000000000000000000000000..8c35ef2bd516c3002ebfc44e1542f5dd0e44bbcb
--- /dev/null
+++ b/teensy3/arm_common_tables.h
@@ -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 */
diff --git a/teensy3/arm_math.h b/teensy3/arm_math.h
new file mode 100644
index 0000000000000000000000000000000000000000..8822dc8eb4649d9a4ccfbd58fde1e0c3215497a8
--- /dev/null
+++ b/teensy3/arm_math.h
@@ -0,0 +1,7571 @@
+/* ----------------------------------------------------------------------   
+ * Copyright (C) 2010-2011 ARM Limited. All rights reserved.   
+ *   
+ * $Date:        15. February 2012  
+ * $Revision: 	V1.1.0  
+ *   
+ * Project: 	    CMSIS DSP Library   
+ * Title:	     	arm_math.h
+ *   
+ * Description:	 Public header file for CMSIS DSP Library
+ *   
+ * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
+ *  
+ * Version 1.1.0 2012/02/15 
+ *    Updated with more optimizations, bug fixes and minor API changes.  
+ *  
+ * Version 1.0.10 2011/7/15 
+ *    Big Endian support added and Merged M0 and M3/M4 Source code.  
+ *   
+ * 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.   
+ * -------------------------------------------------------------------- */
+
+/**
+   \mainpage CMSIS DSP Software Library
+   *
+   * <b>Introduction</b>
+   *
+   * This user manual describes the CMSIS DSP software library, 
+   * a suite of common signal processing functions for use on Cortex-M processor based devices.
+   *
+   * The library is divided into a number of functions each covering a specific category:  
+   * - Basic math functions
+   * - Fast math functions
+   * - Complex math functions
+   * - Filters
+   * - Matrix functions
+   * - Transforms
+   * - Motor control functions
+   * - Statistical functions
+   * - Support functions
+   * - Interpolation functions
+   *
+   * The library has separate functions for operating on 8-bit integers, 16-bit integers,
+   * 32-bit integer and 32-bit floating-point values. 
+   *
+   * <b>Pre-processor Macros</b> 
+   * 
+   * Each library project have differant pre-processor macros. 
+   * 
+   * - UNALIGNED_SUPPORT_DISABLE: 
+   * 
+   * Define macro UNALIGNED_SUPPORT_DISABLE, If the silicon does not support unaligned memory access    
+   * 
+   * - ARM_MATH_BIG_ENDIAN: 
+   * 
+   * Define macro ARM_MATH_BIG_ENDIAN to build the library for big endian targets. By default library builds for little endian targets. 
+   * 
+   * - ARM_MATH_MATRIX_CHECK: 
+   * 
+   * Define macro ARM_MATH_MATRIX_CHECK for checking on the input and output sizes of matrices 
+   * 
+   * - ARM_MATH_ROUNDING: 
+   * 
+   * Define macro ARM_MATH_ROUNDING for rounding on support functions
+   *
+   * - ARM_MATH_CMx:
+   *
+   * Define macro ARM_MATH_CM4 for building the library on Cortex-M4 target, ARM_MATH_CM3 for building library on Cortex-M3 target
+   * and ARM_MATH_CM0 for building library on cortex-M0 target.
+   * 
+   * - __FPU_PRESENT:
+   *
+   * Initialize macro __FPU_PRESENT = 1 when building on FPU supported Targets. Enable this macro for M4bf and M4lf libraries 
+   *
+   * <b>Toolchain Support</b>
+   *
+   * The library has been developed and tested with MDK-ARM version 4.23. 
+   * The library is being tested in GCC and IAR toolchains and updates on this activity will be made available shortly.
+   *
+   * <b>Using the Library</b>
+   *
+   * The library installer contains prebuilt versions of the libraries in the <code>Lib</code> folder.
+   * - arm_cortexM4lf_math.lib (Little endian and Floating Point Unit on Cortex-M4)
+   * - arm_cortexM4bf_math.lib (Big endian and Floating Point Unit on Cortex-M4)
+   * - arm_cortexM4l_math.lib (Little endian on Cortex-M4)
+   * - arm_cortexM4b_math.lib (Big endian on Cortex-M4)
+   * - arm_cortexM3l_math.lib (Little endian on Cortex-M3)
+   * - arm_cortexM3b_math.lib (Big endian on Cortex-M3)
+   * - arm_cortexM0l_math.lib (Little endian on Cortex-M0)
+   * - arm_cortexM0b_math.lib (Big endian on Cortex-M3)
+   *
+   * The library functions are declared in the public file <code>arm_math.h</code> which is placed in the <code>Include</code> folder.
+   * Simply include this file and link the appropriate library in the application and begin calling the library functions. The Library supports single 
+   * public header file <code> arm_math.h</code> for Cortex-M4/M3/M0 with little endian and big endian. Same header file will be used for floating point unit(FPU) variants. 
+   * Define the appropriate pre processor MACRO ARM_MATH_CM4 or  ARM_MATH_CM3 or 
+   * ARM_MATH_CM0 depending on the target processor in the application.
+   *
+   * <b>Examples</b>
+   *
+   * The library ships with a number of examples which demonstrate how to use the library functions.
+   *
+   * <b>Building the Library</b>
+   *
+   * The library installer contains project files to re build libraries on MDK Tool chain in the <code>CMSIS\\DSP_Lib\\Source\\ARM</code> folder.
+   * - arm_cortexM0b_math.uvproj
+   * - arm_cortexM0l_math.uvproj
+   * - arm_cortexM3b_math.uvproj
+   * - arm_cortexM3l_math.uvproj  
+   * - arm_cortexM4b_math.uvproj
+   * - arm_cortexM4l_math.uvproj
+   * - arm_cortexM4bf_math.uvproj
+   * - arm_cortexM4lf_math.uvproj
+   *
+   *
+   * The project can be built by opening the appropriate project in MDK-ARM 4.23 chain and defining the optional pre processor MACROs detailed above.
+   *
+   * <b>Copyright Notice</b>
+   *
+   * Copyright (C) 2010 ARM Limited. All rights reserved.
+   */
+
+
+/**
+ * @defgroup groupMath Basic Math Functions
+ */
+
+/**
+ * @defgroup groupFastMath Fast Math Functions
+ * This set of functions provides a fast approximation to sine, cosine, and square root.
+ * As compared to most of the other functions in the CMSIS math library, the fast math functions
+ * operate on individual values and not arrays.
+ * There are separate functions for Q15, Q31, and floating-point data.
+ *
+ */
+
+/**
+ * @defgroup groupCmplxMath Complex Math Functions
+ * This set of functions operates on complex data vectors.
+ * The data in the complex arrays is stored in an interleaved fashion
+ * (real, imag, real, imag, ...).
+ * In the API functions, the number of samples in a complex array refers
+ * to the number of complex values; the array contains twice this number of
+ * real values.
+ */
+
+/**
+ * @defgroup groupFilters Filtering Functions
+ */
+
+/**
+ * @defgroup groupMatrix Matrix Functions
+ *
+ * This set of functions provides basic matrix math operations.
+ * The functions operate on matrix data structures.  For example,
+ * the type
+ * definition for the floating-point matrix structure is shown
+ * below:
+ * <pre>
+ *     typedef struct
+ *     {
+ *       uint16_t numRows;     // number of rows of the matrix.
+ *       uint16_t numCols;     // number of columns of the matrix.
+ *       float32_t *pData;     // points to the data of the matrix.
+ *     } arm_matrix_instance_f32;
+ * </pre>
+ * There are similar definitions for Q15 and Q31 data types.
+ *
+ * The structure specifies the size of the matrix and then points to
+ * an array of data.  The array is of size <code>numRows X numCols</code>
+ * and the values are arranged in row order.  That is, the
+ * matrix element (i, j) is stored at:
+ * <pre>
+ *     pData[i*numCols + j]
+ * </pre>
+ *
+ * \par Init Functions
+ * There is an associated initialization function for each type of matrix
+ * data structure.
+ * The initialization function sets the values of the internal structure fields.
+ * Refer to the function <code>arm_mat_init_f32()</code>, <code>arm_mat_init_q31()</code>
+ * and <code>arm_mat_init_q15()</code> for floating-point, Q31 and Q15 types,  respectively.
+ *
+ * \par
+ * Use of the initialization function is optional. However, if initialization function is used
+ * then the instance structure cannot be placed into a const data section.
+ * To place the instance structure in a const data
+ * section, manually initialize the data structure.  For example:
+ * <pre>
+ * <code>arm_matrix_instance_f32 S = {nRows, nColumns, pData};</code>
+ * <code>arm_matrix_instance_q31 S = {nRows, nColumns, pData};</code>
+ * <code>arm_matrix_instance_q15 S = {nRows, nColumns, pData};</code>
+ * </pre>
+ * where <code>nRows</code> specifies the number of rows, <code>nColumns</code>
+ * specifies the number of columns, and <code>pData</code> points to the
+ * data array.
+ *
+ * \par Size Checking
+ * By default all of the matrix functions perform size checking on the input and
+ * output matrices.  For example, the matrix addition function verifies that the
+ * two input matrices and the output matrix all have the same number of rows and
+ * columns.  If the size check fails the functions return:
+ * <pre>
+ *     ARM_MATH_SIZE_MISMATCH
+ * </pre>
+ * Otherwise the functions return
+ * <pre>
+ *     ARM_MATH_SUCCESS
+ * </pre>
+ * There is some overhead associated with this matrix size checking.
+ * The matrix size checking is enabled via the \#define
+ * <pre>
+ *     ARM_MATH_MATRIX_CHECK
+ * </pre>
+ * within the library project settings.  By default this macro is defined
+ * and size checking is enabled.  By changing the project settings and
+ * undefining this macro size checking is eliminated and the functions
+ * run a bit faster.  With size checking disabled the functions always
+ * return <code>ARM_MATH_SUCCESS</code>.
+ */
+
+/**
+ * @defgroup groupTransforms Transform Functions
+ */
+
+/**
+ * @defgroup groupController Controller Functions
+ */
+
+/**
+ * @defgroup groupStats Statistics Functions
+ */
+/**
+ * @defgroup groupSupport Support Functions
+ */
+
+/**
+ * @defgroup groupInterpolation Interpolation Functions
+ * These functions perform 1- and 2-dimensional interpolation of data.
+ * Linear interpolation is used for 1-dimensional data and
+ * bilinear interpolation is used for 2-dimensional data.
+ */
+
+/**
+ * @defgroup groupExamples Examples
+ */
+#ifndef _ARM_MATH_H
+#define _ARM_MATH_H
+
+// Teensy 3.0
+#include <stdint.h>
+#define __ASM		__asm
+#define __INLINE	inline
+#define __STATIC_INLINE	static inline
+#define __CORTEX_M	4
+#define __FPU_USED	0
+#define ARM_MATH_CM4
+#include "core_cmInstr.h"
+#include "core_cm4_simd.h"
+
+
+#if 0
+// generic for any board...
+#define __CMSIS_GENERIC         /* disable NVIC and Systick functions */
+#if defined (ARM_MATH_CM4)
+#include "core_cm4.h"
+#elif defined (ARM_MATH_CM3)
+#include "core_cm3.h"
+#elif defined (ARM_MATH_CM0)
+#include "core_cm0.h"
+#else
+#include "ARMCM4.h"
+#warning "Define either ARM_MATH_CM4 OR ARM_MATH_CM3...By Default building on ARM_MATH_CM4....."
+#endif
+#undef  __CMSIS_GENERIC         /* enable NVIC and Systick functions */
+#endif
+
+#include "string.h"
+#include "math.h"
+#ifdef	__cplusplus
+extern "C"
+{
+#endif
+
+
+  /**
+   * @brief Macros required for reciprocal calculation in Normalized LMS
+   */
+
+#define DELTA_Q31 			(0x100)
+#define DELTA_Q15 			0x5
+#define INDEX_MASK 			0x0000003F
+#ifndef PI
+#define PI					3.14159265358979f
+#endif
+
+  /**
+   * @brief Macros required for SINE and COSINE Fast math approximations
+   */
+
+#define TABLE_SIZE			256
+#define TABLE_SPACING_Q31	0x800000
+#define TABLE_SPACING_Q15	0x80
+
+  /**
+   * @brief Macros required for SINE and COSINE Controller functions
+   */
+  /* 1.31(q31) Fixed value of 2/360 */
+  /* -1 to +1 is divided into 360 values so total spacing is (2/360) */
+#define INPUT_SPACING			0xB60B61
+
+  /**
+   * @brief Macro for Unaligned Support
+   */
+#ifndef UNALIGNED_SUPPORT_DISABLE
+    #define ALIGN4
+#else
+  #if defined  (__GNUC__)
+    #define ALIGN4 __attribute__((aligned(4)))
+  #else
+    #define ALIGN4 __align(4)
+  #endif
+#endif	/*	#ifndef UNALIGNED_SUPPORT_DISABLE	*/
+
+  /**
+   * @brief Error status returned by some functions in the library.
+   */
+
+  typedef enum
+  {
+    ARM_MATH_SUCCESS = 0,                /**< No error */
+    ARM_MATH_ARGUMENT_ERROR = -1,        /**< One or more arguments are incorrect */
+    ARM_MATH_LENGTH_ERROR = -2,          /**< Length of data buffer is incorrect */
+    ARM_MATH_SIZE_MISMATCH = -3,         /**< Size of matrices is not compatible with the operation. */
+    ARM_MATH_NANINF = -4,                /**< Not-a-number (NaN) or infinity is generated */
+    ARM_MATH_SINGULAR = -5,              /**< Generated by matrix inversion if the input matrix is singular and cannot be inverted. */
+    ARM_MATH_TEST_FAILURE = -6           /**< Test Failed  */
+  } arm_status;
+
+  /**
+   * @brief 8-bit fractional data type in 1.7 format.
+   */
+  typedef int8_t q7_t;
+
+  /**
+   * @brief 16-bit fractional data type in 1.15 format.
+   */
+  typedef int16_t q15_t;
+
+  /**
+   * @brief 32-bit fractional data type in 1.31 format.
+   */
+  typedef int32_t q31_t;
+
+  /**
+   * @brief 64-bit fractional data type in 1.63 format.
+   */
+  typedef int64_t q63_t;
+
+  /**
+   * @brief 32-bit floating-point type definition.
+   */
+  typedef float float32_t;
+
+  /**
+   * @brief 64-bit floating-point type definition.
+   */
+  typedef double float64_t;
+
+  /**
+   * @brief definition to read/write two 16 bit values.
+   */
+#if defined  (__GNUC__)
+  #define __SIMD32(addr)         (*( int32_t **) & (addr))
+  #define  _SIMD32_OFFSET(addr)  (*( int32_t * )   (addr))
+#else
+  #define __SIMD32(addr)         (*(__packed                    int32_t **) & (addr))
+  #define  _SIMD32_OFFSET(addr)  (*(__packed                    int32_t * )   (addr))
+#endif 
+
+  #define __SIMD64(addr)  (*(int64_t **) & (addr))
+
+#if defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0)
+  /**
+   * @brief definition to pack two 16 bit values.
+   */
+#define __PKHBT(ARG1, ARG2, ARG3)      ( (((int32_t)(ARG1) <<  0) & (int32_t)0x0000FFFF) | \
+                                         (((int32_t)(ARG2) << ARG3) & (int32_t)0xFFFF0000)  )
+#define __PKHTB(ARG1, ARG2, ARG3)      ( (((int32_t)(ARG1) <<  0) & (int32_t)0xFFFF0000) | \
+                                         (((int32_t)(ARG2) >> ARG3) & (int32_t)0x0000FFFF)  )
+
+#endif
+
+
+   /**
+   * @brief definition to pack four 8 bit values.
+   */
+#ifndef ARM_MATH_BIG_ENDIAN
+
+#define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v0) <<  0) & (int32_t)0x000000FF) |	\
+                                (((int32_t)(v1) <<  8) & (int32_t)0x0000FF00) |	\
+							    (((int32_t)(v2) << 16) & (int32_t)0x00FF0000) |	\
+							    (((int32_t)(v3) << 24) & (int32_t)0xFF000000)  )
+#else
+
+#define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v3) <<  0) & (int32_t)0x000000FF) |	\
+                                (((int32_t)(v2) <<  8) & (int32_t)0x0000FF00) |	\
+							    (((int32_t)(v1) << 16) & (int32_t)0x00FF0000) |	\
+							    (((int32_t)(v0) << 24) & (int32_t)0xFF000000)  )
+
+#endif
+
+
+  /**
+   * @brief Clips Q63 to Q31 values.
+   */
+  __STATIC_INLINE q31_t clip_q63_to_q31(
+  q63_t x)
+  {
+    return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ?
+      ((0x7FFFFFFF ^ ((q31_t) (x >> 63)))) : (q31_t) x;
+  }
+
+  /**
+   * @brief Clips Q63 to Q15 values.
+   */
+  __STATIC_INLINE q15_t clip_q63_to_q15(
+  q63_t x)
+  {
+    return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ?
+      ((0x7FFF ^ ((q15_t) (x >> 63)))) : (q15_t) (x >> 15);
+  }
+
+  /**
+   * @brief Clips Q31 to Q7 values.
+   */
+  __STATIC_INLINE q7_t clip_q31_to_q7(
+  q31_t x)
+  {
+    return ((q31_t) (x >> 24) != ((q31_t) x >> 23)) ?
+      ((0x7F ^ ((q7_t) (x >> 31)))) : (q7_t) x;
+  }
+
+  /**
+   * @brief Clips Q31 to Q15 values.
+   */
+  __STATIC_INLINE q15_t clip_q31_to_q15(
+  q31_t x)
+  {
+    return ((q31_t) (x >> 16) != ((q31_t) x >> 15)) ?
+      ((0x7FFF ^ ((q15_t) (x >> 31)))) : (q15_t) x;
+  }
+
+  /**
+   * @brief Multiplies 32 X 64 and returns 32 bit result in 2.30 format.
+   */
+
+  __STATIC_INLINE q63_t mult32x64(
+  q63_t x,
+  q31_t y)
+  {
+    return ((((q63_t) (x & 0x00000000FFFFFFFF) * y) >> 32) +
+            (((q63_t) (x >> 32) * y)));
+  }
+
+
+#if defined (ARM_MATH_CM0) && defined ( __CC_ARM   )
+#define __CLZ __clz
+#endif
+
+#if defined (ARM_MATH_CM0) && defined ( __TASKING__ )
+/* No need to redefine __CLZ */
+#endif
+
+#if defined (ARM_MATH_CM0) && ((defined (__ICCARM__)) ||(defined (__GNUC__)) )
+
+  __STATIC_INLINE  uint32_t __CLZ(q31_t data);
+
+
+  __STATIC_INLINE uint32_t __CLZ(q31_t data)
+  {
+    uint32_t count = 0;
+    uint32_t mask = 0x80000000;
+
+    while((data & mask) == 0)
+    {
+      count += 1u;
+      mask = mask >> 1u;
+    }
+
+    return (count);
+
+  }
+
+#endif
+
+  /**
+   * @brief Function to Calculates 1/in(reciprocal) value of Q31 Data type.
+   */
+
+  __STATIC_INLINE uint32_t arm_recip_q31(
+  q31_t in,
+  q31_t * dst,
+  q31_t * pRecipTable)
+  {
+
+    uint32_t out, tempVal;
+    uint32_t index, i;
+    uint32_t signBits;
+
+    if(in > 0)
+    {
+      signBits = __CLZ(in) - 1;
+    }
+    else
+    {
+      signBits = __CLZ(-in) - 1;
+    }
+
+    /* Convert input sample to 1.31 format */
+    in = in << signBits;
+
+    /* calculation of index for initial approximated Val */
+    index = (uint32_t) (in >> 24u);
+    index = (index & INDEX_MASK);
+
+    /* 1.31 with exp 1 */
+    out = pRecipTable[index];
+
+    /* calculation of reciprocal value */
+    /* running approximation for two iterations */
+    for (i = 0u; i < 2u; i++)
+    {
+      tempVal = (q31_t) (((q63_t) in * out) >> 31u);
+      tempVal = 0x7FFFFFFF - tempVal;
+      /*      1.31 with exp 1 */
+      //out = (q31_t) (((q63_t) out * tempVal) >> 30u);
+      out = (q31_t) clip_q63_to_q31(((q63_t) out * tempVal) >> 30u);
+    }
+
+    /* write output */
+    *dst = out;
+
+    /* return num of signbits of out = 1/in value */
+    return (signBits + 1u);
+
+  }
+
+  /**
+   * @brief Function to Calculates 1/in(reciprocal) value of Q15 Data type.
+   */
+  __STATIC_INLINE uint32_t arm_recip_q15(
+  q15_t in,
+  q15_t * dst,
+  q15_t * pRecipTable)
+  {
+
+    uint32_t out = 0, tempVal = 0;
+    uint32_t index = 0, i = 0;
+    uint32_t signBits = 0;
+
+    if(in > 0)
+    {
+      signBits = __CLZ(in) - 17;
+    }
+    else
+    {
+      signBits = __CLZ(-in) - 17;
+    }
+
+    /* Convert input sample to 1.15 format */
+    in = in << signBits;
+
+    /* calculation of index for initial approximated Val */
+    index = in >> 8;
+    index = (index & INDEX_MASK);
+
+    /*      1.15 with exp 1  */
+    out = pRecipTable[index];
+
+    /* calculation of reciprocal value */
+    /* running approximation for two iterations */
+    for (i = 0; i < 2; i++)
+    {
+      tempVal = (q15_t) (((q31_t) in * out) >> 15);
+      tempVal = 0x7FFF - tempVal;
+      /*      1.15 with exp 1 */
+      out = (q15_t) (((q31_t) out * tempVal) >> 14);
+    }
+
+    /* write output */
+    *dst = out;
+
+    /* return num of signbits of out = 1/in value */
+    return (signBits + 1);
+
+  }
+
+
+  /*
+   * @brief C custom defined intrinisic function for only M0 processors
+   */
+#if defined(ARM_MATH_CM0)
+
+  __STATIC_INLINE q31_t __SSAT(
+  q31_t x,
+  uint32_t y)
+  {
+    int32_t posMax, negMin;
+    uint32_t i;
+
+    posMax = 1;
+    for (i = 0; i < (y - 1); i++)
+    {
+      posMax = posMax * 2;
+    }
+
+    if(x > 0)
+    {
+      posMax = (posMax - 1);
+
+      if(x > posMax)
+      {
+        x = posMax;
+      }
+    }
+    else
+    {
+      negMin = -posMax;
+
+      if(x < negMin)
+      {
+        x = negMin;
+      }
+    }
+    return (x);
+
+
+  }
+
+#endif /* end of ARM_MATH_CM0 */
+
+
+
+  /*
+   * @brief C custom defined intrinsic function for M3 and M0 processors
+   */
+#if defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0)
+
+  /*
+   * @brief C custom defined QADD8 for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __QADD8(
+  q31_t x,
+  q31_t y)
+  {
+
+    q31_t sum;
+    q7_t r, s, t, u;
+
+    r = (q7_t) x;
+    s = (q7_t) y;
+
+    r = __SSAT((q31_t) (r + s), 8);
+    s = __SSAT(((q31_t) (((x << 16) >> 24) + ((y << 16) >> 24))), 8);
+    t = __SSAT(((q31_t) (((x << 8) >> 24) + ((y << 8) >> 24))), 8);
+    u = __SSAT(((q31_t) ((x >> 24) + (y >> 24))), 8);
+
+    sum =
+      (((q31_t) u << 24) & 0xFF000000) | (((q31_t) t << 16) & 0x00FF0000) |
+      (((q31_t) s << 8) & 0x0000FF00) | (r & 0x000000FF);
+
+    return sum;
+
+  }
+
+  /*
+   * @brief C custom defined QSUB8 for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __QSUB8(
+  q31_t x,
+  q31_t y)
+  {
+
+    q31_t sum;
+    q31_t r, s, t, u;
+
+    r = (q7_t) x;
+    s = (q7_t) y;
+
+    r = __SSAT((r - s), 8);
+    s = __SSAT(((q31_t) (((x << 16) >> 24) - ((y << 16) >> 24))), 8) << 8;
+    t = __SSAT(((q31_t) (((x << 8) >> 24) - ((y << 8) >> 24))), 8) << 16;
+    u = __SSAT(((q31_t) ((x >> 24) - (y >> 24))), 8) << 24;
+
+    sum =
+      (u & 0xFF000000) | (t & 0x00FF0000) | (s & 0x0000FF00) | (r &
+                                                                0x000000FF);
+
+    return sum;
+  }
+
+  /*
+   * @brief C custom defined QADD16 for M3 and M0 processors
+   */
+
+  /*
+   * @brief C custom defined QADD16 for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __QADD16(
+  q31_t x,
+  q31_t y)
+  {
+
+    q31_t sum;
+    q31_t r, s;
+
+    r = (short) x;
+    s = (short) y;
+
+    r = __SSAT(r + s, 16);
+    s = __SSAT(((q31_t) ((x >> 16) + (y >> 16))), 16) << 16;
+
+    sum = (s & 0xFFFF0000) | (r & 0x0000FFFF);
+
+    return sum;
+
+  }
+
+  /*
+   * @brief C custom defined SHADD16 for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __SHADD16(
+  q31_t x,
+  q31_t y)
+  {
+
+    q31_t sum;
+    q31_t r, s;
+
+    r = (short) x;
+    s = (short) y;
+
+    r = ((r >> 1) + (s >> 1));
+    s = ((q31_t) ((x >> 17) + (y >> 17))) << 16;
+
+    sum = (s & 0xFFFF0000) | (r & 0x0000FFFF);
+
+    return sum;
+
+  }
+
+  /*
+   * @brief C custom defined QSUB16 for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __QSUB16(
+  q31_t x,
+  q31_t y)
+  {
+
+    q31_t sum;
+    q31_t r, s;
+
+    r = (short) x;
+    s = (short) y;
+
+    r = __SSAT(r - s, 16);
+    s = __SSAT(((q31_t) ((x >> 16) - (y >> 16))), 16) << 16;
+
+    sum = (s & 0xFFFF0000) | (r & 0x0000FFFF);
+
+    return sum;
+  }
+
+  /*
+   * @brief C custom defined SHSUB16 for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __SHSUB16(
+  q31_t x,
+  q31_t y)
+  {
+
+    q31_t diff;
+    q31_t r, s;
+
+    r = (short) x;
+    s = (short) y;
+
+    r = ((r >> 1) - (s >> 1));
+    s = (((x >> 17) - (y >> 17)) << 16);
+
+    diff = (s & 0xFFFF0000) | (r & 0x0000FFFF);
+
+    return diff;
+  }
+
+  /*
+   * @brief C custom defined QASX for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __QASX(
+  q31_t x,
+  q31_t y)
+  {
+
+    q31_t sum = 0;
+
+    sum =
+      ((sum +
+        clip_q31_to_q15((q31_t) ((short) (x >> 16) + (short) y))) << 16) +
+      clip_q31_to_q15((q31_t) ((short) x - (short) (y >> 16)));
+
+    return sum;
+  }
+
+  /*
+   * @brief C custom defined SHASX for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __SHASX(
+  q31_t x,
+  q31_t y)
+  {
+
+    q31_t sum;
+    q31_t r, s;
+
+    r = (short) x;
+    s = (short) y;
+
+    r = ((r >> 1) - (y >> 17));
+    s = (((x >> 17) + (s >> 1)) << 16);
+
+    sum = (s & 0xFFFF0000) | (r & 0x0000FFFF);
+
+    return sum;
+  }
+
+
+  /*
+   * @brief C custom defined QSAX for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __QSAX(
+  q31_t x,
+  q31_t y)
+  {
+
+    q31_t sum = 0;
+
+    sum =
+      ((sum +
+        clip_q31_to_q15((q31_t) ((short) (x >> 16) - (short) y))) << 16) +
+      clip_q31_to_q15((q31_t) ((short) x + (short) (y >> 16)));
+
+    return sum;
+  }
+
+  /*
+   * @brief C custom defined SHSAX for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __SHSAX(
+  q31_t x,
+  q31_t y)
+  {
+
+    q31_t sum;
+    q31_t r, s;
+
+    r = (short) x;
+    s = (short) y;
+
+    r = ((r >> 1) + (y >> 17));
+    s = (((x >> 17) - (s >> 1)) << 16);
+
+    sum = (s & 0xFFFF0000) | (r & 0x0000FFFF);
+
+    return sum;
+  }
+
+  /*
+   * @brief C custom defined SMUSDX for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __SMUSDX(
+  q31_t x,
+  q31_t y)
+  {
+
+    return ((q31_t) (((short) x * (short) (y >> 16)) -
+                     ((short) (x >> 16) * (short) y)));
+  }
+
+  /*
+   * @brief C custom defined SMUADX for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __SMUADX(
+  q31_t x,
+  q31_t y)
+  {
+
+    return ((q31_t) (((short) x * (short) (y >> 16)) +
+                     ((short) (x >> 16) * (short) y)));
+  }
+
+  /*
+   * @brief C custom defined QADD for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __QADD(
+  q31_t x,
+  q31_t y)
+  {
+    return clip_q63_to_q31((q63_t) x + y);
+  }
+
+  /*
+   * @brief C custom defined QSUB for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __QSUB(
+  q31_t x,
+  q31_t y)
+  {
+    return clip_q63_to_q31((q63_t) x - y);
+  }
+
+  /*
+   * @brief C custom defined SMLAD for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __SMLAD(
+  q31_t x,
+  q31_t y,
+  q31_t sum)
+  {
+
+    return (sum + ((short) (x >> 16) * (short) (y >> 16)) +
+            ((short) x * (short) y));
+  }
+
+  /*
+   * @brief C custom defined SMLADX for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __SMLADX(
+  q31_t x,
+  q31_t y,
+  q31_t sum)
+  {
+
+    return (sum + ((short) (x >> 16) * (short) (y)) +
+            ((short) x * (short) (y >> 16)));
+  }
+
+  /*
+   * @brief C custom defined SMLSDX for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __SMLSDX(
+  q31_t x,
+  q31_t y,
+  q31_t sum)
+  {
+
+    return (sum - ((short) (x >> 16) * (short) (y)) +
+            ((short) x * (short) (y >> 16)));
+  }
+
+  /*
+   * @brief C custom defined SMLALD for M3 and M0 processors
+   */
+  __STATIC_INLINE q63_t __SMLALD(
+  q31_t x,
+  q31_t y,
+  q63_t sum)
+  {
+
+    return (sum + ((short) (x >> 16) * (short) (y >> 16)) +
+            ((short) x * (short) y));
+  }
+
+  /*
+   * @brief C custom defined SMLALDX for M3 and M0 processors
+   */
+  __STATIC_INLINE q63_t __SMLALDX(
+  q31_t x,
+  q31_t y,
+  q63_t sum)
+  {
+
+    return (sum + ((short) (x >> 16) * (short) y)) +
+      ((short) x * (short) (y >> 16));
+  }
+
+  /*
+   * @brief C custom defined SMUAD for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __SMUAD(
+  q31_t x,
+  q31_t y)
+  {
+
+    return (((x >> 16) * (y >> 16)) +
+            (((x << 16) >> 16) * ((y << 16) >> 16)));
+  }
+
+  /*
+   * @brief C custom defined SMUSD for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __SMUSD(
+  q31_t x,
+  q31_t y)
+  {
+
+    return (-((x >> 16) * (y >> 16)) +
+            (((x << 16) >> 16) * ((y << 16) >> 16)));
+  }
+
+
+  /*
+   * @brief C custom defined SXTB16 for M3 and M0 processors
+   */
+  __STATIC_INLINE q31_t __SXTB16(
+  q31_t x)
+  {
+
+    return ((((x << 24) >> 24) & 0x0000FFFF) |
+            (((x << 8) >> 8) & 0xFFFF0000));
+  }
+
+
+#endif /* defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0) */
+
+
+  /**
+   * @brief Instance structure for the Q7 FIR filter.
+   */
+  typedef struct
+  {
+    uint16_t numTaps;        /**< number of filter coefficients in the filter. */
+    q7_t *pState;            /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
+    q7_t *pCoeffs;           /**< points to the coefficient array. The array is of length numTaps.*/
+  } arm_fir_instance_q7;
+
+  /**
+   * @brief Instance structure for the Q15 FIR filter.
+   */
+  typedef struct
+  {
+    uint16_t numTaps;         /**< number of filter coefficients in the filter. */
+    q15_t *pState;            /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
+    q15_t *pCoeffs;           /**< points to the coefficient array. The array is of length numTaps.*/
+  } arm_fir_instance_q15;
+
+  /**
+   * @brief Instance structure for the Q31 FIR filter.
+   */
+  typedef struct
+  {
+    uint16_t numTaps;         /**< number of filter coefficients in the filter. */
+    q31_t *pState;            /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
+    q31_t *pCoeffs;           /**< points to the coefficient array. The array is of length numTaps. */
+  } arm_fir_instance_q31;
+
+  /**
+   * @brief Instance structure for the floating-point FIR filter.
+   */
+  typedef struct
+  {
+    uint16_t numTaps;     /**< number of filter coefficients in the filter. */
+    float32_t *pState;    /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
+    float32_t *pCoeffs;   /**< points to the coefficient array. The array is of length numTaps. */
+  } arm_fir_instance_f32;
+
+
+  /**
+   * @brief Processing function for the Q7 FIR filter.
+   * @param[in] *S points to an instance of the Q7 FIR filter structure.
+   * @param[in] *pSrc points to the block of input data.
+   * @param[out] *pDst points to the block of output data.
+   * @param[in] blockSize number of samples to process.
+   * @return none.
+   */
+  void arm_fir_q7(
+  const arm_fir_instance_q7 * S,
+  q7_t * pSrc,
+  q7_t * pDst,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief  Initialization function for the Q7 FIR filter.
+   * @param[in,out] *S points to an instance of the Q7 FIR structure.
+   * @param[in] numTaps  Number of filter coefficients in the filter.
+   * @param[in] *pCoeffs points to the filter coefficients.
+   * @param[in] *pState points to the state buffer.
+   * @param[in] blockSize number of samples that are processed.
+   * @return none
+   */
+  void arm_fir_init_q7(
+  arm_fir_instance_q7 * S,
+  uint16_t numTaps,
+  q7_t * pCoeffs,
+  q7_t * pState,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief Processing function for the Q15 FIR filter.
+   * @param[in] *S points to an instance of the Q15 FIR structure.
+   * @param[in] *pSrc points to the block of input data.
+   * @param[out] *pDst points to the block of output data.
+   * @param[in] blockSize number of samples to process.
+   * @return none.
+   */
+  void arm_fir_q15(
+  const arm_fir_instance_q15 * S,
+  q15_t * pSrc,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Processing function for the fast Q15 FIR filter for Cortex-M3 and Cortex-M4.
+   * @param[in] *S points to an instance of the Q15 FIR filter structure.
+   * @param[in] *pSrc points to the block of input data.
+   * @param[out] *pDst points to the block of output data.
+   * @param[in] blockSize number of samples to process.
+   * @return none.
+   */
+  void arm_fir_fast_q15(
+  const arm_fir_instance_q15 * S,
+  q15_t * pSrc,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Initialization function for the Q15 FIR filter.
+   * @param[in,out] *S points to an instance of the Q15 FIR filter structure.
+   * @param[in] numTaps  Number of filter coefficients in the filter. Must be even and greater than or equal to 4.
+   * @param[in] *pCoeffs points to the filter coefficients.
+   * @param[in] *pState points to the state buffer.
+   * @param[in] blockSize number of samples that are processed at a time.
+   * @return The function returns ARM_MATH_SUCCESS if initialization was successful or ARM_MATH_ARGUMENT_ERROR if
+   * <code>numTaps</code> is not a supported value.
+   */
+
+  arm_status arm_fir_init_q15(
+  arm_fir_instance_q15 * S,
+  uint16_t numTaps,
+  q15_t * pCoeffs,
+  q15_t * pState,
+  uint32_t blockSize);
+
+  /**
+   * @brief Processing function for the Q31 FIR filter.
+   * @param[in] *S points to an instance of the Q31 FIR filter structure.
+   * @param[in] *pSrc points to the block of input data.
+   * @param[out] *pDst points to the block of output data.
+   * @param[in] blockSize number of samples to process.
+   * @return none.
+   */
+  void arm_fir_q31(
+  const arm_fir_instance_q31 * S,
+  q31_t * pSrc,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Processing function for the fast Q31 FIR filter for Cortex-M3 and Cortex-M4.
+   * @param[in] *S points to an instance of the Q31 FIR structure.
+   * @param[in] *pSrc points to the block of input data.
+   * @param[out] *pDst points to the block of output data.
+   * @param[in] blockSize number of samples to process.
+   * @return none.
+   */
+  void arm_fir_fast_q31(
+  const arm_fir_instance_q31 * S,
+  q31_t * pSrc,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Initialization function for the Q31 FIR filter.
+   * @param[in,out] *S points to an instance of the Q31 FIR structure.
+   * @param[in] 	numTaps  Number of filter coefficients in the filter.
+   * @param[in] 	*pCoeffs points to the filter coefficients.
+   * @param[in] 	*pState points to the state buffer.
+   * @param[in] 	blockSize number of samples that are processed at a time.
+   * @return 		none.
+   */
+  void arm_fir_init_q31(
+  arm_fir_instance_q31 * S,
+  uint16_t numTaps,
+  q31_t * pCoeffs,
+  q31_t * pState,
+  uint32_t blockSize);
+
+  /**
+   * @brief Processing function for the floating-point FIR filter.
+   * @param[in] *S points to an instance of the floating-point FIR structure.
+   * @param[in] *pSrc points to the block of input data.
+   * @param[out] *pDst points to the block of output data.
+   * @param[in] blockSize number of samples to process.
+   * @return none.
+   */
+  void arm_fir_f32(
+  const arm_fir_instance_f32 * S,
+  float32_t * pSrc,
+  float32_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Initialization function for the floating-point FIR filter.
+   * @param[in,out] *S points to an instance of the floating-point FIR filter structure.
+   * @param[in] 	numTaps  Number of filter coefficients in the filter.
+   * @param[in] 	*pCoeffs points to the filter coefficients.
+   * @param[in] 	*pState points to the state buffer.
+   * @param[in] 	blockSize number of samples that are processed at a time.
+   * @return    	none.
+   */
+  void arm_fir_init_f32(
+  arm_fir_instance_f32 * S,
+  uint16_t numTaps,
+  float32_t * pCoeffs,
+  float32_t * pState,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief Instance structure for the Q15 Biquad cascade filter.
+   */
+  typedef struct
+  {
+    int8_t numStages;         /**< number of 2nd order stages in the filter.  Overall order is 2*numStages. */
+    q15_t *pState;            /**< Points to the array of state coefficients.  The array is of length 4*numStages. */
+    q15_t *pCoeffs;           /**< Points to the array of coefficients.  The array is of length 5*numStages. */
+    int8_t postShift;         /**< Additional shift, in bits, applied to each output sample. */
+
+  } arm_biquad_casd_df1_inst_q15;
+
+
+  /**
+   * @brief Instance structure for the Q31 Biquad cascade filter.
+   */
+  typedef struct
+  {
+    uint32_t numStages;      /**< number of 2nd order stages in the filter.  Overall order is 2*numStages. */
+    q31_t *pState;           /**< Points to the array of state coefficients.  The array is of length 4*numStages. */
+    q31_t *pCoeffs;          /**< Points to the array of coefficients.  The array is of length 5*numStages. */
+    uint8_t postShift;       /**< Additional shift, in bits, applied to each output sample. */
+
+  } arm_biquad_casd_df1_inst_q31;
+
+  /**
+   * @brief Instance structure for the floating-point Biquad cascade filter.
+   */
+  typedef struct
+  {
+    uint32_t numStages;         /**< number of 2nd order stages in the filter.  Overall order is 2*numStages. */
+    float32_t *pState;          /**< Points to the array of state coefficients.  The array is of length 4*numStages. */
+    float32_t *pCoeffs;         /**< Points to the array of coefficients.  The array is of length 5*numStages. */
+
+
+  } arm_biquad_casd_df1_inst_f32;
+
+
+
+  /**
+   * @brief Processing function for the Q15 Biquad cascade filter.
+   * @param[in]  *S points to an instance of the Q15 Biquad cascade structure.
+   * @param[in]  *pSrc points to the block of input data.
+   * @param[out] *pDst points to the block of output data.
+   * @param[in]  blockSize number of samples to process.
+   * @return     none.
+   */
+
+  void arm_biquad_cascade_df1_q15(
+  const arm_biquad_casd_df1_inst_q15 * S,
+  q15_t * pSrc,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Initialization function for the Q15 Biquad cascade filter.
+   * @param[in,out] *S           points to an instance of the Q15 Biquad cascade structure.
+   * @param[in]     numStages    number of 2nd order stages in the filter.
+   * @param[in]     *pCoeffs     points to the filter coefficients.
+   * @param[in]     *pState      points to the state buffer.
+   * @param[in]     postShift    Shift to be applied to the output. Varies according to the coefficients format
+   * @return        none
+   */
+
+  void arm_biquad_cascade_df1_init_q15(
+  arm_biquad_casd_df1_inst_q15 * S,
+  uint8_t numStages,
+  q15_t * pCoeffs,
+  q15_t * pState,
+  int8_t postShift);
+
+
+  /**
+   * @brief Fast but less precise processing function for the Q15 Biquad cascade filter for Cortex-M3 and Cortex-M4.
+   * @param[in]  *S points to an instance of the Q15 Biquad cascade structure.
+   * @param[in]  *pSrc points to the block of input data.
+   * @param[out] *pDst points to the block of output data.
+   * @param[in]  blockSize number of samples to process.
+   * @return     none.
+   */
+
+  void arm_biquad_cascade_df1_fast_q15(
+  const arm_biquad_casd_df1_inst_q15 * S,
+  q15_t * pSrc,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief Processing function for the Q31 Biquad cascade filter
+   * @param[in]  *S         points to an instance of the Q31 Biquad cascade structure.
+   * @param[in]  *pSrc      points to the block of input data.
+   * @param[out] *pDst      points to the block of output data.
+   * @param[in]  blockSize  number of samples to process.
+   * @return     none.
+   */
+
+  void arm_biquad_cascade_df1_q31(
+  const arm_biquad_casd_df1_inst_q31 * S,
+  q31_t * pSrc,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Fast but less precise processing function for the Q31 Biquad cascade filter for Cortex-M3 and Cortex-M4.
+   * @param[in]  *S         points to an instance of the Q31 Biquad cascade structure.
+   * @param[in]  *pSrc      points to the block of input data.
+   * @param[out] *pDst      points to the block of output data.
+   * @param[in]  blockSize  number of samples to process.
+   * @return     none.
+   */
+
+  void arm_biquad_cascade_df1_fast_q31(
+  const arm_biquad_casd_df1_inst_q31 * S,
+  q31_t * pSrc,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Initialization function for the Q31 Biquad cascade filter.
+   * @param[in,out] *S           points to an instance of the Q31 Biquad cascade structure.
+   * @param[in]     numStages      number of 2nd order stages in the filter.
+   * @param[in]     *pCoeffs     points to the filter coefficients.
+   * @param[in]     *pState      points to the state buffer.
+   * @param[in]     postShift    Shift to be applied to the output. Varies according to the coefficients format
+   * @return        none
+   */
+
+  void arm_biquad_cascade_df1_init_q31(
+  arm_biquad_casd_df1_inst_q31 * S,
+  uint8_t numStages,
+  q31_t * pCoeffs,
+  q31_t * pState,
+  int8_t postShift);
+
+  /**
+   * @brief Processing function for the floating-point Biquad cascade filter.
+   * @param[in]  *S         points to an instance of the floating-point Biquad cascade structure.
+   * @param[in]  *pSrc      points to the block of input data.
+   * @param[out] *pDst      points to the block of output data.
+   * @param[in]  blockSize  number of samples to process.
+   * @return     none.
+   */
+
+  void arm_biquad_cascade_df1_f32(
+  const arm_biquad_casd_df1_inst_f32 * S,
+  float32_t * pSrc,
+  float32_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Initialization function for the floating-point Biquad cascade filter.
+   * @param[in,out] *S           points to an instance of the floating-point Biquad cascade structure.
+   * @param[in]     numStages    number of 2nd order stages in the filter.
+   * @param[in]     *pCoeffs     points to the filter coefficients.
+   * @param[in]     *pState      points to the state buffer.
+   * @return        none
+   */
+
+  void arm_biquad_cascade_df1_init_f32(
+  arm_biquad_casd_df1_inst_f32 * S,
+  uint8_t numStages,
+  float32_t * pCoeffs,
+  float32_t * pState);
+
+
+  /**
+   * @brief Instance structure for the floating-point matrix structure.
+   */
+
+  typedef struct
+  {
+    uint16_t numRows;     /**< number of rows of the matrix.     */
+    uint16_t numCols;     /**< number of columns of the matrix.  */
+    float32_t *pData;     /**< points to the data of the matrix. */
+  } arm_matrix_instance_f32;
+
+  /**
+   * @brief Instance structure for the Q15 matrix structure.
+   */
+
+  typedef struct
+  {
+    uint16_t numRows;     /**< number of rows of the matrix.     */
+    uint16_t numCols;     /**< number of columns of the matrix.  */
+    q15_t *pData;         /**< points to the data of the matrix. */
+
+  } arm_matrix_instance_q15;
+
+  /**
+   * @brief Instance structure for the Q31 matrix structure.
+   */
+
+  typedef struct
+  {
+    uint16_t numRows;     /**< number of rows of the matrix.     */
+    uint16_t numCols;     /**< number of columns of the matrix.  */
+    q31_t *pData;         /**< points to the data of the matrix. */
+
+  } arm_matrix_instance_q31;
+
+
+
+  /**
+   * @brief Floating-point matrix addition.
+   * @param[in]       *pSrcA points to the first input matrix structure
+   * @param[in]       *pSrcB points to the second input matrix structure
+   * @param[out]      *pDst points to output matrix structure
+   * @return     The function returns either
+   * <code>ARM_MATH_SIZE_MISMATCH</code> or <code>ARM_MATH_SUCCESS</code> based on the outcome of size checking.
+   */
+
+  arm_status arm_mat_add_f32(
+  const arm_matrix_instance_f32 * pSrcA,
+  const arm_matrix_instance_f32 * pSrcB,
+  arm_matrix_instance_f32 * pDst);
+
+  /**
+   * @brief Q15 matrix addition.
+   * @param[in]       *pSrcA points to the first input matrix structure
+   * @param[in]       *pSrcB points to the second input matrix structure
+   * @param[out]      *pDst points to output matrix structure
+   * @return     The function returns either
+   * <code>ARM_MATH_SIZE_MISMATCH</code> or <code>ARM_MATH_SUCCESS</code> based on the outcome of size checking.
+   */
+
+  arm_status arm_mat_add_q15(
+  const arm_matrix_instance_q15 * pSrcA,
+  const arm_matrix_instance_q15 * pSrcB,
+  arm_matrix_instance_q15 * pDst);
+
+  /**
+   * @brief Q31 matrix addition.
+   * @param[in]       *pSrcA points to the first input matrix structure
+   * @param[in]       *pSrcB points to the second input matrix structure
+   * @param[out]      *pDst points to output matrix structure
+   * @return     The function returns either
+   * <code>ARM_MATH_SIZE_MISMATCH</code> or <code>ARM_MATH_SUCCESS</code> based on the outcome of size checking.
+   */
+
+  arm_status arm_mat_add_q31(
+  const arm_matrix_instance_q31 * pSrcA,
+  const arm_matrix_instance_q31 * pSrcB,
+  arm_matrix_instance_q31 * pDst);
+
+
+  /**
+   * @brief Floating-point matrix transpose.
+   * @param[in]  *pSrc points to the input matrix
+   * @param[out] *pDst points to the output matrix
+   * @return 	The function returns either  <code>ARM_MATH_SIZE_MISMATCH</code>
+   * or <code>ARM_MATH_SUCCESS</code> based on the outcome of size checking.
+   */
+
+  arm_status arm_mat_trans_f32(
+  const arm_matrix_instance_f32 * pSrc,
+  arm_matrix_instance_f32 * pDst);
+
+
+  /**
+   * @brief Q15 matrix transpose.
+   * @param[in]  *pSrc points to the input matrix
+   * @param[out] *pDst points to the output matrix
+   * @return 	The function returns either  <code>ARM_MATH_SIZE_MISMATCH</code>
+   * or <code>ARM_MATH_SUCCESS</code> based on the outcome of size checking.
+   */
+
+  arm_status arm_mat_trans_q15(
+  const arm_matrix_instance_q15 * pSrc,
+  arm_matrix_instance_q15 * pDst);
+
+  /**
+   * @brief Q31 matrix transpose.
+   * @param[in]  *pSrc points to the input matrix
+   * @param[out] *pDst points to the output matrix
+   * @return 	The function returns either  <code>ARM_MATH_SIZE_MISMATCH</code>
+   * or <code>ARM_MATH_SUCCESS</code> based on the outcome of size checking.
+   */
+
+  arm_status arm_mat_trans_q31(
+  const arm_matrix_instance_q31 * pSrc,
+  arm_matrix_instance_q31 * pDst);
+
+
+  /**
+   * @brief Floating-point matrix multiplication
+   * @param[in]       *pSrcA points to the first input matrix structure
+   * @param[in]       *pSrcB points to the second input matrix structure
+   * @param[out]      *pDst points to output matrix structure
+   * @return     The function returns either
+   * <code>ARM_MATH_SIZE_MISMATCH</code> or <code>ARM_MATH_SUCCESS</code> based on the outcome of size checking.
+   */
+
+  arm_status arm_mat_mult_f32(
+  const arm_matrix_instance_f32 * pSrcA,
+  const arm_matrix_instance_f32 * pSrcB,
+  arm_matrix_instance_f32 * pDst);
+
+  /**
+   * @brief Q15 matrix multiplication
+   * @param[in]       *pSrcA points to the first input matrix structure
+   * @param[in]       *pSrcB points to the second input matrix structure
+   * @param[out]      *pDst points to output matrix structure
+   * @return     The function returns either
+   * <code>ARM_MATH_SIZE_MISMATCH</code> or <code>ARM_MATH_SUCCESS</code> based on the outcome of size checking.
+   */
+
+  arm_status arm_mat_mult_q15(
+  const arm_matrix_instance_q15 * pSrcA,
+  const arm_matrix_instance_q15 * pSrcB,
+  arm_matrix_instance_q15 * pDst,
+  q15_t * pState);
+
+  /**
+   * @brief Q15 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4
+   * @param[in]       *pSrcA  points to the first input matrix structure
+   * @param[in]       *pSrcB  points to the second input matrix structure
+   * @param[out]      *pDst   points to output matrix structure
+   * @param[in]		  *pState points to the array for storing intermediate results  
+   * @return     The function returns either
+   * <code>ARM_MATH_SIZE_MISMATCH</code> or <code>ARM_MATH_SUCCESS</code> based on the outcome of size checking.
+   */
+
+  arm_status arm_mat_mult_fast_q15(
+  const arm_matrix_instance_q15 * pSrcA,
+  const arm_matrix_instance_q15 * pSrcB,
+  arm_matrix_instance_q15 * pDst,
+  q15_t * pState);
+
+  /**
+   * @brief Q31 matrix multiplication
+   * @param[in]       *pSrcA points to the first input matrix structure
+   * @param[in]       *pSrcB points to the second input matrix structure
+   * @param[out]      *pDst points to output matrix structure
+   * @return     The function returns either
+   * <code>ARM_MATH_SIZE_MISMATCH</code> or <code>ARM_MATH_SUCCESS</code> based on the outcome of size checking.
+   */
+
+  arm_status arm_mat_mult_q31(
+  const arm_matrix_instance_q31 * pSrcA,
+  const arm_matrix_instance_q31 * pSrcB,
+  arm_matrix_instance_q31 * pDst);
+
+  /**
+   * @brief Q31 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4
+   * @param[in]       *pSrcA points to the first input matrix structure
+   * @param[in]       *pSrcB points to the second input matrix structure
+   * @param[out]      *pDst points to output matrix structure
+   * @return     The function returns either
+   * <code>ARM_MATH_SIZE_MISMATCH</code> or <code>ARM_MATH_SUCCESS</code> based on the outcome of size checking.
+   */
+
+  arm_status arm_mat_mult_fast_q31(
+  const arm_matrix_instance_q31 * pSrcA,
+  const arm_matrix_instance_q31 * pSrcB,
+  arm_matrix_instance_q31 * pDst);
+
+
+  /**
+   * @brief Floating-point matrix subtraction
+   * @param[in]       *pSrcA points to the first input matrix structure
+   * @param[in]       *pSrcB points to the second input matrix structure
+   * @param[out]      *pDst points to output matrix structure
+   * @return     The function returns either
+   * <code>ARM_MATH_SIZE_MISMATCH</code> or <code>ARM_MATH_SUCCESS</code> based on the outcome of size checking.
+   */
+
+  arm_status arm_mat_sub_f32(
+  const arm_matrix_instance_f32 * pSrcA,
+  const arm_matrix_instance_f32 * pSrcB,
+  arm_matrix_instance_f32 * pDst);
+
+  /**
+   * @brief Q15 matrix subtraction
+   * @param[in]       *pSrcA points to the first input matrix structure
+   * @param[in]       *pSrcB points to the second input matrix structure
+   * @param[out]      *pDst points to output matrix structure
+   * @return     The function returns either
+   * <code>ARM_MATH_SIZE_MISMATCH</code> or <code>ARM_MATH_SUCCESS</code> based on the outcome of size checking.
+   */
+
+  arm_status arm_mat_sub_q15(
+  const arm_matrix_instance_q15 * pSrcA,
+  const arm_matrix_instance_q15 * pSrcB,
+  arm_matrix_instance_q15 * pDst);
+
+  /**
+   * @brief Q31 matrix subtraction
+   * @param[in]       *pSrcA points to the first input matrix structure
+   * @param[in]       *pSrcB points to the second input matrix structure
+   * @param[out]      *pDst points to output matrix structure
+   * @return     The function returns either
+   * <code>ARM_MATH_SIZE_MISMATCH</code> or <code>ARM_MATH_SUCCESS</code> based on the outcome of size checking.
+   */
+
+  arm_status arm_mat_sub_q31(
+  const arm_matrix_instance_q31 * pSrcA,
+  const arm_matrix_instance_q31 * pSrcB,
+  arm_matrix_instance_q31 * pDst);
+
+  /**
+   * @brief Floating-point matrix scaling.
+   * @param[in]  *pSrc points to the input matrix
+   * @param[in]  scale scale factor
+   * @param[out] *pDst points to the output matrix
+   * @return     The function returns either
+   * <code>ARM_MATH_SIZE_MISMATCH</code> or <code>ARM_MATH_SUCCESS</code> based on the outcome of size checking.
+   */
+
+  arm_status arm_mat_scale_f32(
+  const arm_matrix_instance_f32 * pSrc,
+  float32_t scale,
+  arm_matrix_instance_f32 * pDst);
+
+  /**
+   * @brief Q15 matrix scaling.
+   * @param[in]       *pSrc points to input matrix
+   * @param[in]       scaleFract fractional portion of the scale factor
+   * @param[in]       shift number of bits to shift the result by
+   * @param[out]      *pDst points to output matrix
+   * @return     The function returns either
+   * <code>ARM_MATH_SIZE_MISMATCH</code> or <code>ARM_MATH_SUCCESS</code> based on the outcome of size checking.
+   */
+
+  arm_status arm_mat_scale_q15(
+  const arm_matrix_instance_q15 * pSrc,
+  q15_t scaleFract,
+  int32_t shift,
+  arm_matrix_instance_q15 * pDst);
+
+  /**
+   * @brief Q31 matrix scaling.
+   * @param[in]       *pSrc points to input matrix
+   * @param[in]       scaleFract fractional portion of the scale factor
+   * @param[in]       shift number of bits to shift the result by
+   * @param[out]      *pDst points to output matrix structure
+   * @return     The function returns either
+   * <code>ARM_MATH_SIZE_MISMATCH</code> or <code>ARM_MATH_SUCCESS</code> based on the outcome of size checking.
+   */
+
+  arm_status arm_mat_scale_q31(
+  const arm_matrix_instance_q31 * pSrc,
+  q31_t scaleFract,
+  int32_t shift,
+  arm_matrix_instance_q31 * pDst);
+
+
+  /**
+   * @brief  Q31 matrix initialization.
+   * @param[in,out] *S             points to an instance of the floating-point matrix structure.
+   * @param[in]     nRows          number of rows in the matrix.
+   * @param[in]     nColumns       number of columns in the matrix.
+   * @param[in]     *pData	       points to the matrix data array.
+   * @return        none
+   */
+
+  void arm_mat_init_q31(
+  arm_matrix_instance_q31 * S,
+  uint16_t nRows,
+  uint16_t nColumns,
+  q31_t * pData);
+
+  /**
+   * @brief  Q15 matrix initialization.
+   * @param[in,out] *S             points to an instance of the floating-point matrix structure.
+   * @param[in]     nRows          number of rows in the matrix.
+   * @param[in]     nColumns       number of columns in the matrix.
+   * @param[in]     *pData	       points to the matrix data array.
+   * @return        none
+   */
+
+  void arm_mat_init_q15(
+  arm_matrix_instance_q15 * S,
+  uint16_t nRows,
+  uint16_t nColumns,
+  q15_t * pData);
+
+  /**
+   * @brief  Floating-point matrix initialization.
+   * @param[in,out] *S             points to an instance of the floating-point matrix structure.
+   * @param[in]     nRows          number of rows in the matrix.
+   * @param[in]     nColumns       number of columns in the matrix.
+   * @param[in]     *pData	       points to the matrix data array.
+   * @return        none
+   */
+
+  void arm_mat_init_f32(
+  arm_matrix_instance_f32 * S,
+  uint16_t nRows,
+  uint16_t nColumns,
+  float32_t * pData);
+
+
+
+  /**
+   * @brief Instance structure for the Q15 PID Control.
+   */
+  typedef struct
+  {
+    q15_t A0;    /**< The derived gain, A0 = Kp + Ki + Kd . */
+#ifdef ARM_MATH_CM0
+    q15_t A1;
+    q15_t A2;
+#else
+    q31_t A1;           /**< The derived gain A1 = -Kp - 2Kd | Kd.*/
+#endif
+    q15_t state[3];       /**< The state array of length 3. */
+    q15_t Kp;           /**< The proportional gain. */
+    q15_t Ki;           /**< The integral gain. */
+    q15_t Kd;           /**< The derivative gain. */
+  } arm_pid_instance_q15;
+
+  /**
+   * @brief Instance structure for the Q31 PID Control.
+   */
+  typedef struct
+  {
+    q31_t A0;            /**< The derived gain, A0 = Kp + Ki + Kd . */
+    q31_t A1;            /**< The derived gain, A1 = -Kp - 2Kd. */
+    q31_t A2;            /**< The derived gain, A2 = Kd . */
+    q31_t state[3];      /**< The state array of length 3. */
+    q31_t Kp;            /**< The proportional gain. */
+    q31_t Ki;            /**< The integral gain. */
+    q31_t Kd;            /**< The derivative gain. */
+
+  } arm_pid_instance_q31;
+
+  /**
+   * @brief Instance structure for the floating-point PID Control.
+   */
+  typedef struct
+  {
+    float32_t A0;          /**< The derived gain, A0 = Kp + Ki + Kd . */
+    float32_t A1;          /**< The derived gain, A1 = -Kp - 2Kd. */
+    float32_t A2;          /**< The derived gain, A2 = Kd . */
+    float32_t state[3];    /**< The state array of length 3. */
+    float32_t Kp;               /**< The proportional gain. */
+    float32_t Ki;               /**< The integral gain. */
+    float32_t Kd;               /**< The derivative gain. */
+  } arm_pid_instance_f32;
+
+
+
+  /**
+   * @brief  Initialization function for the floating-point PID Control.
+   * @param[in,out] *S      points to an instance of the PID structure.
+   * @param[in]     resetStateFlag  flag to reset the state. 0 = no change in state 1 = reset the state.
+   * @return none.
+   */
+  void arm_pid_init_f32(
+  arm_pid_instance_f32 * S,
+  int32_t resetStateFlag);
+
+  /**
+   * @brief  Reset function for the floating-point PID Control.
+   * @param[in,out] *S is an instance of the floating-point PID Control structure
+   * @return none
+   */
+  void arm_pid_reset_f32(
+  arm_pid_instance_f32 * S);
+
+
+  /**
+   * @brief  Initialization function for the Q31 PID Control.
+   * @param[in,out] *S points to an instance of the Q15 PID structure.
+   * @param[in]     resetStateFlag  flag to reset the state. 0 = no change in state 1 = reset the state.
+   * @return none.
+   */
+  void arm_pid_init_q31(
+  arm_pid_instance_q31 * S,
+  int32_t resetStateFlag);
+
+
+  /**
+   * @brief  Reset function for the Q31 PID Control.
+   * @param[in,out] *S points to an instance of the Q31 PID Control structure
+   * @return none
+   */
+
+  void arm_pid_reset_q31(
+  arm_pid_instance_q31 * S);
+
+  /**
+   * @brief  Initialization function for the Q15 PID Control.
+   * @param[in,out] *S points to an instance of the Q15 PID structure.
+   * @param[in] resetStateFlag  flag to reset the state. 0 = no change in state 1 = reset the state.
+   * @return none.
+   */
+  void arm_pid_init_q15(
+  arm_pid_instance_q15 * S,
+  int32_t resetStateFlag);
+
+  /**
+   * @brief  Reset function for the Q15 PID Control.
+   * @param[in,out] *S points to an instance of the q15 PID Control structure
+   * @return none
+   */
+  void arm_pid_reset_q15(
+  arm_pid_instance_q15 * S);
+
+
+  /**
+   * @brief Instance structure for the floating-point Linear Interpolate function.
+   */
+  typedef struct
+  {
+    uint32_t nValues;           /**< nValues */
+    float32_t x1;               /**< x1 */
+    float32_t xSpacing;         /**< xSpacing */
+    float32_t *pYData;          /**< pointer to the table of Y values */
+  } arm_linear_interp_instance_f32;
+
+  /**
+   * @brief Instance structure for the floating-point bilinear interpolation function.
+   */
+
+  typedef struct
+  {
+    uint16_t numRows;   /**< number of rows in the data table. */
+    uint16_t numCols;   /**< number of columns in the data table. */
+    float32_t *pData;   /**< points to the data table. */
+  } arm_bilinear_interp_instance_f32;
+
+   /**
+   * @brief Instance structure for the Q31 bilinear interpolation function.
+   */
+
+  typedef struct
+  {
+    uint16_t numRows;   /**< number of rows in the data table. */
+    uint16_t numCols;   /**< number of columns in the data table. */
+    q31_t *pData;       /**< points to the data table. */
+  } arm_bilinear_interp_instance_q31;
+
+   /**
+   * @brief Instance structure for the Q15 bilinear interpolation function.
+   */
+
+  typedef struct
+  {
+    uint16_t numRows;   /**< number of rows in the data table. */
+    uint16_t numCols;   /**< number of columns in the data table. */
+    q15_t *pData;       /**< points to the data table. */
+  } arm_bilinear_interp_instance_q15;
+
+   /**
+   * @brief Instance structure for the Q15 bilinear interpolation function.
+   */
+
+  typedef struct
+  {
+    uint16_t numRows;   /**< number of rows in the data table. */
+    uint16_t numCols;   /**< number of columns in the data table. */
+    q7_t *pData;                /**< points to the data table. */
+  } arm_bilinear_interp_instance_q7;
+
+
+  /**
+   * @brief Q7 vector multiplication.
+   * @param[in]       *pSrcA points to the first input vector
+   * @param[in]       *pSrcB points to the second input vector
+   * @param[out]      *pDst  points to the output vector
+   * @param[in]       blockSize number of samples in each vector
+   * @return none.
+   */
+
+  void arm_mult_q7(
+  q7_t * pSrcA,
+  q7_t * pSrcB,
+  q7_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Q15 vector multiplication.
+   * @param[in]       *pSrcA points to the first input vector
+   * @param[in]       *pSrcB points to the second input vector
+   * @param[out]      *pDst  points to the output vector
+   * @param[in]       blockSize number of samples in each vector
+   * @return none.
+   */
+
+  void arm_mult_q15(
+  q15_t * pSrcA,
+  q15_t * pSrcB,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Q31 vector multiplication.
+   * @param[in]       *pSrcA points to the first input vector
+   * @param[in]       *pSrcB points to the second input vector
+   * @param[out]      *pDst points to the output vector
+   * @param[in]       blockSize number of samples in each vector
+   * @return none.
+   */
+
+  void arm_mult_q31(
+  q31_t * pSrcA,
+  q31_t * pSrcB,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Floating-point vector multiplication.
+   * @param[in]       *pSrcA points to the first input vector
+   * @param[in]       *pSrcB points to the second input vector
+   * @param[out]      *pDst points to the output vector
+   * @param[in]       blockSize number of samples in each vector
+   * @return none.
+   */
+
+  void arm_mult_f32(
+  float32_t * pSrcA,
+  float32_t * pSrcB,
+  float32_t * pDst,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief Instance structure for the Q15 CFFT/CIFFT function.
+   */
+
+  typedef struct
+  {
+    uint16_t fftLen;                 /**< length of the FFT. */
+    uint8_t ifftFlag;                /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */
+    uint8_t bitReverseFlag;          /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */
+    q15_t *pTwiddle;                 /**< points to the twiddle factor table. */
+    uint16_t *pBitRevTable;          /**< points to the bit reversal table. */
+    uint16_t twidCoefModifier;       /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */
+    uint16_t bitRevFactor;           /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */
+  } arm_cfft_radix4_instance_q15;
+
+  /**
+   * @brief Instance structure for the Q31 CFFT/CIFFT function.
+   */
+
+  typedef struct
+  {
+    uint16_t fftLen;                 /**< length of the FFT. */
+    uint8_t ifftFlag;                /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */
+    uint8_t bitReverseFlag;          /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */
+    q31_t *pTwiddle;                 /**< points to the twiddle factor table. */
+    uint16_t *pBitRevTable;          /**< points to the bit reversal table. */
+    uint16_t twidCoefModifier;       /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */
+    uint16_t bitRevFactor;           /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */
+  } arm_cfft_radix4_instance_q31;
+
+
+  /**
+   * @brief Instance structure for the floating-point CFFT/CIFFT function.
+   */
+
+  typedef struct
+  {
+    uint16_t fftLen;                   /**< length of the FFT. */
+    uint8_t ifftFlag;                  /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */
+    uint8_t bitReverseFlag;            /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */
+    float32_t *pTwiddle;               /**< points to the twiddle factor table. */
+    uint16_t *pBitRevTable;            /**< points to the bit reversal table. */
+    uint16_t twidCoefModifier;         /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */
+    uint16_t bitRevFactor;             /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */
+    float32_t onebyfftLen;                 /**< value of 1/fftLen. */
+  } arm_cfft_radix4_instance_f32;
+
+
+  /**
+   * @brief Instance structure for the Q15 CFFT/CIFFT function.
+   */
+
+  typedef struct
+  {
+    uint16_t fftLen;                 /**< length of the FFT. */
+    uint8_t ifftFlag;                /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */
+    uint8_t bitReverseFlag;          /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */
+    q15_t *pTwiddle;                     /**< points to the Sin twiddle factor table. */
+    uint16_t *pBitRevTable;          /**< points to the bit reversal table. */
+    uint16_t twidCoefModifier;       /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */
+    uint16_t bitRevFactor;           /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */
+  } arm_cfft_radix2_instance_q15;
+
+  /**
+   * @brief Instance structure for the Radix-2 Q31 CFFT/CIFFT function.
+   */
+
+  typedef struct
+  {
+    uint16_t fftLen;                 /**< length of the FFT. */
+    uint8_t ifftFlag;                /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */
+    uint8_t bitReverseFlag;          /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */
+    q31_t *pTwiddle;                     /**< points to the Twiddle factor table. */
+    uint16_t *pBitRevTable;          /**< points to the bit reversal table. */
+    uint16_t twidCoefModifier;       /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */
+    uint16_t bitRevFactor;           /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */
+  } arm_cfft_radix2_instance_q31;
+
+  /**
+   * @brief Instance structure for the floating-point CFFT/CIFFT function.
+   */
+
+  typedef struct
+  {
+    uint16_t fftLen;                   /**< length of the FFT. */
+    uint8_t ifftFlag;                  /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */
+    uint8_t bitReverseFlag;            /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */
+    float32_t *pTwiddle;               /**< points to the Twiddle factor table. */
+    uint16_t *pBitRevTable;            /**< points to the bit reversal table. */
+    uint16_t twidCoefModifier;         /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */
+    uint16_t bitRevFactor;             /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */
+    float32_t onebyfftLen;                 /**< value of 1/fftLen. */
+  } arm_cfft_radix2_instance_f32;
+
+
+  /**
+   * @brief Processing function for the Q15 CFFT/CIFFT.
+   * @param[in]      *S    points to an instance of the Q15 CFFT/CIFFT structure.
+   * @param[in, out] *pSrc points to the complex data buffer. Processing occurs in-place.
+   * @return none.
+   */
+
+  void arm_cfft_radix4_q15(
+  const arm_cfft_radix4_instance_q15 * S,
+  q15_t * pSrc);
+
+  /**
+   * @brief Processing function for the Q15 CFFT/CIFFT.
+   * @param[in]      *S    points to an instance of the Q15 CFFT/CIFFT structure.
+   * @param[in, out] *pSrc points to the complex data buffer. Processing occurs in-place.
+   * @return none.
+   */
+
+  void arm_cfft_radix2_q15(
+  const arm_cfft_radix2_instance_q15 * S,
+  q15_t * pSrc);
+
+  /**
+   * @brief Initialization function for the Q15 CFFT/CIFFT.
+   * @param[in,out] *S             points to an instance of the Q15 CFFT/CIFFT structure.
+   * @param[in]     fftLen         length of the FFT.
+   * @param[in]     ifftFlag       flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform.
+   * @param[in]     bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.
+   * @return        arm_status     function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if <code>fftLen</code> is not a supported value.
+   */
+
+  arm_status arm_cfft_radix4_init_q15(
+  arm_cfft_radix4_instance_q15 * S,
+  uint16_t fftLen,
+  uint8_t ifftFlag,
+  uint8_t bitReverseFlag);
+
+  /**
+   * @brief Initialization function for the Q15 CFFT/CIFFT.
+   * @param[in,out] *S             points to an instance of the Q15 CFFT/CIFFT structure.
+   * @param[in]     fftLen         length of the FFT.
+   * @param[in]     ifftFlag       flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform.
+   * @param[in]     bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.
+   * @return        arm_status     function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if <code>fftLen</code> is not a supported value.
+   */
+
+  arm_status arm_cfft_radix2_init_q15(
+  arm_cfft_radix2_instance_q15 * S,
+  uint16_t fftLen,
+  uint8_t ifftFlag,
+  uint8_t bitReverseFlag);
+
+  /**
+   * @brief Processing function for the Q31 CFFT/CIFFT.
+   * @param[in]      *S    points to an instance of the Q31 CFFT/CIFFT structure.
+   * @param[in, out] *pSrc points to the complex data buffer. Processing occurs in-place.
+   * @return none.
+   */
+
+  void arm_cfft_radix4_q31(
+  const arm_cfft_radix4_instance_q31 * S,
+  q31_t * pSrc);
+
+  /**
+   * @brief  Initialization function for the Q31 CFFT/CIFFT.
+   * @param[in,out] *S             points to an instance of the Q31 CFFT/CIFFT structure.
+   * @param[in]     fftLen         length of the FFT.
+   * @param[in]     ifftFlag       flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform.
+   * @param[in]     bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.
+   * @return        arm_status     function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if <code>fftLen</code> is not a supported value.
+   */
+
+  arm_status arm_cfft_radix4_init_q31(
+  arm_cfft_radix4_instance_q31 * S,
+  uint16_t fftLen,
+  uint8_t ifftFlag,
+  uint8_t bitReverseFlag);
+
+  /**
+   * @brief Processing function for the Radix-2 Q31 CFFT/CIFFT.
+   * @param[in]      *S    points to an instance of the Radix-2 Q31 CFFT/CIFFT structure.
+   * @param[in, out] *pSrc points to the complex data buffer. Processing occurs in-place.
+   * @return none.
+   */
+
+  void arm_cfft_radix2_q31(
+  const arm_cfft_radix2_instance_q31 * S,
+  q31_t * pSrc);
+
+  /**
+   * @brief  Initialization function for the Radix-2 Q31 CFFT/CIFFT.
+   * @param[in,out] *S             points to an instance of the Radix-2 Q31 CFFT/CIFFT structure.
+   * @param[in]     fftLen         length of the FFT.
+   * @param[in]     ifftFlag       flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform.
+   * @param[in]     bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.
+   * @return        arm_status     function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if <code>fftLen</code> is not a supported value.
+   */
+
+  arm_status arm_cfft_radix2_init_q31(
+  arm_cfft_radix2_instance_q31 * S,
+  uint16_t fftLen,
+  uint8_t ifftFlag,
+  uint8_t bitReverseFlag);
+
+
+
+  /**
+   * @brief Processing function for the floating-point CFFT/CIFFT.
+   * @param[in]      *S    points to an instance of the floating-point CFFT/CIFFT structure.
+   * @param[in, out] *pSrc points to the complex data buffer. Processing occurs in-place.
+   * @return none.
+   */
+
+  void arm_cfft_radix2_f32(
+  const arm_cfft_radix2_instance_f32 * S,
+  float32_t * pSrc);
+
+  /**
+   * @brief  Initialization function for the floating-point CFFT/CIFFT.
+   * @param[in,out] *S             points to an instance of the floating-point CFFT/CIFFT structure.
+   * @param[in]     fftLen         length of the FFT.
+   * @param[in]     ifftFlag       flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform.
+   * @param[in]     bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.
+   * @return        The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if <code>fftLen</code> is not a supported value.
+   */
+
+  arm_status arm_cfft_radix2_init_f32(
+  arm_cfft_radix2_instance_f32 * S,
+  uint16_t fftLen,
+  uint8_t ifftFlag,
+  uint8_t bitReverseFlag);
+
+  /**
+   * @brief Processing function for the floating-point CFFT/CIFFT.
+   * @param[in]      *S    points to an instance of the floating-point CFFT/CIFFT structure.
+   * @param[in, out] *pSrc points to the complex data buffer. Processing occurs in-place.
+   * @return none.
+   */
+
+  void arm_cfft_radix4_f32(
+  const arm_cfft_radix4_instance_f32 * S,
+  float32_t * pSrc);
+
+  /**
+   * @brief  Initialization function for the floating-point CFFT/CIFFT.
+   * @param[in,out] *S             points to an instance of the floating-point CFFT/CIFFT structure.
+   * @param[in]     fftLen         length of the FFT.
+   * @param[in]     ifftFlag       flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform.
+   * @param[in]     bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.
+   * @return        The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if <code>fftLen</code> is not a supported value.
+   */
+
+  arm_status arm_cfft_radix4_init_f32(
+  arm_cfft_radix4_instance_f32 * S,
+  uint16_t fftLen,
+  uint8_t ifftFlag,
+  uint8_t bitReverseFlag);
+
+
+
+  /*----------------------------------------------------------------------
+   *		Internal functions prototypes FFT function
+   ----------------------------------------------------------------------*/
+
+  /**
+   * @brief  Core function for the floating-point CFFT butterfly process.
+   * @param[in, out] *pSrc            points to the in-place buffer of floating-point data type.
+   * @param[in]      fftLen           length of the FFT.
+   * @param[in]      *pCoef           points to the twiddle coefficient buffer.
+   * @param[in]      twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
+   * @return none.
+   */
+
+  void arm_radix4_butterfly_f32(
+  float32_t * pSrc,
+  uint16_t fftLen,
+  float32_t * pCoef,
+  uint16_t twidCoefModifier);
+
+  /**
+   * @brief  Core function for the floating-point CIFFT butterfly process.
+   * @param[in, out] *pSrc            points to the in-place buffer of floating-point data type.
+   * @param[in]      fftLen           length of the FFT.
+   * @param[in]      *pCoef           points to twiddle coefficient buffer.
+   * @param[in]      twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
+   * @param[in]      onebyfftLen      value of 1/fftLen.
+   * @return none.
+   */
+
+  void arm_radix4_butterfly_inverse_f32(
+  float32_t * pSrc,
+  uint16_t fftLen,
+  float32_t * pCoef,
+  uint16_t twidCoefModifier,
+  float32_t onebyfftLen);
+
+  /**
+   * @brief  In-place bit reversal function.
+   * @param[in, out] *pSrc        points to the in-place buffer of floating-point data type.
+   * @param[in]      fftSize      length of the FFT.
+   * @param[in]      bitRevFactor bit reversal modifier that supports different size FFTs with the same bit reversal table.
+   * @param[in]      *pBitRevTab  points to the bit reversal table.
+   * @return none.
+   */
+
+  void arm_bitreversal_f32(
+  float32_t * pSrc,
+  uint16_t fftSize,
+  uint16_t bitRevFactor,
+  uint16_t * pBitRevTab);
+
+  /**
+   * @brief  Core function for the Q31 CFFT butterfly process.
+   * @param[in, out] *pSrc            points to the in-place buffer of Q31 data type.
+   * @param[in]      fftLen           length of the FFT.
+   * @param[in]      *pCoef           points to Twiddle coefficient buffer.
+   * @param[in]      twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
+   * @return none.
+   */
+
+  void arm_radix4_butterfly_q31(
+  q31_t * pSrc,
+  uint32_t fftLen,
+  q31_t * pCoef,
+  uint32_t twidCoefModifier);
+
+  /**
+   * @brief  Core function for the f32 FFT butterfly process.
+   * @param[in, out] *pSrc            points to the in-place buffer of f32 data type.
+   * @param[in]      fftLen           length of the FFT.
+   * @param[in]      *pCoef        	  points to Twiddle coefficient buffer.
+   * @param[in]      twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
+   * @return none.
+   */
+
+  void arm_radix2_butterfly_f32(
+  float32_t * pSrc,
+  uint32_t fftLen,
+  float32_t * pCoef,
+  uint16_t twidCoefModifier);
+
+        /**  
+	 * @brief  Core function for the Radix-2 Q31 CFFT butterfly process. 
+	 * @param[in, out] *pSrc            points to the in-place buffer of Q31 data type. 
+	 * @param[in]      fftLen           length of the FFT. 
+	 * @param[in]      *pCoef         	points to Twiddle coefficient buffer.
+	 * @param[in]      twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. 
+	 * @return none. 
+	 */
+
+  void arm_radix2_butterfly_q31(
+  q31_t * pSrc,
+  uint32_t fftLen,
+  q31_t * pCoef,
+  uint16_t twidCoefModifier);
+
+        /**  
+	 * @brief  Core function for the Radix-2 Q15 CFFT butterfly process. 
+	 * @param[in, out] *pSrc            points to the in-place buffer of Q15 data type. 
+	 * @param[in]      fftLen           length of the FFT. 
+	 * @param[in]      *pCoef           points to Twiddle coefficient buffer.
+	 * @param[in]      twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. 
+	 * @return none. 
+	 */
+
+  void arm_radix2_butterfly_q15(
+  q15_t * pSrc,
+  uint32_t fftLen,
+  q15_t * pCoef,
+  uint16_t twidCoefModifier);
+
+        /**  
+	 * @brief  Core function for the Radix-2 Q15 CFFT Inverse butterfly process. 
+	 * @param[in, out] *pSrc            points to the in-place buffer of Q15 data type. 
+	 * @param[in]      fftLen           length of the FFT. 
+	 * @param[in]      *pCoef       	points to Twiddle coefficient buffer.
+	 * @param[in]      twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. 
+	 * @return none. 
+	 */
+
+  void arm_radix2_butterfly_inverse_q15(
+  q15_t * pSrc,
+  uint32_t fftLen,
+  q15_t * pCoef,
+  uint16_t twidCoefModifier);
+
+        /**  
+	 * @brief  Core function for the Radix-2 Q31 CFFT Inverse butterfly process. 
+	 * @param[in, out] *pSrc            points to the in-place buffer of Q31 data type. 
+	 * @param[in]      fftLen           length of the FFT. 
+	 * @param[in]      *pCoef         	points to Twiddle coefficient buffer.
+	 * @param[in]      twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. 
+	 * @return none. 
+	 */
+
+  void arm_radix2_butterfly_inverse_q31(
+  q31_t * pSrc,
+  uint32_t fftLen,
+  q31_t * pCoef,
+  uint16_t twidCoefModifier);
+
+  /**
+   * @brief  Core function for the f32 IFFT butterfly process.
+   * @param[in, out] *pSrc            points to the in-place buffer of f32 data type.
+   * @param[in]      fftLen           length of the FFT.
+   * @param[in]      *pCoef        	  points to Twiddle coefficient buffer.
+   * @param[in]      twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
+   * @param[in]		 onebyfftLen	  1/fftLenfth
+   * @return none.
+   */
+
+  void arm_radix2_butterfly_inverse_f32(
+  float32_t * pSrc,
+  uint32_t fftLen,
+  float32_t * pCoef,
+  uint16_t twidCoefModifier,
+  float32_t onebyfftLen);
+
+                                                                /**
+   * @brief  Core function for the Q31 CIFFT butterfly process.
+   * @param[in, out] *pSrc            points to the in-place buffer of Q31 data type.
+   * @param[in]      fftLen           length of the FFT.
+   * @param[in]      *pCoef           points to twiddle coefficient buffer.
+   * @param[in]      twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
+   * @return none.
+   */
+
+  void arm_radix4_butterfly_inverse_q31(
+  q31_t * pSrc,
+  uint32_t fftLen,
+  q31_t * pCoef,
+  uint32_t twidCoefModifier);
+
+  /**
+   * @brief  In-place bit reversal function.
+   * @param[in, out] *pSrc        points to the in-place buffer of Q31 data type.
+   * @param[in]      fftLen       length of the FFT.
+   * @param[in]      bitRevFactor bit reversal modifier that supports different size FFTs with the same bit reversal table
+   * @param[in]      *pBitRevTab  points to bit reversal table.
+   * @return none.
+   */
+
+  void arm_bitreversal_q31(
+  q31_t * pSrc,
+  uint32_t fftLen,
+  uint16_t bitRevFactor,
+  uint16_t * pBitRevTab);
+
+  /**
+   * @brief  Core function for the Q15 CFFT butterfly process.
+   * @param[in, out] *pSrc16          points to the in-place buffer of Q15 data type.
+   * @param[in]      fftLen           length of the FFT.
+   * @param[in]      *pCoef16         points to twiddle coefficient buffer.
+   * @param[in]      twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
+   * @return none.
+   */
+
+  void arm_radix4_butterfly_q15(
+  q15_t * pSrc16,
+  uint32_t fftLen,
+  q15_t * pCoef16,
+  uint32_t twidCoefModifier);
+
+
+  /**
+   * @brief  Core function for the Q15 CIFFT butterfly process.
+   * @param[in, out] *pSrc16          points to the in-place buffer of Q15 data type.
+   * @param[in]      fftLen           length of the FFT.
+   * @param[in]      *pCoef16         points to twiddle coefficient buffer.
+   * @param[in]      twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
+   * @return none.
+   */
+
+  void arm_radix4_butterfly_inverse_q15(
+  q15_t * pSrc16,
+  uint32_t fftLen,
+  q15_t * pCoef16,
+  uint32_t twidCoefModifier);
+
+  /**
+   * @brief  In-place bit reversal function.
+   * @param[in, out] *pSrc        points to the in-place buffer of Q15 data type.
+   * @param[in]      fftLen       length of the FFT.
+   * @param[in]      bitRevFactor bit reversal modifier that supports different size FFTs with the same bit reversal table
+   * @param[in]      *pBitRevTab  points to bit reversal table.
+   * @return none.
+   */
+
+  void arm_bitreversal_q15(
+  q15_t * pSrc,
+  uint32_t fftLen,
+  uint16_t bitRevFactor,
+  uint16_t * pBitRevTab);
+
+
+  /**
+   * @brief Instance structure for the Q15 RFFT/RIFFT function.
+   */
+
+  typedef struct
+  {
+    uint32_t fftLenReal;                      /**< length of the real FFT. */
+    uint32_t fftLenBy2;                       /**< length of the complex FFT. */
+    uint8_t ifftFlagR;                        /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */
+    uint8_t bitReverseFlagR;                      /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */
+    uint32_t twidCoefRModifier;               /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */
+    q15_t *pTwiddleAReal;                     /**< points to the real twiddle factor table. */
+    q15_t *pTwiddleBReal;                     /**< points to the imag twiddle factor table. */
+    arm_cfft_radix4_instance_q15 *pCfft;          /**< points to the complex FFT instance. */
+  } arm_rfft_instance_q15;
+
+  /**
+   * @brief Instance structure for the Q31 RFFT/RIFFT function.
+   */
+
+  typedef struct
+  {
+    uint32_t fftLenReal;                        /**< length of the real FFT. */
+    uint32_t fftLenBy2;                         /**< length of the complex FFT. */
+    uint8_t ifftFlagR;                          /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */
+    uint8_t bitReverseFlagR;                        /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */
+    uint32_t twidCoefRModifier;                 /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */
+    q31_t *pTwiddleAReal;                       /**< points to the real twiddle factor table. */
+    q31_t *pTwiddleBReal;                       /**< points to the imag twiddle factor table. */
+    arm_cfft_radix4_instance_q31 *pCfft;        /**< points to the complex FFT instance. */
+  } arm_rfft_instance_q31;
+
+  /**
+   * @brief Instance structure for the floating-point RFFT/RIFFT function.
+   */
+
+  typedef struct
+  {
+    uint32_t fftLenReal;                        /**< length of the real FFT. */
+    uint16_t fftLenBy2;                         /**< length of the complex FFT. */
+    uint8_t ifftFlagR;                          /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */
+    uint8_t bitReverseFlagR;                    /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */
+    uint32_t twidCoefRModifier;                     /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */
+    float32_t *pTwiddleAReal;                   /**< points to the real twiddle factor table. */
+    float32_t *pTwiddleBReal;                   /**< points to the imag twiddle factor table. */
+    arm_cfft_radix4_instance_f32 *pCfft;        /**< points to the complex FFT instance. */
+  } arm_rfft_instance_f32;
+
+  /**
+   * @brief Processing function for the Q15 RFFT/RIFFT.
+   * @param[in]  *S    points to an instance of the Q15 RFFT/RIFFT structure.
+   * @param[in]  *pSrc points to the input buffer.
+   * @param[out] *pDst points to the output buffer.
+   * @return none.
+   */
+
+  void arm_rfft_q15(
+  const arm_rfft_instance_q15 * S,
+  q15_t * pSrc,
+  q15_t * pDst);
+
+  /**
+   * @brief  Initialization function for the Q15 RFFT/RIFFT.
+   * @param[in, out] *S             points to an instance of the Q15 RFFT/RIFFT structure.
+   * @param[in]      *S_CFFT        points to an instance of the Q15 CFFT/CIFFT structure.
+   * @param[in]      fftLenReal     length of the FFT.
+   * @param[in]      ifftFlagR      flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform.
+   * @param[in]      bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.
+   * @return		The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if <code>fftLenReal</code> is not a supported value.
+   */
+
+  arm_status arm_rfft_init_q15(
+  arm_rfft_instance_q15 * S,
+  arm_cfft_radix4_instance_q15 * S_CFFT,
+  uint32_t fftLenReal,
+  uint32_t ifftFlagR,
+  uint32_t bitReverseFlag);
+
+  /**
+   * @brief Processing function for the Q31 RFFT/RIFFT.
+   * @param[in]  *S    points to an instance of the Q31 RFFT/RIFFT structure.
+   * @param[in]  *pSrc points to the input buffer.
+   * @param[out] *pDst points to the output buffer.
+   * @return none.
+   */
+
+  void arm_rfft_q31(
+  const arm_rfft_instance_q31 * S,
+  q31_t * pSrc,
+  q31_t * pDst);
+
+  /**
+   * @brief  Initialization function for the Q31 RFFT/RIFFT.
+   * @param[in, out] *S             points to an instance of the Q31 RFFT/RIFFT structure.
+   * @param[in, out] *S_CFFT        points to an instance of the Q31 CFFT/CIFFT structure.
+   * @param[in]      fftLenReal     length of the FFT.
+   * @param[in]      ifftFlagR      flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform.
+   * @param[in]      bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.
+   * @return		The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if <code>fftLenReal</code> is not a supported value.
+   */
+
+  arm_status arm_rfft_init_q31(
+  arm_rfft_instance_q31 * S,
+  arm_cfft_radix4_instance_q31 * S_CFFT,
+  uint32_t fftLenReal,
+  uint32_t ifftFlagR,
+  uint32_t bitReverseFlag);
+
+  /**
+   * @brief  Initialization function for the floating-point RFFT/RIFFT.
+   * @param[in,out] *S             points to an instance of the floating-point RFFT/RIFFT structure.
+   * @param[in,out] *S_CFFT        points to an instance of the floating-point CFFT/CIFFT structure.
+   * @param[in]     fftLenReal     length of the FFT.
+   * @param[in]     ifftFlagR      flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform.
+   * @param[in]     bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.
+   * @return		The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if <code>fftLenReal</code> is not a supported value.
+   */
+
+  arm_status arm_rfft_init_f32(
+  arm_rfft_instance_f32 * S,
+  arm_cfft_radix4_instance_f32 * S_CFFT,
+  uint32_t fftLenReal,
+  uint32_t ifftFlagR,
+  uint32_t bitReverseFlag);
+
+  /**
+   * @brief Processing function for the floating-point RFFT/RIFFT.
+   * @param[in]  *S    points to an instance of the floating-point RFFT/RIFFT structure.
+   * @param[in]  *pSrc points to the input buffer.
+   * @param[out] *pDst points to the output buffer.
+   * @return none.
+   */
+
+  void arm_rfft_f32(
+  const arm_rfft_instance_f32 * S,
+  float32_t * pSrc,
+  float32_t * pDst);
+
+  /**
+   * @brief Instance structure for the floating-point DCT4/IDCT4 function.
+   */
+
+  typedef struct
+  {
+    uint16_t N;                         /**< length of the DCT4. */
+    uint16_t Nby2;                      /**< half of the length of the DCT4. */
+    float32_t normalize;                /**< normalizing factor. */
+    float32_t *pTwiddle;                /**< points to the twiddle factor table. */
+    float32_t *pCosFactor;              /**< points to the cosFactor table. */
+    arm_rfft_instance_f32 *pRfft;        /**< points to the real FFT instance. */
+    arm_cfft_radix4_instance_f32 *pCfft; /**< points to the complex FFT instance. */
+  } arm_dct4_instance_f32;
+
+  /**
+   * @brief  Initialization function for the floating-point DCT4/IDCT4.
+   * @param[in,out] *S         points to an instance of floating-point DCT4/IDCT4 structure.
+   * @param[in]     *S_RFFT    points to an instance of floating-point RFFT/RIFFT structure.
+   * @param[in]     *S_CFFT    points to an instance of floating-point CFFT/CIFFT structure.
+   * @param[in]     N          length of the DCT4.
+   * @param[in]     Nby2       half of the length of the DCT4.
+   * @param[in]     normalize  normalizing factor.
+   * @return		arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if <code>fftLenReal</code> is not a supported transform length.
+   */
+
+  arm_status arm_dct4_init_f32(
+  arm_dct4_instance_f32 * S,
+  arm_rfft_instance_f32 * S_RFFT,
+  arm_cfft_radix4_instance_f32 * S_CFFT,
+  uint16_t N,
+  uint16_t Nby2,
+  float32_t normalize);
+
+  /**
+   * @brief Processing function for the floating-point DCT4/IDCT4.
+   * @param[in]       *S             points to an instance of the floating-point DCT4/IDCT4 structure.
+   * @param[in]       *pState        points to state buffer.
+   * @param[in,out]   *pInlineBuffer points to the in-place input and output buffer.
+   * @return none.
+   */
+
+  void arm_dct4_f32(
+  const arm_dct4_instance_f32 * S,
+  float32_t * pState,
+  float32_t * pInlineBuffer);
+
+  /**
+   * @brief Instance structure for the Q31 DCT4/IDCT4 function.
+   */
+
+  typedef struct
+  {
+    uint16_t N;                         /**< length of the DCT4. */
+    uint16_t Nby2;                      /**< half of the length of the DCT4. */
+    q31_t normalize;                    /**< normalizing factor. */
+    q31_t *pTwiddle;                    /**< points to the twiddle factor table. */
+    q31_t *pCosFactor;                  /**< points to the cosFactor table. */
+    arm_rfft_instance_q31 *pRfft;        /**< points to the real FFT instance. */
+    arm_cfft_radix4_instance_q31 *pCfft; /**< points to the complex FFT instance. */
+  } arm_dct4_instance_q31;
+
+  /**
+   * @brief  Initialization function for the Q31 DCT4/IDCT4.
+   * @param[in,out] *S         points to an instance of Q31 DCT4/IDCT4 structure.
+   * @param[in]     *S_RFFT    points to an instance of Q31 RFFT/RIFFT structure
+   * @param[in]     *S_CFFT    points to an instance of Q31 CFFT/CIFFT structure
+   * @param[in]     N          length of the DCT4.
+   * @param[in]     Nby2       half of the length of the DCT4.
+   * @param[in]     normalize  normalizing factor.
+   * @return		arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if <code>N</code> is not a supported transform length.
+   */
+
+  arm_status arm_dct4_init_q31(
+  arm_dct4_instance_q31 * S,
+  arm_rfft_instance_q31 * S_RFFT,
+  arm_cfft_radix4_instance_q31 * S_CFFT,
+  uint16_t N,
+  uint16_t Nby2,
+  q31_t normalize);
+
+  /**
+   * @brief Processing function for the Q31 DCT4/IDCT4.
+   * @param[in]       *S             points to an instance of the Q31 DCT4 structure.
+   * @param[in]       *pState        points to state buffer.
+   * @param[in,out]   *pInlineBuffer points to the in-place input and output buffer.
+   * @return none.
+   */
+
+  void arm_dct4_q31(
+  const arm_dct4_instance_q31 * S,
+  q31_t * pState,
+  q31_t * pInlineBuffer);
+
+  /**
+   * @brief Instance structure for the Q15 DCT4/IDCT4 function.
+   */
+
+  typedef struct
+  {
+    uint16_t N;                         /**< length of the DCT4. */
+    uint16_t Nby2;                      /**< half of the length of the DCT4. */
+    q15_t normalize;                    /**< normalizing factor. */
+    q15_t *pTwiddle;                    /**< points to the twiddle factor table. */
+    q15_t *pCosFactor;                  /**< points to the cosFactor table. */
+    arm_rfft_instance_q15 *pRfft;        /**< points to the real FFT instance. */
+    arm_cfft_radix4_instance_q15 *pCfft; /**< points to the complex FFT instance. */
+  } arm_dct4_instance_q15;
+
+  /**
+   * @brief  Initialization function for the Q15 DCT4/IDCT4.
+   * @param[in,out] *S         points to an instance of Q15 DCT4/IDCT4 structure.
+   * @param[in]     *S_RFFT    points to an instance of Q15 RFFT/RIFFT structure.
+   * @param[in]     *S_CFFT    points to an instance of Q15 CFFT/CIFFT structure.
+   * @param[in]     N          length of the DCT4.
+   * @param[in]     Nby2       half of the length of the DCT4.
+   * @param[in]     normalize  normalizing factor.
+   * @return		arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if <code>N</code> is not a supported transform length.
+   */
+
+  arm_status arm_dct4_init_q15(
+  arm_dct4_instance_q15 * S,
+  arm_rfft_instance_q15 * S_RFFT,
+  arm_cfft_radix4_instance_q15 * S_CFFT,
+  uint16_t N,
+  uint16_t Nby2,
+  q15_t normalize);
+
+  /**
+   * @brief Processing function for the Q15 DCT4/IDCT4.
+   * @param[in]       *S             points to an instance of the Q15 DCT4 structure.
+   * @param[in]       *pState        points to state buffer.
+   * @param[in,out]   *pInlineBuffer points to the in-place input and output buffer.
+   * @return none.
+   */
+
+  void arm_dct4_q15(
+  const arm_dct4_instance_q15 * S,
+  q15_t * pState,
+  q15_t * pInlineBuffer);
+
+  /**
+   * @brief Floating-point vector addition.
+   * @param[in]       *pSrcA points to the first input vector
+   * @param[in]       *pSrcB points to the second input vector
+   * @param[out]      *pDst points to the output vector
+   * @param[in]       blockSize number of samples in each vector
+   * @return none.
+   */
+
+  void arm_add_f32(
+  float32_t * pSrcA,
+  float32_t * pSrcB,
+  float32_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Q7 vector addition.
+   * @param[in]       *pSrcA points to the first input vector
+   * @param[in]       *pSrcB points to the second input vector
+   * @param[out]      *pDst points to the output vector
+   * @param[in]       blockSize number of samples in each vector
+   * @return none.
+   */
+
+  void arm_add_q7(
+  q7_t * pSrcA,
+  q7_t * pSrcB,
+  q7_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Q15 vector addition.
+   * @param[in]       *pSrcA points to the first input vector
+   * @param[in]       *pSrcB points to the second input vector
+   * @param[out]      *pDst points to the output vector
+   * @param[in]       blockSize number of samples in each vector
+   * @return none.
+   */
+
+  void arm_add_q15(
+  q15_t * pSrcA,
+  q15_t * pSrcB,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Q31 vector addition.
+   * @param[in]       *pSrcA points to the first input vector
+   * @param[in]       *pSrcB points to the second input vector
+   * @param[out]      *pDst points to the output vector
+   * @param[in]       blockSize number of samples in each vector
+   * @return none.
+   */
+
+  void arm_add_q31(
+  q31_t * pSrcA,
+  q31_t * pSrcB,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Floating-point vector subtraction.
+   * @param[in]       *pSrcA points to the first input vector
+   * @param[in]       *pSrcB points to the second input vector
+   * @param[out]      *pDst points to the output vector
+   * @param[in]       blockSize number of samples in each vector
+   * @return none.
+   */
+
+  void arm_sub_f32(
+  float32_t * pSrcA,
+  float32_t * pSrcB,
+  float32_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Q7 vector subtraction.
+   * @param[in]       *pSrcA points to the first input vector
+   * @param[in]       *pSrcB points to the second input vector
+   * @param[out]      *pDst points to the output vector
+   * @param[in]       blockSize number of samples in each vector
+   * @return none.
+   */
+
+  void arm_sub_q7(
+  q7_t * pSrcA,
+  q7_t * pSrcB,
+  q7_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Q15 vector subtraction.
+   * @param[in]       *pSrcA points to the first input vector
+   * @param[in]       *pSrcB points to the second input vector
+   * @param[out]      *pDst points to the output vector
+   * @param[in]       blockSize number of samples in each vector
+   * @return none.
+   */
+
+  void arm_sub_q15(
+  q15_t * pSrcA,
+  q15_t * pSrcB,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Q31 vector subtraction.
+   * @param[in]       *pSrcA points to the first input vector
+   * @param[in]       *pSrcB points to the second input vector
+   * @param[out]      *pDst points to the output vector
+   * @param[in]       blockSize number of samples in each vector
+   * @return none.
+   */
+
+  void arm_sub_q31(
+  q31_t * pSrcA,
+  q31_t * pSrcB,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Multiplies a floating-point vector by a scalar.
+   * @param[in]       *pSrc points to the input vector
+   * @param[in]       scale scale factor to be applied
+   * @param[out]      *pDst points to the output vector
+   * @param[in]       blockSize number of samples in the vector
+   * @return none.
+   */
+
+  void arm_scale_f32(
+  float32_t * pSrc,
+  float32_t scale,
+  float32_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Multiplies a Q7 vector by a scalar.
+   * @param[in]       *pSrc points to the input vector
+   * @param[in]       scaleFract fractional portion of the scale value
+   * @param[in]       shift number of bits to shift the result by
+   * @param[out]      *pDst points to the output vector
+   * @param[in]       blockSize number of samples in the vector
+   * @return none.
+   */
+
+  void arm_scale_q7(
+  q7_t * pSrc,
+  q7_t scaleFract,
+  int8_t shift,
+  q7_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Multiplies a Q15 vector by a scalar.
+   * @param[in]       *pSrc points to the input vector
+   * @param[in]       scaleFract fractional portion of the scale value
+   * @param[in]       shift number of bits to shift the result by
+   * @param[out]      *pDst points to the output vector
+   * @param[in]       blockSize number of samples in the vector
+   * @return none.
+   */
+
+  void arm_scale_q15(
+  q15_t * pSrc,
+  q15_t scaleFract,
+  int8_t shift,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Multiplies a Q31 vector by a scalar.
+   * @param[in]       *pSrc points to the input vector
+   * @param[in]       scaleFract fractional portion of the scale value
+   * @param[in]       shift number of bits to shift the result by
+   * @param[out]      *pDst points to the output vector
+   * @param[in]       blockSize number of samples in the vector
+   * @return none.
+   */
+
+  void arm_scale_q31(
+  q31_t * pSrc,
+  q31_t scaleFract,
+  int8_t shift,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Q7 vector absolute value.
+   * @param[in]       *pSrc points to the input buffer
+   * @param[out]      *pDst points to the output buffer
+   * @param[in]       blockSize number of samples in each vector
+   * @return none.
+   */
+
+  void arm_abs_q7(
+  q7_t * pSrc,
+  q7_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Floating-point vector absolute value.
+   * @param[in]       *pSrc points to the input buffer
+   * @param[out]      *pDst points to the output buffer
+   * @param[in]       blockSize number of samples in each vector
+   * @return none.
+   */
+
+  void arm_abs_f32(
+  float32_t * pSrc,
+  float32_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Q15 vector absolute value.
+   * @param[in]       *pSrc points to the input buffer
+   * @param[out]      *pDst points to the output buffer
+   * @param[in]       blockSize number of samples in each vector
+   * @return none.
+   */
+
+  void arm_abs_q15(
+  q15_t * pSrc,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Q31 vector absolute value.
+   * @param[in]       *pSrc points to the input buffer
+   * @param[out]      *pDst points to the output buffer
+   * @param[in]       blockSize number of samples in each vector
+   * @return none.
+   */
+
+  void arm_abs_q31(
+  q31_t * pSrc,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Dot product of floating-point vectors.
+   * @param[in]       *pSrcA points to the first input vector
+   * @param[in]       *pSrcB points to the second input vector
+   * @param[in]       blockSize number of samples in each vector
+   * @param[out]      *result output result returned here
+   * @return none.
+   */
+
+  void arm_dot_prod_f32(
+  float32_t * pSrcA,
+  float32_t * pSrcB,
+  uint32_t blockSize,
+  float32_t * result);
+
+  /**
+   * @brief Dot product of Q7 vectors.
+   * @param[in]       *pSrcA points to the first input vector
+   * @param[in]       *pSrcB points to the second input vector
+   * @param[in]       blockSize number of samples in each vector
+   * @param[out]      *result output result returned here
+   * @return none.
+   */
+
+  void arm_dot_prod_q7(
+  q7_t * pSrcA,
+  q7_t * pSrcB,
+  uint32_t blockSize,
+  q31_t * result);
+
+  /**
+   * @brief Dot product of Q15 vectors.
+   * @param[in]       *pSrcA points to the first input vector
+   * @param[in]       *pSrcB points to the second input vector
+   * @param[in]       blockSize number of samples in each vector
+   * @param[out]      *result output result returned here
+   * @return none.
+   */
+
+  void arm_dot_prod_q15(
+  q15_t * pSrcA,
+  q15_t * pSrcB,
+  uint32_t blockSize,
+  q63_t * result);
+
+  /**
+   * @brief Dot product of Q31 vectors.
+   * @param[in]       *pSrcA points to the first input vector
+   * @param[in]       *pSrcB points to the second input vector
+   * @param[in]       blockSize number of samples in each vector
+   * @param[out]      *result output result returned here
+   * @return none.
+   */
+
+  void arm_dot_prod_q31(
+  q31_t * pSrcA,
+  q31_t * pSrcB,
+  uint32_t blockSize,
+  q63_t * result);
+
+  /**
+   * @brief  Shifts the elements of a Q7 vector a specified number of bits.
+   * @param[in]  *pSrc points to the input vector
+   * @param[in]  shiftBits number of bits to shift.  A positive value shifts left; a negative value shifts right.
+   * @param[out]  *pDst points to the output vector
+   * @param[in]  blockSize number of samples in the vector
+   * @return none.
+   */
+
+  void arm_shift_q7(
+  q7_t * pSrc,
+  int8_t shiftBits,
+  q7_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Shifts the elements of a Q15 vector a specified number of bits.
+   * @param[in]  *pSrc points to the input vector
+   * @param[in]  shiftBits number of bits to shift.  A positive value shifts left; a negative value shifts right.
+   * @param[out]  *pDst points to the output vector
+   * @param[in]  blockSize number of samples in the vector
+   * @return none.
+   */
+
+  void arm_shift_q15(
+  q15_t * pSrc,
+  int8_t shiftBits,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Shifts the elements of a Q31 vector a specified number of bits.
+   * @param[in]  *pSrc points to the input vector
+   * @param[in]  shiftBits number of bits to shift.  A positive value shifts left; a negative value shifts right.
+   * @param[out]  *pDst points to the output vector
+   * @param[in]  blockSize number of samples in the vector
+   * @return none.
+   */
+
+  void arm_shift_q31(
+  q31_t * pSrc,
+  int8_t shiftBits,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Adds a constant offset to a floating-point vector.
+   * @param[in]  *pSrc points to the input vector
+   * @param[in]  offset is the offset to be added
+   * @param[out]  *pDst points to the output vector
+   * @param[in]  blockSize number of samples in the vector
+   * @return none.
+   */
+
+  void arm_offset_f32(
+  float32_t * pSrc,
+  float32_t offset,
+  float32_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Adds a constant offset to a Q7 vector.
+   * @param[in]  *pSrc points to the input vector
+   * @param[in]  offset is the offset to be added
+   * @param[out]  *pDst points to the output vector
+   * @param[in]  blockSize number of samples in the vector
+   * @return none.
+   */
+
+  void arm_offset_q7(
+  q7_t * pSrc,
+  q7_t offset,
+  q7_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Adds a constant offset to a Q15 vector.
+   * @param[in]  *pSrc points to the input vector
+   * @param[in]  offset is the offset to be added
+   * @param[out]  *pDst points to the output vector
+   * @param[in]  blockSize number of samples in the vector
+   * @return none.
+   */
+
+  void arm_offset_q15(
+  q15_t * pSrc,
+  q15_t offset,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Adds a constant offset to a Q31 vector.
+   * @param[in]  *pSrc points to the input vector
+   * @param[in]  offset is the offset to be added
+   * @param[out]  *pDst points to the output vector
+   * @param[in]  blockSize number of samples in the vector
+   * @return none.
+   */
+
+  void arm_offset_q31(
+  q31_t * pSrc,
+  q31_t offset,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Negates the elements of a floating-point vector.
+   * @param[in]  *pSrc points to the input vector
+   * @param[out]  *pDst points to the output vector
+   * @param[in]  blockSize number of samples in the vector
+   * @return none.
+   */
+
+  void arm_negate_f32(
+  float32_t * pSrc,
+  float32_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Negates the elements of a Q7 vector.
+   * @param[in]  *pSrc points to the input vector
+   * @param[out]  *pDst points to the output vector
+   * @param[in]  blockSize number of samples in the vector
+   * @return none.
+   */
+
+  void arm_negate_q7(
+  q7_t * pSrc,
+  q7_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Negates the elements of a Q15 vector.
+   * @param[in]  *pSrc points to the input vector
+   * @param[out]  *pDst points to the output vector
+   * @param[in]  blockSize number of samples in the vector
+   * @return none.
+   */
+
+  void arm_negate_q15(
+  q15_t * pSrc,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Negates the elements of a Q31 vector.
+   * @param[in]  *pSrc points to the input vector
+   * @param[out]  *pDst points to the output vector
+   * @param[in]  blockSize number of samples in the vector
+   * @return none.
+   */
+
+  void arm_negate_q31(
+  q31_t * pSrc,
+  q31_t * pDst,
+  uint32_t blockSize);
+  /**
+   * @brief  Copies the elements of a floating-point vector. 
+   * @param[in]  *pSrc input pointer
+   * @param[out]  *pDst output pointer
+   * @param[in]  blockSize number of samples to process
+   * @return none.
+   */
+  void arm_copy_f32(
+  float32_t * pSrc,
+  float32_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Copies the elements of a Q7 vector. 
+   * @param[in]  *pSrc input pointer
+   * @param[out]  *pDst output pointer
+   * @param[in]  blockSize number of samples to process
+   * @return none.
+   */
+  void arm_copy_q7(
+  q7_t * pSrc,
+  q7_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Copies the elements of a Q15 vector. 
+   * @param[in]  *pSrc input pointer
+   * @param[out]  *pDst output pointer
+   * @param[in]  blockSize number of samples to process
+   * @return none.
+   */
+  void arm_copy_q15(
+  q15_t * pSrc,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Copies the elements of a Q31 vector. 
+   * @param[in]  *pSrc input pointer
+   * @param[out]  *pDst output pointer
+   * @param[in]  blockSize number of samples to process
+   * @return none.
+   */
+  void arm_copy_q31(
+  q31_t * pSrc,
+  q31_t * pDst,
+  uint32_t blockSize);
+  /**
+   * @brief  Fills a constant value into a floating-point vector. 
+   * @param[in]  value input value to be filled
+   * @param[out]  *pDst output pointer
+   * @param[in]  blockSize number of samples to process
+   * @return none.
+   */
+  void arm_fill_f32(
+  float32_t value,
+  float32_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Fills a constant value into a Q7 vector. 
+   * @param[in]  value input value to be filled
+   * @param[out]  *pDst output pointer
+   * @param[in]  blockSize number of samples to process
+   * @return none.
+   */
+  void arm_fill_q7(
+  q7_t value,
+  q7_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Fills a constant value into a Q15 vector. 
+   * @param[in]  value input value to be filled
+   * @param[out]  *pDst output pointer
+   * @param[in]  blockSize number of samples to process
+   * @return none.
+   */
+  void arm_fill_q15(
+  q15_t value,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Fills a constant value into a Q31 vector. 
+   * @param[in]  value input value to be filled
+   * @param[out]  *pDst output pointer
+   * @param[in]  blockSize number of samples to process
+   * @return none.
+   */
+  void arm_fill_q31(
+  q31_t value,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+/**  
+ * @brief Convolution of floating-point sequences.  
+ * @param[in] *pSrcA points to the first input sequence.  
+ * @param[in] srcALen length of the first input sequence.  
+ * @param[in] *pSrcB points to the second input sequence.  
+ * @param[in] srcBLen length of the second input sequence.  
+ * @param[out] *pDst points to the location where the output result is written.  Length srcALen+srcBLen-1.  
+ * @return none.  
+ */
+
+  void arm_conv_f32(
+  float32_t * pSrcA,
+  uint32_t srcALen,
+  float32_t * pSrcB,
+  uint32_t srcBLen,
+  float32_t * pDst);
+
+  
+  /**   
+   * @brief Convolution of Q15 sequences.   
+   * @param[in] *pSrcA points to the first input sequence.   
+   * @param[in] srcALen length of the first input sequence.   
+   * @param[in] *pSrcB points to the second input sequence.   
+   * @param[in] srcBLen length of the second input sequence.   
+   * @param[out] *pDst points to the block of output data  Length srcALen+srcBLen-1.   
+   * @param[in]  *pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2.   
+   * @param[in]  *pScratch2 points to scratch buffer of size min(srcALen, srcBLen).   
+   * @return none.   
+   */
+
+
+  void arm_conv_opt_q15(
+  q15_t * pSrcA,
+  uint32_t srcALen,
+  q15_t * pSrcB,
+  uint32_t srcBLen,
+  q15_t * pDst,
+  q15_t * pScratch1,
+  q15_t * pScratch2);
+
+
+/**  
+ * @brief Convolution of Q15 sequences.  
+ * @param[in] *pSrcA points to the first input sequence.  
+ * @param[in] srcALen length of the first input sequence.  
+ * @param[in] *pSrcB points to the second input sequence.  
+ * @param[in] srcBLen length of the second input sequence.  
+ * @param[out] *pDst points to the location where the output result is written.  Length srcALen+srcBLen-1.  
+ * @return none.  
+ */
+
+  void arm_conv_q15(
+  q15_t * pSrcA,
+  uint32_t srcALen,
+  q15_t * pSrcB,
+  uint32_t srcBLen,
+  q15_t * pDst);
+
+  /**
+   * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4
+   * @param[in] *pSrcA points to the first input sequence.
+   * @param[in] srcALen length of the first input sequence.
+   * @param[in] *pSrcB points to the second input sequence.
+   * @param[in] srcBLen length of the second input sequence.
+   * @param[out] *pDst points to the block of output data  Length srcALen+srcBLen-1.
+   * @return none.
+   */
+
+  void arm_conv_fast_q15(
+			  q15_t * pSrcA,
+			 uint32_t srcALen,
+			  q15_t * pSrcB,
+			 uint32_t srcBLen,
+			 q15_t * pDst);
+
+  /**
+   * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4
+   * @param[in] *pSrcA points to the first input sequence.
+   * @param[in] srcALen length of the first input sequence.
+   * @param[in] *pSrcB points to the second input sequence.
+   * @param[in] srcBLen length of the second input sequence.
+   * @param[out] *pDst points to the block of output data  Length srcALen+srcBLen-1.
+   * @param[in]  *pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2.   
+   * @param[in]  *pScratch2 points to scratch buffer of size min(srcALen, srcBLen).   
+   * @return none.   
+   */
+
+  void arm_conv_fast_opt_q15(
+  q15_t * pSrcA,
+  uint32_t srcALen,
+  q15_t * pSrcB,
+  uint32_t srcBLen,
+  q15_t * pDst,
+  q15_t * pScratch1,
+  q15_t * pScratch2);
+
+
+
+  /**
+   * @brief Convolution of Q31 sequences.
+   * @param[in] *pSrcA points to the first input sequence.
+   * @param[in] srcALen length of the first input sequence.
+   * @param[in] *pSrcB points to the second input sequence.
+   * @param[in] srcBLen length of the second input sequence.
+   * @param[out] *pDst points to the block of output data  Length srcALen+srcBLen-1.
+   * @return none.
+   */
+
+  void arm_conv_q31(
+  q31_t * pSrcA,
+  uint32_t srcALen,
+  q31_t * pSrcB,
+  uint32_t srcBLen,
+  q31_t * pDst);
+
+  /**
+   * @brief Convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4
+   * @param[in] *pSrcA points to the first input sequence.
+   * @param[in] srcALen length of the first input sequence.
+   * @param[in] *pSrcB points to the second input sequence.
+   * @param[in] srcBLen length of the second input sequence.
+   * @param[out] *pDst points to the block of output data  Length srcALen+srcBLen-1.
+   * @return none.
+   */
+
+  void arm_conv_fast_q31(
+  q31_t * pSrcA,
+  uint32_t srcALen,
+  q31_t * pSrcB,
+  uint32_t srcBLen,
+  q31_t * pDst);
+
+
+    /**   
+   * @brief Convolution of Q7 sequences.   
+   * @param[in] *pSrcA points to the first input sequence.   
+   * @param[in] srcALen length of the first input sequence.   
+   * @param[in] *pSrcB points to the second input sequence.   
+   * @param[in] srcBLen length of the second input sequence.   
+   * @param[out] *pDst points to the block of output data  Length srcALen+srcBLen-1.   
+   * @param[in]  *pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2.   
+   * @param[in]  *pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen).   
+   * @return none.   
+   */
+
+  void arm_conv_opt_q7(
+  q7_t * pSrcA,
+  uint32_t srcALen,
+  q7_t * pSrcB,
+  uint32_t srcBLen,
+  q7_t * pDst,
+  q15_t * pScratch1,
+  q15_t * pScratch2);
+
+
+
+  /**
+   * @brief Convolution of Q7 sequences.
+   * @param[in] *pSrcA points to the first input sequence.
+   * @param[in] srcALen length of the first input sequence.
+   * @param[in] *pSrcB points to the second input sequence.
+   * @param[in] srcBLen length of the second input sequence.
+   * @param[out] *pDst points to the block of output data  Length srcALen+srcBLen-1.
+   * @return none.
+   */
+
+  void arm_conv_q7(
+  q7_t * pSrcA,
+  uint32_t srcALen,
+  q7_t * pSrcB,
+  uint32_t srcBLen,
+  q7_t * pDst);
+
+
+  /**
+   * @brief Partial convolution of floating-point sequences.
+   * @param[in]       *pSrcA points to the first input sequence.
+   * @param[in]       srcALen length of the first input sequence.
+   * @param[in]       *pSrcB points to the second input sequence.
+   * @param[in]       srcBLen length of the second input sequence.
+   * @param[out]      *pDst points to the block of output data
+   * @param[in]       firstIndex is the first output sample to start with.
+   * @param[in]       numPoints is the number of output points to be computed.
+   * @return  Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2].
+   */
+
+  arm_status arm_conv_partial_f32(
+  float32_t * pSrcA,
+  uint32_t srcALen,
+  float32_t * pSrcB,
+  uint32_t srcBLen,
+  float32_t * pDst,
+  uint32_t firstIndex,
+  uint32_t numPoints);
+
+    /**   
+   * @brief Partial convolution of Q15 sequences.   
+   * @param[in]       *pSrcA points to the first input sequence.   
+   * @param[in]       srcALen length of the first input sequence.   
+   * @param[in]       *pSrcB points to the second input sequence.   
+   * @param[in]       srcBLen length of the second input sequence.   
+   * @param[out]      *pDst points to the block of output data   
+   * @param[in]       firstIndex is the first output sample to start with.   
+   * @param[in]       numPoints is the number of output points to be computed.   
+   * @param[in]       * pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2.   
+   * @param[in]       * pScratch2 points to scratch buffer of size min(srcALen, srcBLen).   
+   * @return  Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2].   
+   */
+
+  arm_status arm_conv_partial_opt_q15(
+  q15_t * pSrcA,
+  uint32_t srcALen,
+  q15_t * pSrcB,
+  uint32_t srcBLen,
+  q15_t * pDst,
+  uint32_t firstIndex,
+  uint32_t numPoints,
+  q15_t * pScratch1,
+  q15_t * pScratch2);
+
+
+/**
+   * @brief Partial convolution of Q15 sequences.
+   * @param[in]       *pSrcA points to the first input sequence.
+   * @param[in]       srcALen length of the first input sequence.
+   * @param[in]       *pSrcB points to the second input sequence.
+   * @param[in]       srcBLen length of the second input sequence.
+   * @param[out]      *pDst points to the block of output data
+   * @param[in]       firstIndex is the first output sample to start with.
+   * @param[in]       numPoints is the number of output points to be computed.
+   * @return  Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2].
+   */
+
+  arm_status arm_conv_partial_q15(
+  q15_t * pSrcA,
+  uint32_t srcALen,
+  q15_t * pSrcB,
+  uint32_t srcBLen,
+  q15_t * pDst,
+  uint32_t firstIndex,
+  uint32_t numPoints);
+
+  /**
+   * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4
+   * @param[in]       *pSrcA points to the first input sequence.
+   * @param[in]       srcALen length of the first input sequence.
+   * @param[in]       *pSrcB points to the second input sequence.
+   * @param[in]       srcBLen length of the second input sequence.
+   * @param[out]      *pDst points to the block of output data
+   * @param[in]       firstIndex is the first output sample to start with.
+   * @param[in]       numPoints is the number of output points to be computed.
+   * @return  Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2].
+   */
+
+  arm_status arm_conv_partial_fast_q15(
+				        q15_t * pSrcA,
+				       uint32_t srcALen,
+				        q15_t * pSrcB,
+				       uint32_t srcBLen,
+				       q15_t * pDst,
+				       uint32_t firstIndex,
+				       uint32_t numPoints);
+
+
+  /**
+   * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4
+   * @param[in]       *pSrcA points to the first input sequence.
+   * @param[in]       srcALen length of the first input sequence.
+   * @param[in]       *pSrcB points to the second input sequence.
+   * @param[in]       srcBLen length of the second input sequence.
+   * @param[out]      *pDst points to the block of output data
+   * @param[in]       firstIndex is the first output sample to start with.
+   * @param[in]       numPoints is the number of output points to be computed.
+   * @param[in]       * pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2.   
+   * @param[in]       * pScratch2 points to scratch buffer of size min(srcALen, srcBLen).   
+   * @return  Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2].   
+   */
+
+  arm_status arm_conv_partial_fast_opt_q15(
+  q15_t * pSrcA,
+  uint32_t srcALen,
+  q15_t * pSrcB,
+  uint32_t srcBLen,
+  q15_t * pDst,
+  uint32_t firstIndex,
+  uint32_t numPoints,
+  q15_t * pScratch1,
+  q15_t * pScratch2);
+
+
+  /**
+   * @brief Partial convolution of Q31 sequences.
+   * @param[in]       *pSrcA points to the first input sequence.
+   * @param[in]       srcALen length of the first input sequence.
+   * @param[in]       *pSrcB points to the second input sequence.
+   * @param[in]       srcBLen length of the second input sequence.
+   * @param[out]      *pDst points to the block of output data
+   * @param[in]       firstIndex is the first output sample to start with.
+   * @param[in]       numPoints is the number of output points to be computed.
+   * @return  Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2].
+   */
+
+  arm_status arm_conv_partial_q31(
+  q31_t * pSrcA,
+  uint32_t srcALen,
+  q31_t * pSrcB,
+  uint32_t srcBLen,
+  q31_t * pDst,
+  uint32_t firstIndex,
+  uint32_t numPoints);
+
+
+  /**
+   * @brief Partial convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4
+   * @param[in]       *pSrcA points to the first input sequence.
+   * @param[in]       srcALen length of the first input sequence.
+   * @param[in]       *pSrcB points to the second input sequence.
+   * @param[in]       srcBLen length of the second input sequence.
+   * @param[out]      *pDst points to the block of output data
+   * @param[in]       firstIndex is the first output sample to start with.
+   * @param[in]       numPoints is the number of output points to be computed.
+   * @return  Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2].
+   */
+
+  arm_status arm_conv_partial_fast_q31(
+  q31_t * pSrcA,
+  uint32_t srcALen,
+  q31_t * pSrcB,
+  uint32_t srcBLen,
+  q31_t * pDst,
+  uint32_t firstIndex,
+  uint32_t numPoints);
+
+
+  /**   
+   * @brief Partial convolution of Q7 sequences   
+   * @param[in]       *pSrcA points to the first input sequence.   
+   * @param[in]       srcALen length of the first input sequence.   
+   * @param[in]       *pSrcB points to the second input sequence.   
+   * @param[in]       srcBLen length of the second input sequence.   
+   * @param[out]      *pDst points to the block of output data   
+   * @param[in]       firstIndex is the first output sample to start with.   
+   * @param[in]       numPoints is the number of output points to be computed.   
+   * @param[in]  *pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2.   
+   * @param[in]  *pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen).   
+   * @return  Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2].   
+   */
+
+  arm_status arm_conv_partial_opt_q7(
+  q7_t * pSrcA,
+  uint32_t srcALen,
+  q7_t * pSrcB,
+  uint32_t srcBLen,
+  q7_t * pDst,
+  uint32_t firstIndex,
+  uint32_t numPoints,
+  q15_t * pScratch1,
+  q15_t * pScratch2);
+
+
+/**
+   * @brief Partial convolution of Q7 sequences.
+   * @param[in]       *pSrcA points to the first input sequence.
+   * @param[in]       srcALen length of the first input sequence.
+   * @param[in]       *pSrcB points to the second input sequence.
+   * @param[in]       srcBLen length of the second input sequence.
+   * @param[out]      *pDst points to the block of output data
+   * @param[in]       firstIndex is the first output sample to start with.
+   * @param[in]       numPoints is the number of output points to be computed.
+   * @return  Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2].
+   */
+
+  arm_status arm_conv_partial_q7(
+  q7_t * pSrcA,
+  uint32_t srcALen,
+  q7_t * pSrcB,
+  uint32_t srcBLen,
+  q7_t * pDst,
+  uint32_t firstIndex,
+  uint32_t numPoints);
+
+
+
+  /**
+   * @brief Instance structure for the Q15 FIR decimator.
+   */
+
+  typedef struct
+  {
+    uint8_t M;                      /**< decimation factor. */
+    uint16_t numTaps;               /**< number of coefficients in the filter. */
+    q15_t *pCoeffs;                  /**< points to the coefficient array. The array is of length numTaps.*/
+    q15_t *pState;                   /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
+  } arm_fir_decimate_instance_q15;
+
+  /**
+   * @brief Instance structure for the Q31 FIR decimator.
+   */
+
+  typedef struct
+  {
+    uint8_t M;                  /**< decimation factor. */
+    uint16_t numTaps;           /**< number of coefficients in the filter. */
+    q31_t *pCoeffs;              /**< points to the coefficient array. The array is of length numTaps.*/
+    q31_t *pState;               /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
+
+  } arm_fir_decimate_instance_q31;
+
+  /**
+   * @brief Instance structure for the floating-point FIR decimator.
+   */
+
+  typedef struct
+  {
+    uint8_t M;                          /**< decimation factor. */
+    uint16_t numTaps;                   /**< number of coefficients in the filter. */
+    float32_t *pCoeffs;                  /**< points to the coefficient array. The array is of length numTaps.*/
+    float32_t *pState;                   /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
+
+  } arm_fir_decimate_instance_f32;
+
+
+
+  /**
+   * @brief Processing function for the floating-point FIR decimator.
+   * @param[in] *S points to an instance of the floating-point FIR decimator structure.
+   * @param[in] *pSrc points to the block of input data.
+   * @param[out] *pDst points to the block of output data
+   * @param[in] blockSize number of input samples to process per call.
+   * @return none
+   */
+
+  void arm_fir_decimate_f32(
+  const arm_fir_decimate_instance_f32 * S,
+  float32_t * pSrc,
+  float32_t * pDst,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief  Initialization function for the floating-point FIR decimator.
+   * @param[in,out] *S points to an instance of the floating-point FIR decimator structure.
+   * @param[in] numTaps  number of coefficients in the filter.
+   * @param[in] M  decimation factor.
+   * @param[in] *pCoeffs points to the filter coefficients.
+   * @param[in] *pState points to the state buffer.
+   * @param[in] blockSize number of input samples to process per call.
+   * @return    The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if
+   * <code>blockSize</code> is not a multiple of <code>M</code>.
+   */
+
+  arm_status arm_fir_decimate_init_f32(
+  arm_fir_decimate_instance_f32 * S,
+  uint16_t numTaps,
+  uint8_t M,
+  float32_t * pCoeffs,
+  float32_t * pState,
+  uint32_t blockSize);
+
+  /**
+   * @brief Processing function for the Q15 FIR decimator.
+   * @param[in] *S points to an instance of the Q15 FIR decimator structure.
+   * @param[in] *pSrc points to the block of input data.
+   * @param[out] *pDst points to the block of output data
+   * @param[in] blockSize number of input samples to process per call.
+   * @return none
+   */
+
+  void arm_fir_decimate_q15(
+  const arm_fir_decimate_instance_q15 * S,
+  q15_t * pSrc,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Processing function for the Q15 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4.
+   * @param[in] *S points to an instance of the Q15 FIR decimator structure.
+   * @param[in] *pSrc points to the block of input data.
+   * @param[out] *pDst points to the block of output data
+   * @param[in] blockSize number of input samples to process per call.
+   * @return none
+   */
+
+  void arm_fir_decimate_fast_q15(
+  const arm_fir_decimate_instance_q15 * S,
+  q15_t * pSrc,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+
+
+  /**
+   * @brief  Initialization function for the Q15 FIR decimator.
+   * @param[in,out] *S points to an instance of the Q15 FIR decimator structure.
+   * @param[in] numTaps  number of coefficients in the filter.
+   * @param[in] M  decimation factor.
+   * @param[in] *pCoeffs points to the filter coefficients.
+   * @param[in] *pState points to the state buffer.
+   * @param[in] blockSize number of input samples to process per call.
+   * @return    The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if
+   * <code>blockSize</code> is not a multiple of <code>M</code>.
+   */
+
+  arm_status arm_fir_decimate_init_q15(
+  arm_fir_decimate_instance_q15 * S,
+  uint16_t numTaps,
+  uint8_t M,
+  q15_t * pCoeffs,
+  q15_t * pState,
+  uint32_t blockSize);
+
+  /**
+   * @brief Processing function for the Q31 FIR decimator.
+   * @param[in] *S points to an instance of the Q31 FIR decimator structure.
+   * @param[in] *pSrc points to the block of input data.
+   * @param[out] *pDst points to the block of output data
+   * @param[in] blockSize number of input samples to process per call.
+   * @return none
+   */
+
+  void arm_fir_decimate_q31(
+  const arm_fir_decimate_instance_q31 * S,
+  q31_t * pSrc,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Processing function for the Q31 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4.
+   * @param[in] *S points to an instance of the Q31 FIR decimator structure.
+   * @param[in] *pSrc points to the block of input data.
+   * @param[out] *pDst points to the block of output data
+   * @param[in] blockSize number of input samples to process per call.
+   * @return none
+   */
+
+  void arm_fir_decimate_fast_q31(
+  arm_fir_decimate_instance_q31 * S,
+  q31_t * pSrc,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief  Initialization function for the Q31 FIR decimator.
+   * @param[in,out] *S points to an instance of the Q31 FIR decimator structure.
+   * @param[in] numTaps  number of coefficients in the filter.
+   * @param[in] M  decimation factor.
+   * @param[in] *pCoeffs points to the filter coefficients.
+   * @param[in] *pState points to the state buffer.
+   * @param[in] blockSize number of input samples to process per call.
+   * @return    The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if
+   * <code>blockSize</code> is not a multiple of <code>M</code>.
+   */
+
+  arm_status arm_fir_decimate_init_q31(
+  arm_fir_decimate_instance_q31 * S,
+  uint16_t numTaps,
+  uint8_t M,
+  q31_t * pCoeffs,
+  q31_t * pState,
+  uint32_t blockSize);
+
+
+
+  /**
+   * @brief Instance structure for the Q15 FIR interpolator.
+   */
+
+  typedef struct
+  {
+    uint8_t L;                      /**< upsample factor. */
+    uint16_t phaseLength;           /**< length of each polyphase filter component. */
+    q15_t *pCoeffs;                 /**< points to the coefficient array. The array is of length L*phaseLength. */
+    q15_t *pState;                  /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */
+  } arm_fir_interpolate_instance_q15;
+
+  /**
+   * @brief Instance structure for the Q31 FIR interpolator.
+   */
+
+  typedef struct
+  {
+    uint8_t L;                      /**< upsample factor. */
+    uint16_t phaseLength;           /**< length of each polyphase filter component. */
+    q31_t *pCoeffs;                  /**< points to the coefficient array. The array is of length L*phaseLength. */
+    q31_t *pState;                   /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */
+  } arm_fir_interpolate_instance_q31;
+
+  /**
+   * @brief Instance structure for the floating-point FIR interpolator.
+   */
+
+  typedef struct
+  {
+    uint8_t L;                     /**< upsample factor. */
+    uint16_t phaseLength;          /**< length of each polyphase filter component. */
+    float32_t *pCoeffs;             /**< points to the coefficient array. The array is of length L*phaseLength. */
+    float32_t *pState;              /**< points to the state variable array. The array is of length phaseLength+numTaps-1. */
+  } arm_fir_interpolate_instance_f32;
+
+
+  /**
+   * @brief Processing function for the Q15 FIR interpolator.
+   * @param[in] *S        points to an instance of the Q15 FIR interpolator structure.
+   * @param[in] *pSrc     points to the block of input data.
+   * @param[out] *pDst    points to the block of output data.
+   * @param[in] blockSize number of input samples to process per call.
+   * @return none.
+   */
+
+  void arm_fir_interpolate_q15(
+  const arm_fir_interpolate_instance_q15 * S,
+  q15_t * pSrc,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief  Initialization function for the Q15 FIR interpolator.
+   * @param[in,out] *S        points to an instance of the Q15 FIR interpolator structure.
+   * @param[in]     L         upsample factor.
+   * @param[in]     numTaps   number of filter coefficients in the filter.
+   * @param[in]     *pCoeffs  points to the filter coefficient buffer.
+   * @param[in]     *pState   points to the state buffer.
+   * @param[in]     blockSize number of input samples to process per call.
+   * @return        The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if
+   * the filter length <code>numTaps</code> is not a multiple of the interpolation factor <code>L</code>.
+   */
+
+  arm_status arm_fir_interpolate_init_q15(
+  arm_fir_interpolate_instance_q15 * S,
+  uint8_t L,
+  uint16_t numTaps,
+  q15_t * pCoeffs,
+  q15_t * pState,
+  uint32_t blockSize);
+
+  /**
+   * @brief Processing function for the Q31 FIR interpolator.
+   * @param[in] *S        points to an instance of the Q15 FIR interpolator structure.
+   * @param[in] *pSrc     points to the block of input data.
+   * @param[out] *pDst    points to the block of output data.
+   * @param[in] blockSize number of input samples to process per call.
+   * @return none.
+   */
+
+  void arm_fir_interpolate_q31(
+  const arm_fir_interpolate_instance_q31 * S,
+  q31_t * pSrc,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Initialization function for the Q31 FIR interpolator.
+   * @param[in,out] *S        points to an instance of the Q31 FIR interpolator structure.
+   * @param[in]     L         upsample factor.
+   * @param[in]     numTaps   number of filter coefficients in the filter.
+   * @param[in]     *pCoeffs  points to the filter coefficient buffer.
+   * @param[in]     *pState   points to the state buffer.
+   * @param[in]     blockSize number of input samples to process per call.
+   * @return        The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if
+   * the filter length <code>numTaps</code> is not a multiple of the interpolation factor <code>L</code>.
+   */
+
+  arm_status arm_fir_interpolate_init_q31(
+  arm_fir_interpolate_instance_q31 * S,
+  uint8_t L,
+  uint16_t numTaps,
+  q31_t * pCoeffs,
+  q31_t * pState,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief Processing function for the floating-point FIR interpolator.
+   * @param[in] *S        points to an instance of the floating-point FIR interpolator structure.
+   * @param[in] *pSrc     points to the block of input data.
+   * @param[out] *pDst    points to the block of output data.
+   * @param[in] blockSize number of input samples to process per call.
+   * @return none.
+   */
+
+  void arm_fir_interpolate_f32(
+  const arm_fir_interpolate_instance_f32 * S,
+  float32_t * pSrc,
+  float32_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Initialization function for the floating-point FIR interpolator.
+   * @param[in,out] *S        points to an instance of the floating-point FIR interpolator structure.
+   * @param[in]     L         upsample factor.
+   * @param[in]     numTaps   number of filter coefficients in the filter.
+   * @param[in]     *pCoeffs  points to the filter coefficient buffer.
+   * @param[in]     *pState   points to the state buffer.
+   * @param[in]     blockSize number of input samples to process per call.
+   * @return        The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if
+   * the filter length <code>numTaps</code> is not a multiple of the interpolation factor <code>L</code>.
+   */
+
+  arm_status arm_fir_interpolate_init_f32(
+  arm_fir_interpolate_instance_f32 * S,
+  uint8_t L,
+  uint16_t numTaps,
+  float32_t * pCoeffs,
+  float32_t * pState,
+  uint32_t blockSize);
+
+  /**
+   * @brief Instance structure for the high precision Q31 Biquad cascade filter.
+   */
+
+  typedef struct
+  {
+    uint8_t numStages;       /**< number of 2nd order stages in the filter.  Overall order is 2*numStages. */
+    q63_t *pState;           /**< points to the array of state coefficients.  The array is of length 4*numStages. */
+    q31_t *pCoeffs;          /**< points to the array of coefficients.  The array is of length 5*numStages. */
+    uint8_t postShift;       /**< additional shift, in bits, applied to each output sample. */
+
+  } arm_biquad_cas_df1_32x64_ins_q31;
+
+
+  /**
+   * @param[in]  *S        points to an instance of the high precision Q31 Biquad cascade filter structure.
+   * @param[in]  *pSrc     points to the block of input data.
+   * @param[out] *pDst     points to the block of output data
+   * @param[in]  blockSize number of samples to process.
+   * @return none.
+   */
+
+  void arm_biquad_cas_df1_32x64_q31(
+  const arm_biquad_cas_df1_32x64_ins_q31 * S,
+  q31_t * pSrc,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+
+  /**
+   * @param[in,out] *S           points to an instance of the high precision Q31 Biquad cascade filter structure.
+   * @param[in]     numStages    number of 2nd order stages in the filter.
+   * @param[in]     *pCoeffs     points to the filter coefficients.
+   * @param[in]     *pState      points to the state buffer.
+   * @param[in]     postShift    shift to be applied to the output. Varies according to the coefficients format
+   * @return        none
+   */
+
+  void arm_biquad_cas_df1_32x64_init_q31(
+  arm_biquad_cas_df1_32x64_ins_q31 * S,
+  uint8_t numStages,
+  q31_t * pCoeffs,
+  q63_t * pState,
+  uint8_t postShift);
+
+
+
+  /**
+   * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter.
+   */
+
+  typedef struct
+  {
+    uint8_t numStages;         /**< number of 2nd order stages in the filter.  Overall order is 2*numStages. */
+    float32_t *pState;         /**< points to the array of state coefficients.  The array is of length 2*numStages. */
+    float32_t *pCoeffs;        /**< points to the array of coefficients.  The array is of length 5*numStages. */
+  } arm_biquad_cascade_df2T_instance_f32;
+
+
+  /**
+   * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter.
+   * @param[in]  *S        points to an instance of the filter data structure.
+   * @param[in]  *pSrc     points to the block of input data.
+   * @param[out] *pDst     points to the block of output data
+   * @param[in]  blockSize number of samples to process.
+   * @return none.
+   */
+
+  void arm_biquad_cascade_df2T_f32(
+  const arm_biquad_cascade_df2T_instance_f32 * S,
+  float32_t * pSrc,
+  float32_t * pDst,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief  Initialization function for the floating-point transposed direct form II Biquad cascade filter.
+   * @param[in,out] *S           points to an instance of the filter data structure.
+   * @param[in]     numStages    number of 2nd order stages in the filter.
+   * @param[in]     *pCoeffs     points to the filter coefficients.
+   * @param[in]     *pState      points to the state buffer.
+   * @return        none
+   */
+
+  void arm_biquad_cascade_df2T_init_f32(
+  arm_biquad_cascade_df2T_instance_f32 * S,
+  uint8_t numStages,
+  float32_t * pCoeffs,
+  float32_t * pState);
+
+
+
+  /**
+   * @brief Instance structure for the Q15 FIR lattice filter.
+   */
+
+  typedef struct
+  {
+    uint16_t numStages;                          /**< number of filter stages. */
+    q15_t *pState;                               /**< points to the state variable array. The array is of length numStages. */
+    q15_t *pCoeffs;                              /**< points to the coefficient array. The array is of length numStages. */
+  } arm_fir_lattice_instance_q15;
+
+  /**
+   * @brief Instance structure for the Q31 FIR lattice filter.
+   */
+
+  typedef struct
+  {
+    uint16_t numStages;                          /**< number of filter stages. */
+    q31_t *pState;                               /**< points to the state variable array. The array is of length numStages. */
+    q31_t *pCoeffs;                              /**< points to the coefficient array. The array is of length numStages. */
+  } arm_fir_lattice_instance_q31;
+
+  /**
+   * @brief Instance structure for the floating-point FIR lattice filter.
+   */
+
+  typedef struct
+  {
+    uint16_t numStages;                  /**< number of filter stages. */
+    float32_t *pState;                   /**< points to the state variable array. The array is of length numStages. */
+    float32_t *pCoeffs;                  /**< points to the coefficient array. The array is of length numStages. */
+  } arm_fir_lattice_instance_f32;
+
+  /**
+   * @brief Initialization function for the Q15 FIR lattice filter.
+   * @param[in] *S points to an instance of the Q15 FIR lattice structure.
+   * @param[in] numStages  number of filter stages.
+   * @param[in] *pCoeffs points to the coefficient buffer.  The array is of length numStages. 
+   * @param[in] *pState points to the state buffer.  The array is of length numStages. 
+   * @return none.
+   */
+
+  void arm_fir_lattice_init_q15(
+  arm_fir_lattice_instance_q15 * S,
+  uint16_t numStages,
+  q15_t * pCoeffs,
+  q15_t * pState);
+
+
+  /**
+   * @brief Processing function for the Q15 FIR lattice filter.
+   * @param[in] *S points to an instance of the Q15 FIR lattice structure.
+   * @param[in] *pSrc points to the block of input data.
+   * @param[out] *pDst points to the block of output data.
+   * @param[in] blockSize number of samples to process.
+   * @return none.
+   */
+  void arm_fir_lattice_q15(
+  const arm_fir_lattice_instance_q15 * S,
+  q15_t * pSrc,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Initialization function for the Q31 FIR lattice filter.
+   * @param[in] *S points to an instance of the Q31 FIR lattice structure.
+   * @param[in] numStages  number of filter stages.
+   * @param[in] *pCoeffs points to the coefficient buffer.  The array is of length numStages.
+   * @param[in] *pState points to the state buffer.   The array is of length numStages.
+   * @return none.
+   */
+
+  void arm_fir_lattice_init_q31(
+  arm_fir_lattice_instance_q31 * S,
+  uint16_t numStages,
+  q31_t * pCoeffs,
+  q31_t * pState);
+
+
+  /**
+   * @brief Processing function for the Q31 FIR lattice filter.
+   * @param[in]  *S        points to an instance of the Q31 FIR lattice structure.
+   * @param[in]  *pSrc     points to the block of input data.
+   * @param[out] *pDst     points to the block of output data
+   * @param[in]  blockSize number of samples to process.
+   * @return none.
+   */
+
+  void arm_fir_lattice_q31(
+  const arm_fir_lattice_instance_q31 * S,
+  q31_t * pSrc,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+/**
+ * @brief Initialization function for the floating-point FIR lattice filter.
+ * @param[in] *S points to an instance of the floating-point FIR lattice structure.
+ * @param[in] numStages  number of filter stages.
+ * @param[in] *pCoeffs points to the coefficient buffer.  The array is of length numStages.
+ * @param[in] *pState points to the state buffer.  The array is of length numStages.
+ * @return none.
+ */
+
+  void arm_fir_lattice_init_f32(
+  arm_fir_lattice_instance_f32 * S,
+  uint16_t numStages,
+  float32_t * pCoeffs,
+  float32_t * pState);
+
+  /**
+   * @brief Processing function for the floating-point FIR lattice filter.
+   * @param[in]  *S        points to an instance of the floating-point FIR lattice structure.
+   * @param[in]  *pSrc     points to the block of input data.
+   * @param[out] *pDst     points to the block of output data
+   * @param[in]  blockSize number of samples to process.
+   * @return none.
+   */
+
+  void arm_fir_lattice_f32(
+  const arm_fir_lattice_instance_f32 * S,
+  float32_t * pSrc,
+  float32_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Instance structure for the Q15 IIR lattice filter.
+   */
+  typedef struct
+  {
+    uint16_t numStages;                         /**< number of stages in the filter. */
+    q15_t *pState;                              /**< points to the state variable array. The array is of length numStages+blockSize. */
+    q15_t *pkCoeffs;                            /**< points to the reflection coefficient array. The array is of length numStages. */
+    q15_t *pvCoeffs;                            /**< points to the ladder coefficient array. The array is of length numStages+1. */
+  } arm_iir_lattice_instance_q15;
+
+  /**
+   * @brief Instance structure for the Q31 IIR lattice filter.
+   */
+  typedef struct
+  {
+    uint16_t numStages;                         /**< number of stages in the filter. */
+    q31_t *pState;                              /**< points to the state variable array. The array is of length numStages+blockSize. */
+    q31_t *pkCoeffs;                            /**< points to the reflection coefficient array. The array is of length numStages. */
+    q31_t *pvCoeffs;                            /**< points to the ladder coefficient array. The array is of length numStages+1. */
+  } arm_iir_lattice_instance_q31;
+
+  /**
+   * @brief Instance structure for the floating-point IIR lattice filter.
+   */
+  typedef struct
+  {
+    uint16_t numStages;                         /**< number of stages in the filter. */
+    float32_t *pState;                          /**< points to the state variable array. The array is of length numStages+blockSize. */
+    float32_t *pkCoeffs;                        /**< points to the reflection coefficient array. The array is of length numStages. */
+    float32_t *pvCoeffs;                        /**< points to the ladder coefficient array. The array is of length numStages+1. */
+  } arm_iir_lattice_instance_f32;
+
+  /**
+   * @brief Processing function for the floating-point IIR lattice filter.
+   * @param[in] *S points to an instance of the floating-point IIR lattice structure.
+   * @param[in] *pSrc points to the block of input data.
+   * @param[out] *pDst points to the block of output data.
+   * @param[in] blockSize number of samples to process.
+   * @return none.
+   */
+
+  void arm_iir_lattice_f32(
+  const arm_iir_lattice_instance_f32 * S,
+  float32_t * pSrc,
+  float32_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Initialization function for the floating-point IIR lattice filter.
+   * @param[in] *S points to an instance of the floating-point IIR lattice structure.
+   * @param[in] numStages number of stages in the filter.
+   * @param[in] *pkCoeffs points to the reflection coefficient buffer.  The array is of length numStages.
+   * @param[in] *pvCoeffs points to the ladder coefficient buffer.  The array is of length numStages+1.
+   * @param[in] *pState points to the state buffer.  The array is of length numStages+blockSize-1.
+   * @param[in] blockSize number of samples to process.
+   * @return none.
+   */
+
+  void arm_iir_lattice_init_f32(
+  arm_iir_lattice_instance_f32 * S,
+  uint16_t numStages,
+  float32_t * pkCoeffs,
+  float32_t * pvCoeffs,
+  float32_t * pState,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief Processing function for the Q31 IIR lattice filter.
+   * @param[in] *S points to an instance of the Q31 IIR lattice structure.
+   * @param[in] *pSrc points to the block of input data.
+   * @param[out] *pDst points to the block of output data.
+   * @param[in] blockSize number of samples to process.
+   * @return none.
+   */
+
+  void arm_iir_lattice_q31(
+  const arm_iir_lattice_instance_q31 * S,
+  q31_t * pSrc,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief Initialization function for the Q31 IIR lattice filter.
+   * @param[in] *S points to an instance of the Q31 IIR lattice structure.
+   * @param[in] numStages number of stages in the filter.
+   * @param[in] *pkCoeffs points to the reflection coefficient buffer.  The array is of length numStages.
+   * @param[in] *pvCoeffs points to the ladder coefficient buffer.  The array is of length numStages+1.
+   * @param[in] *pState points to the state buffer.  The array is of length numStages+blockSize.
+   * @param[in] blockSize number of samples to process.
+   * @return none.
+   */
+
+  void arm_iir_lattice_init_q31(
+  arm_iir_lattice_instance_q31 * S,
+  uint16_t numStages,
+  q31_t * pkCoeffs,
+  q31_t * pvCoeffs,
+  q31_t * pState,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief Processing function for the Q15 IIR lattice filter.
+   * @param[in] *S points to an instance of the Q15 IIR lattice structure.
+   * @param[in] *pSrc points to the block of input data.
+   * @param[out] *pDst points to the block of output data.
+   * @param[in] blockSize number of samples to process.
+   * @return none.
+   */
+
+  void arm_iir_lattice_q15(
+  const arm_iir_lattice_instance_q15 * S,
+  q15_t * pSrc,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+
+/**
+ * @brief Initialization function for the Q15 IIR lattice filter.
+ * @param[in] *S points to an instance of the fixed-point Q15 IIR lattice structure.
+ * @param[in] numStages  number of stages in the filter.
+ * @param[in] *pkCoeffs points to reflection coefficient buffer.  The array is of length numStages.
+ * @param[in] *pvCoeffs points to ladder coefficient buffer.  The array is of length numStages+1.
+ * @param[in] *pState points to state buffer.  The array is of length numStages+blockSize.
+ * @param[in] blockSize number of samples to process per call.
+ * @return none.
+ */
+
+  void arm_iir_lattice_init_q15(
+  arm_iir_lattice_instance_q15 * S,
+  uint16_t numStages,
+  q15_t * pkCoeffs,
+  q15_t * pvCoeffs,
+  q15_t * pState,
+  uint32_t blockSize);
+
+  /**
+   * @brief Instance structure for the floating-point LMS filter.
+   */
+
+  typedef struct
+  {
+    uint16_t numTaps;    /**< number of coefficients in the filter. */
+    float32_t *pState;   /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
+    float32_t *pCoeffs;  /**< points to the coefficient array. The array is of length numTaps. */
+    float32_t mu;        /**< step size that controls filter coefficient updates. */
+  } arm_lms_instance_f32;
+
+  /**
+   * @brief Processing function for floating-point LMS filter.
+   * @param[in]  *S points to an instance of the floating-point LMS filter structure.
+   * @param[in]  *pSrc points to the block of input data.
+   * @param[in]  *pRef points to the block of reference data.
+   * @param[out] *pOut points to the block of output data.
+   * @param[out] *pErr points to the block of error data.
+   * @param[in]  blockSize number of samples to process.
+   * @return     none.
+   */
+
+  void arm_lms_f32(
+  const arm_lms_instance_f32 * S,
+  float32_t * pSrc,
+  float32_t * pRef,
+  float32_t * pOut,
+  float32_t * pErr,
+  uint32_t blockSize);
+
+  /**
+   * @brief Initialization function for floating-point LMS filter.
+   * @param[in] *S points to an instance of the floating-point LMS filter structure.
+   * @param[in] numTaps  number of filter coefficients.
+   * @param[in] *pCoeffs points to the coefficient buffer.
+   * @param[in] *pState points to state buffer.
+   * @param[in] mu step size that controls filter coefficient updates.
+   * @param[in] blockSize number of samples to process.
+   * @return none.
+   */
+
+  void arm_lms_init_f32(
+  arm_lms_instance_f32 * S,
+  uint16_t numTaps,
+  float32_t * pCoeffs,
+  float32_t * pState,
+  float32_t mu,
+  uint32_t blockSize);
+
+  /**
+   * @brief Instance structure for the Q15 LMS filter.
+   */
+
+  typedef struct
+  {
+    uint16_t numTaps;    /**< number of coefficients in the filter. */
+    q15_t *pState;       /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
+    q15_t *pCoeffs;      /**< points to the coefficient array. The array is of length numTaps. */
+    q15_t mu;            /**< step size that controls filter coefficient updates. */
+    uint32_t postShift;  /**< bit shift applied to coefficients. */
+  } arm_lms_instance_q15;
+
+
+  /**
+   * @brief Initialization function for the Q15 LMS filter.
+   * @param[in] *S points to an instance of the Q15 LMS filter structure.
+   * @param[in] numTaps  number of filter coefficients.
+   * @param[in] *pCoeffs points to the coefficient buffer.
+   * @param[in] *pState points to the state buffer.
+   * @param[in] mu step size that controls filter coefficient updates.
+   * @param[in] blockSize number of samples to process.
+   * @param[in] postShift bit shift applied to coefficients.
+   * @return    none.
+   */
+
+  void arm_lms_init_q15(
+  arm_lms_instance_q15 * S,
+  uint16_t numTaps,
+  q15_t * pCoeffs,
+  q15_t * pState,
+  q15_t mu,
+  uint32_t blockSize,
+  uint32_t postShift);
+
+  /**
+   * @brief Processing function for Q15 LMS filter.
+   * @param[in] *S points to an instance of the Q15 LMS filter structure.
+   * @param[in] *pSrc points to the block of input data.
+   * @param[in] *pRef points to the block of reference data.
+   * @param[out] *pOut points to the block of output data.
+   * @param[out] *pErr points to the block of error data.
+   * @param[in] blockSize number of samples to process.
+   * @return none.
+   */
+
+  void arm_lms_q15(
+  const arm_lms_instance_q15 * S,
+  q15_t * pSrc,
+  q15_t * pRef,
+  q15_t * pOut,
+  q15_t * pErr,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief Instance structure for the Q31 LMS filter.
+   */
+
+  typedef struct
+  {
+    uint16_t numTaps;    /**< number of coefficients in the filter. */
+    q31_t *pState;       /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
+    q31_t *pCoeffs;      /**< points to the coefficient array. The array is of length numTaps. */
+    q31_t mu;            /**< step size that controls filter coefficient updates. */
+    uint32_t postShift;  /**< bit shift applied to coefficients. */
+
+  } arm_lms_instance_q31;
+
+  /**
+   * @brief Processing function for Q31 LMS filter.
+   * @param[in]  *S points to an instance of the Q15 LMS filter structure.
+   * @param[in]  *pSrc points to the block of input data.
+   * @param[in]  *pRef points to the block of reference data.
+   * @param[out] *pOut points to the block of output data.
+   * @param[out] *pErr points to the block of error data.
+   * @param[in]  blockSize number of samples to process.
+   * @return     none.
+   */
+
+  void arm_lms_q31(
+  const arm_lms_instance_q31 * S,
+  q31_t * pSrc,
+  q31_t * pRef,
+  q31_t * pOut,
+  q31_t * pErr,
+  uint32_t blockSize);
+
+  /**
+   * @brief Initialization function for Q31 LMS filter.
+   * @param[in] *S points to an instance of the Q31 LMS filter structure.
+   * @param[in] numTaps  number of filter coefficients.
+   * @param[in] *pCoeffs points to coefficient buffer.
+   * @param[in] *pState points to state buffer.
+   * @param[in] mu step size that controls filter coefficient updates.
+   * @param[in] blockSize number of samples to process.
+   * @param[in] postShift bit shift applied to coefficients.
+   * @return none.
+   */
+
+  void arm_lms_init_q31(
+  arm_lms_instance_q31 * S,
+  uint16_t numTaps,
+  q31_t * pCoeffs,
+  q31_t * pState,
+  q31_t mu,
+  uint32_t blockSize,
+  uint32_t postShift);
+
+  /**
+   * @brief Instance structure for the floating-point normalized LMS filter.
+   */
+
+  typedef struct
+  {
+    uint16_t numTaps;     /**< number of coefficients in the filter. */
+    float32_t *pState;    /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
+    float32_t *pCoeffs;   /**< points to the coefficient array. The array is of length numTaps. */
+    float32_t mu;        /**< step size that control filter coefficient updates. */
+    float32_t energy;    /**< saves previous frame energy. */
+    float32_t x0;        /**< saves previous input sample. */
+  } arm_lms_norm_instance_f32;
+
+  /**
+   * @brief Processing function for floating-point normalized LMS filter.
+   * @param[in] *S points to an instance of the floating-point normalized LMS filter structure.
+   * @param[in] *pSrc points to the block of input data.
+   * @param[in] *pRef points to the block of reference data.
+   * @param[out] *pOut points to the block of output data.
+   * @param[out] *pErr points to the block of error data.
+   * @param[in] blockSize number of samples to process.
+   * @return none.
+   */
+
+  void arm_lms_norm_f32(
+  arm_lms_norm_instance_f32 * S,
+  float32_t * pSrc,
+  float32_t * pRef,
+  float32_t * pOut,
+  float32_t * pErr,
+  uint32_t blockSize);
+
+  /**
+   * @brief Initialization function for floating-point normalized LMS filter.
+   * @param[in] *S points to an instance of the floating-point LMS filter structure.
+   * @param[in] numTaps  number of filter coefficients.
+   * @param[in] *pCoeffs points to coefficient buffer.
+   * @param[in] *pState points to state buffer.
+   * @param[in] mu step size that controls filter coefficient updates.
+   * @param[in] blockSize number of samples to process.
+   * @return none.
+   */
+
+  void arm_lms_norm_init_f32(
+  arm_lms_norm_instance_f32 * S,
+  uint16_t numTaps,
+  float32_t * pCoeffs,
+  float32_t * pState,
+  float32_t mu,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief Instance structure for the Q31 normalized LMS filter.
+   */
+  typedef struct
+  {
+    uint16_t numTaps;     /**< number of coefficients in the filter. */
+    q31_t *pState;        /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
+    q31_t *pCoeffs;       /**< points to the coefficient array. The array is of length numTaps. */
+    q31_t mu;             /**< step size that controls filter coefficient updates. */
+    uint8_t postShift;    /**< bit shift applied to coefficients. */
+    q31_t *recipTable;    /**< points to the reciprocal initial value table. */
+    q31_t energy;         /**< saves previous frame energy. */
+    q31_t x0;             /**< saves previous input sample. */
+  } arm_lms_norm_instance_q31;
+
+  /**
+   * @brief Processing function for Q31 normalized LMS filter.
+   * @param[in] *S points to an instance of the Q31 normalized LMS filter structure.
+   * @param[in] *pSrc points to the block of input data.
+   * @param[in] *pRef points to the block of reference data.
+   * @param[out] *pOut points to the block of output data.
+   * @param[out] *pErr points to the block of error data.
+   * @param[in] blockSize number of samples to process.
+   * @return none.
+   */
+
+  void arm_lms_norm_q31(
+  arm_lms_norm_instance_q31 * S,
+  q31_t * pSrc,
+  q31_t * pRef,
+  q31_t * pOut,
+  q31_t * pErr,
+  uint32_t blockSize);
+
+  /**
+   * @brief Initialization function for Q31 normalized LMS filter.
+   * @param[in] *S points to an instance of the Q31 normalized LMS filter structure.
+   * @param[in] numTaps  number of filter coefficients.
+   * @param[in] *pCoeffs points to coefficient buffer.
+   * @param[in] *pState points to state buffer.
+   * @param[in] mu step size that controls filter coefficient updates.
+   * @param[in] blockSize number of samples to process.
+   * @param[in] postShift bit shift applied to coefficients.
+   * @return none.
+   */
+
+  void arm_lms_norm_init_q31(
+  arm_lms_norm_instance_q31 * S,
+  uint16_t numTaps,
+  q31_t * pCoeffs,
+  q31_t * pState,
+  q31_t mu,
+  uint32_t blockSize,
+  uint8_t postShift);
+
+  /**
+   * @brief Instance structure for the Q15 normalized LMS filter.
+   */
+
+  typedef struct
+  {
+    uint16_t numTaps;    /**< Number of coefficients in the filter. */
+    q15_t *pState;        /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
+    q15_t *pCoeffs;       /**< points to the coefficient array. The array is of length numTaps. */
+    q15_t mu;            /**< step size that controls filter coefficient updates. */
+    uint8_t postShift;   /**< bit shift applied to coefficients. */
+    q15_t *recipTable;   /**< Points to the reciprocal initial value table. */
+    q15_t energy;        /**< saves previous frame energy. */
+    q15_t x0;            /**< saves previous input sample. */
+  } arm_lms_norm_instance_q15;
+
+  /**
+   * @brief Processing function for Q15 normalized LMS filter.
+   * @param[in] *S points to an instance of the Q15 normalized LMS filter structure.
+   * @param[in] *pSrc points to the block of input data.
+   * @param[in] *pRef points to the block of reference data.
+   * @param[out] *pOut points to the block of output data.
+   * @param[out] *pErr points to the block of error data.
+   * @param[in] blockSize number of samples to process.
+   * @return none.
+   */
+
+  void arm_lms_norm_q15(
+  arm_lms_norm_instance_q15 * S,
+  q15_t * pSrc,
+  q15_t * pRef,
+  q15_t * pOut,
+  q15_t * pErr,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief Initialization function for Q15 normalized LMS filter.
+   * @param[in] *S points to an instance of the Q15 normalized LMS filter structure.
+   * @param[in] numTaps  number of filter coefficients.
+   * @param[in] *pCoeffs points to coefficient buffer.
+   * @param[in] *pState points to state buffer.
+   * @param[in] mu step size that controls filter coefficient updates.
+   * @param[in] blockSize number of samples to process.
+   * @param[in] postShift bit shift applied to coefficients.
+   * @return none.
+   */
+
+  void arm_lms_norm_init_q15(
+  arm_lms_norm_instance_q15 * S,
+  uint16_t numTaps,
+  q15_t * pCoeffs,
+  q15_t * pState,
+  q15_t mu,
+  uint32_t blockSize,
+  uint8_t postShift);
+
+  /**
+   * @brief Correlation of floating-point sequences.
+   * @param[in] *pSrcA points to the first input sequence.
+   * @param[in] srcALen length of the first input sequence.
+   * @param[in] *pSrcB points to the second input sequence.
+   * @param[in] srcBLen length of the second input sequence.
+   * @param[out] *pDst points to the block of output data  Length 2 * max(srcALen, srcBLen) - 1.
+   * @return none.
+   */
+
+  void arm_correlate_f32(
+  float32_t * pSrcA,
+  uint32_t srcALen,
+  float32_t * pSrcB,
+  uint32_t srcBLen,
+  float32_t * pDst);
+
+
+   /**   
+   * @brief Correlation of Q15 sequences   
+   * @param[in] *pSrcA points to the first input sequence.   
+   * @param[in] srcALen length of the first input sequence.   
+   * @param[in] *pSrcB points to the second input sequence.   
+   * @param[in] srcBLen length of the second input sequence.   
+   * @param[out] *pDst points to the block of output data  Length 2 * max(srcALen, srcBLen) - 1.   
+   * @param[in]  *pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2.   
+   * @return none.   
+   */
+  void arm_correlate_opt_q15(
+  q15_t * pSrcA,
+  uint32_t srcALen,
+  q15_t * pSrcB,
+  uint32_t srcBLen,
+  q15_t * pDst,
+  q15_t * pScratch);
+
+
+  /**
+   * @brief Correlation of Q15 sequences.
+   * @param[in] *pSrcA points to the first input sequence.
+   * @param[in] srcALen length of the first input sequence.
+   * @param[in] *pSrcB points to the second input sequence.
+   * @param[in] srcBLen length of the second input sequence.
+   * @param[out] *pDst points to the block of output data  Length 2 * max(srcALen, srcBLen) - 1.
+   * @return none.
+   */
+
+  void arm_correlate_q15(
+  q15_t * pSrcA,
+  uint32_t srcALen,
+  q15_t * pSrcB,
+  uint32_t srcBLen,
+  q15_t * pDst);
+
+  /**
+   * @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4.
+   * @param[in] *pSrcA points to the first input sequence.
+   * @param[in] srcALen length of the first input sequence.
+   * @param[in] *pSrcB points to the second input sequence.
+   * @param[in] srcBLen length of the second input sequence.
+   * @param[out] *pDst points to the block of output data  Length 2 * max(srcALen, srcBLen) - 1.
+   * @return none.
+   */
+
+  void arm_correlate_fast_q15(
+			       q15_t * pSrcA,
+			      uint32_t srcALen,
+			       q15_t * pSrcB,
+			      uint32_t srcBLen,
+			      q15_t * pDst);
+
+
+
+  /**
+   * @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4.
+   * @param[in] *pSrcA points to the first input sequence.
+   * @param[in] srcALen length of the first input sequence.
+   * @param[in] *pSrcB points to the second input sequence.
+   * @param[in] srcBLen length of the second input sequence.
+   * @param[out] *pDst points to the block of output data  Length 2 * max(srcALen, srcBLen) - 1.
+   * @param[in]  *pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2.   
+   * @return none.
+   */
+
+  void arm_correlate_fast_opt_q15(
+  q15_t * pSrcA,
+  uint32_t srcALen,
+  q15_t * pSrcB,
+  uint32_t srcBLen,
+  q15_t * pDst,
+  q15_t * pScratch);
+
+  /**
+   * @brief Correlation of Q31 sequences.
+   * @param[in] *pSrcA points to the first input sequence.
+   * @param[in] srcALen length of the first input sequence.
+   * @param[in] *pSrcB points to the second input sequence.
+   * @param[in] srcBLen length of the second input sequence.
+   * @param[out] *pDst points to the block of output data  Length 2 * max(srcALen, srcBLen) - 1.
+   * @return none.
+   */
+
+  void arm_correlate_q31(
+  q31_t * pSrcA,
+  uint32_t srcALen,
+  q31_t * pSrcB,
+  uint32_t srcBLen,
+  q31_t * pDst);
+
+  /**
+   * @brief Correlation of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4
+   * @param[in] *pSrcA points to the first input sequence.
+   * @param[in] srcALen length of the first input sequence.
+   * @param[in] *pSrcB points to the second input sequence.
+   * @param[in] srcBLen length of the second input sequence.
+   * @param[out] *pDst points to the block of output data  Length 2 * max(srcALen, srcBLen) - 1.
+   * @return none.
+   */
+
+  void arm_correlate_fast_q31(
+  q31_t * pSrcA,
+  uint32_t srcALen,
+  q31_t * pSrcB,
+  uint32_t srcBLen,
+  q31_t * pDst);
+
+
+
+ /**   
+   * @brief Correlation of Q7 sequences.   
+   * @param[in] *pSrcA points to the first input sequence.   
+   * @param[in] srcALen length of the first input sequence.   
+   * @param[in] *pSrcB points to the second input sequence.   
+   * @param[in] srcBLen length of the second input sequence.   
+   * @param[out] *pDst points to the block of output data  Length 2 * max(srcALen, srcBLen) - 1.   
+   * @param[in]  *pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2.   
+   * @param[in]  *pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen).   
+   * @return none.   
+   */
+
+  void arm_correlate_opt_q7(
+  q7_t * pSrcA,
+  uint32_t srcALen,
+  q7_t * pSrcB,
+  uint32_t srcBLen,
+  q7_t * pDst,
+  q15_t * pScratch1,
+  q15_t * pScratch2);
+
+
+  /**
+   * @brief Correlation of Q7 sequences.
+   * @param[in] *pSrcA points to the first input sequence.
+   * @param[in] srcALen length of the first input sequence.
+   * @param[in] *pSrcB points to the second input sequence.
+   * @param[in] srcBLen length of the second input sequence.
+   * @param[out] *pDst points to the block of output data  Length 2 * max(srcALen, srcBLen) - 1.
+   * @return none.
+   */
+
+  void arm_correlate_q7(
+  q7_t * pSrcA,
+  uint32_t srcALen,
+  q7_t * pSrcB,
+  uint32_t srcBLen,
+  q7_t * pDst);
+
+
+  /**
+   * @brief Instance structure for the floating-point sparse FIR filter.
+   */
+  typedef struct
+  {
+    uint16_t numTaps;             /**< number of coefficients in the filter. */
+    uint16_t stateIndex;          /**< state buffer index.  Points to the oldest sample in the state buffer. */
+    float32_t *pState;            /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */
+    float32_t *pCoeffs;           /**< points to the coefficient array. The array is of length numTaps.*/
+    uint16_t maxDelay;            /**< maximum offset specified by the pTapDelay array. */
+    int32_t *pTapDelay;           /**< points to the array of delay values.  The array is of length numTaps. */
+  } arm_fir_sparse_instance_f32;
+
+  /**
+   * @brief Instance structure for the Q31 sparse FIR filter.
+   */
+
+  typedef struct
+  {
+    uint16_t numTaps;             /**< number of coefficients in the filter. */
+    uint16_t stateIndex;          /**< state buffer index.  Points to the oldest sample in the state buffer. */
+    q31_t *pState;                /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */
+    q31_t *pCoeffs;               /**< points to the coefficient array. The array is of length numTaps.*/
+    uint16_t maxDelay;            /**< maximum offset specified by the pTapDelay array. */
+    int32_t *pTapDelay;           /**< points to the array of delay values.  The array is of length numTaps. */
+  } arm_fir_sparse_instance_q31;
+
+  /**
+   * @brief Instance structure for the Q15 sparse FIR filter.
+   */
+
+  typedef struct
+  {
+    uint16_t numTaps;             /**< number of coefficients in the filter. */
+    uint16_t stateIndex;          /**< state buffer index.  Points to the oldest sample in the state buffer. */
+    q15_t *pState;                /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */
+    q15_t *pCoeffs;               /**< points to the coefficient array. The array is of length numTaps.*/
+    uint16_t maxDelay;            /**< maximum offset specified by the pTapDelay array. */
+    int32_t *pTapDelay;           /**< points to the array of delay values.  The array is of length numTaps. */
+  } arm_fir_sparse_instance_q15;
+
+  /**
+   * @brief Instance structure for the Q7 sparse FIR filter.
+   */
+
+  typedef struct
+  {
+    uint16_t numTaps;             /**< number of coefficients in the filter. */
+    uint16_t stateIndex;          /**< state buffer index.  Points to the oldest sample in the state buffer. */
+    q7_t *pState;                 /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */
+    q7_t *pCoeffs;                /**< points to the coefficient array. The array is of length numTaps.*/
+    uint16_t maxDelay;            /**< maximum offset specified by the pTapDelay array. */
+    int32_t *pTapDelay;           /**< points to the array of delay values.  The array is of length numTaps. */
+  } arm_fir_sparse_instance_q7;
+
+  /**
+   * @brief Processing function for the floating-point sparse FIR filter.
+   * @param[in]  *S          points to an instance of the floating-point sparse FIR structure.
+   * @param[in]  *pSrc       points to the block of input data.
+   * @param[out] *pDst       points to the block of output data
+   * @param[in]  *pScratchIn points to a temporary buffer of size blockSize.
+   * @param[in]  blockSize   number of input samples to process per call.
+   * @return none.
+   */
+
+  void arm_fir_sparse_f32(
+  arm_fir_sparse_instance_f32 * S,
+  float32_t * pSrc,
+  float32_t * pDst,
+  float32_t * pScratchIn,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Initialization function for the floating-point sparse FIR filter.
+   * @param[in,out] *S         points to an instance of the floating-point sparse FIR structure.
+   * @param[in]     numTaps    number of nonzero coefficients in the filter.
+   * @param[in]     *pCoeffs   points to the array of filter coefficients.
+   * @param[in]     *pState    points to the state buffer.
+   * @param[in]     *pTapDelay points to the array of offset times.
+   * @param[in]     maxDelay   maximum offset time supported.
+   * @param[in]     blockSize  number of samples that will be processed per block.
+   * @return none
+   */
+
+  void arm_fir_sparse_init_f32(
+  arm_fir_sparse_instance_f32 * S,
+  uint16_t numTaps,
+  float32_t * pCoeffs,
+  float32_t * pState,
+  int32_t * pTapDelay,
+  uint16_t maxDelay,
+  uint32_t blockSize);
+
+  /**
+   * @brief Processing function for the Q31 sparse FIR filter.
+   * @param[in]  *S          points to an instance of the Q31 sparse FIR structure.
+   * @param[in]  *pSrc       points to the block of input data.
+   * @param[out] *pDst       points to the block of output data
+   * @param[in]  *pScratchIn points to a temporary buffer of size blockSize.
+   * @param[in]  blockSize   number of input samples to process per call.
+   * @return none.
+   */
+
+  void arm_fir_sparse_q31(
+  arm_fir_sparse_instance_q31 * S,
+  q31_t * pSrc,
+  q31_t * pDst,
+  q31_t * pScratchIn,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Initialization function for the Q31 sparse FIR filter.
+   * @param[in,out] *S         points to an instance of the Q31 sparse FIR structure.
+   * @param[in]     numTaps    number of nonzero coefficients in the filter.
+   * @param[in]     *pCoeffs   points to the array of filter coefficients.
+   * @param[in]     *pState    points to the state buffer.
+   * @param[in]     *pTapDelay points to the array of offset times.
+   * @param[in]     maxDelay   maximum offset time supported.
+   * @param[in]     blockSize  number of samples that will be processed per block.
+   * @return none
+   */
+
+  void arm_fir_sparse_init_q31(
+  arm_fir_sparse_instance_q31 * S,
+  uint16_t numTaps,
+  q31_t * pCoeffs,
+  q31_t * pState,
+  int32_t * pTapDelay,
+  uint16_t maxDelay,
+  uint32_t blockSize);
+
+  /**
+   * @brief Processing function for the Q15 sparse FIR filter.
+   * @param[in]  *S           points to an instance of the Q15 sparse FIR structure.
+   * @param[in]  *pSrc        points to the block of input data.
+   * @param[out] *pDst        points to the block of output data
+   * @param[in]  *pScratchIn  points to a temporary buffer of size blockSize.
+   * @param[in]  *pScratchOut points to a temporary buffer of size blockSize.
+   * @param[in]  blockSize    number of input samples to process per call.
+   * @return none.
+   */
+
+  void arm_fir_sparse_q15(
+  arm_fir_sparse_instance_q15 * S,
+  q15_t * pSrc,
+  q15_t * pDst,
+  q15_t * pScratchIn,
+  q31_t * pScratchOut,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief  Initialization function for the Q15 sparse FIR filter.
+   * @param[in,out] *S         points to an instance of the Q15 sparse FIR structure.
+   * @param[in]     numTaps    number of nonzero coefficients in the filter.
+   * @param[in]     *pCoeffs   points to the array of filter coefficients.
+   * @param[in]     *pState    points to the state buffer.
+   * @param[in]     *pTapDelay points to the array of offset times.
+   * @param[in]     maxDelay   maximum offset time supported.
+   * @param[in]     blockSize  number of samples that will be processed per block.
+   * @return none
+   */
+
+  void arm_fir_sparse_init_q15(
+  arm_fir_sparse_instance_q15 * S,
+  uint16_t numTaps,
+  q15_t * pCoeffs,
+  q15_t * pState,
+  int32_t * pTapDelay,
+  uint16_t maxDelay,
+  uint32_t blockSize);
+
+  /**
+   * @brief Processing function for the Q7 sparse FIR filter.
+   * @param[in]  *S           points to an instance of the Q7 sparse FIR structure.
+   * @param[in]  *pSrc        points to the block of input data.
+   * @param[out] *pDst        points to the block of output data
+   * @param[in]  *pScratchIn  points to a temporary buffer of size blockSize.
+   * @param[in]  *pScratchOut points to a temporary buffer of size blockSize.
+   * @param[in]  blockSize    number of input samples to process per call.
+   * @return none.
+   */
+
+  void arm_fir_sparse_q7(
+  arm_fir_sparse_instance_q7 * S,
+  q7_t * pSrc,
+  q7_t * pDst,
+  q7_t * pScratchIn,
+  q31_t * pScratchOut,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Initialization function for the Q7 sparse FIR filter.
+   * @param[in,out] *S         points to an instance of the Q7 sparse FIR structure.
+   * @param[in]     numTaps    number of nonzero coefficients in the filter.
+   * @param[in]     *pCoeffs   points to the array of filter coefficients.
+   * @param[in]     *pState    points to the state buffer.
+   * @param[in]     *pTapDelay points to the array of offset times.
+   * @param[in]     maxDelay   maximum offset time supported.
+   * @param[in]     blockSize  number of samples that will be processed per block.
+   * @return none
+   */
+
+  void arm_fir_sparse_init_q7(
+  arm_fir_sparse_instance_q7 * S,
+  uint16_t numTaps,
+  q7_t * pCoeffs,
+  q7_t * pState,
+  int32_t * pTapDelay,
+  uint16_t maxDelay,
+  uint32_t blockSize);
+
+
+  /*
+   * @brief  Floating-point sin_cos function.
+   * @param[in]  theta    input value in degrees 
+   * @param[out] *pSinVal points to the processed sine output. 
+   * @param[out] *pCosVal points to the processed cos output. 
+   * @return none.
+   */
+
+  void arm_sin_cos_f32(
+  float32_t theta,
+  float32_t * pSinVal,
+  float32_t * pCcosVal);
+
+  /*
+   * @brief  Q31 sin_cos function.
+   * @param[in]  theta    scaled input value in degrees 
+   * @param[out] *pSinVal points to the processed sine output. 
+   * @param[out] *pCosVal points to the processed cosine output. 
+   * @return none.
+   */
+
+  void arm_sin_cos_q31(
+  q31_t theta,
+  q31_t * pSinVal,
+  q31_t * pCosVal);
+
+
+  /**
+   * @brief  Floating-point complex conjugate.
+   * @param[in]  *pSrc points to the input vector
+   * @param[out]  *pDst points to the output vector
+   * @param[in]  numSamples number of complex samples in each vector
+   * @return none.
+   */
+
+  void arm_cmplx_conj_f32(
+  float32_t * pSrc,
+  float32_t * pDst,
+  uint32_t numSamples);
+
+  /**
+   * @brief  Q31 complex conjugate.
+   * @param[in]  *pSrc points to the input vector
+   * @param[out]  *pDst points to the output vector
+   * @param[in]  numSamples number of complex samples in each vector
+   * @return none.
+   */
+
+  void arm_cmplx_conj_q31(
+  q31_t * pSrc,
+  q31_t * pDst,
+  uint32_t numSamples);
+
+  /**
+   * @brief  Q15 complex conjugate.
+   * @param[in]  *pSrc points to the input vector
+   * @param[out]  *pDst points to the output vector
+   * @param[in]  numSamples number of complex samples in each vector
+   * @return none.
+   */
+
+  void arm_cmplx_conj_q15(
+  q15_t * pSrc,
+  q15_t * pDst,
+  uint32_t numSamples);
+
+
+
+  /**
+   * @brief  Floating-point complex magnitude squared
+   * @param[in]  *pSrc points to the complex input vector
+   * @param[out]  *pDst points to the real output vector
+   * @param[in]  numSamples number of complex samples in the input vector
+   * @return none.
+   */
+
+  void arm_cmplx_mag_squared_f32(
+  float32_t * pSrc,
+  float32_t * pDst,
+  uint32_t numSamples);
+
+  /**
+   * @brief  Q31 complex magnitude squared
+   * @param[in]  *pSrc points to the complex input vector
+   * @param[out]  *pDst points to the real output vector
+   * @param[in]  numSamples number of complex samples in the input vector
+   * @return none.
+   */
+
+  void arm_cmplx_mag_squared_q31(
+  q31_t * pSrc,
+  q31_t * pDst,
+  uint32_t numSamples);
+
+  /**
+   * @brief  Q15 complex magnitude squared
+   * @param[in]  *pSrc points to the complex input vector
+   * @param[out]  *pDst points to the real output vector
+   * @param[in]  numSamples number of complex samples in the input vector
+   * @return none.
+   */
+
+  void arm_cmplx_mag_squared_q15(
+  q15_t * pSrc,
+  q15_t * pDst,
+  uint32_t numSamples);
+
+
+ /**
+   * @ingroup groupController
+   */
+
+  /**
+   * @defgroup PID PID Motor Control
+   *
+   * A Proportional Integral Derivative (PID) controller is a generic feedback control 
+   * loop mechanism widely used in industrial control systems.
+   * A PID controller is the most commonly used type of feedback controller.
+   *
+   * This set of functions implements (PID) controllers
+   * for Q15, Q31, and floating-point data types.  The functions operate on a single sample
+   * of data and each call to the function returns a single processed value.
+   * <code>S</code> points to an instance of the PID control data structure.  <code>in</code>
+   * is the input sample value. The functions return the output value.
+   *
+   * \par Algorithm:
+   * <pre>
+   *    y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2]
+   *    A0 = Kp + Ki + Kd
+   *    A1 = (-Kp ) - (2 * Kd )
+   *    A2 = Kd  </pre>
+   *
+   * \par
+   * where \c Kp is proportional constant, \c Ki is Integral constant and \c Kd is Derivative constant
+   * 
+   * \par 
+   * \image html PID.gif "Proportional Integral Derivative Controller" 
+   *
+   * \par
+   * The PID controller calculates an "error" value as the difference between
+   * the measured output and the reference input.
+   * The controller attempts to minimize the error by adjusting the process control inputs.  
+   * The proportional value determines the reaction to the current error, 
+   * the integral value determines the reaction based on the sum of recent errors, 
+   * and the derivative value determines the reaction based on the rate at which the error has been changing.
+   *
+   * \par Instance Structure 
+   * The Gains A0, A1, A2 and state variables for a PID controller are stored together in an instance data structure. 
+   * A separate instance structure must be defined for each PID Controller. 
+   * There are separate instance structure declarations for each of the 3 supported data types. 
+   * 
+   * \par Reset Functions 
+   * There is also an associated reset function for each data type which clears the state array. 
+   *
+   * \par Initialization Functions 
+   * There is also an associated initialization function for each data type. 
+   * The initialization function performs the following operations: 
+   * - Initializes the Gains A0, A1, A2 from Kp,Ki, Kd gains.
+   * - Zeros out the values in the state buffer.   
+   * 
+   * \par 
+   * Instance structure cannot be placed into a const data section and it is recommended to use the initialization function. 
+   *
+   * \par Fixed-Point Behavior 
+   * Care must be taken when using the fixed-point versions of the PID Controller functions. 
+   * In particular, the overflow and saturation behavior of the accumulator used in each function must be considered. 
+   * Refer to the function specific documentation below for usage guidelines. 
+   */
+
+  /**
+   * @addtogroup PID
+   * @{
+   */
+
+  /**
+   * @brief  Process function for the floating-point PID Control.
+   * @param[in,out] *S is an instance of the floating-point PID Control structure
+   * @param[in] in input sample to process
+   * @return out processed output sample.
+   */
+
+
+  __STATIC_INLINE float32_t arm_pid_f32(
+  arm_pid_instance_f32 * S,
+  float32_t in)
+  {
+    float32_t out;
+
+    /* y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2]  */
+    out = (S->A0 * in) +
+      (S->A1 * S->state[0]) + (S->A2 * S->state[1]) + (S->state[2]);
+
+    /* Update state */
+    S->state[1] = S->state[0];
+    S->state[0] = in;
+    S->state[2] = out;
+
+    /* return to application */
+    return (out);
+
+  }
+
+  /**
+   * @brief  Process function for the Q31 PID Control.
+   * @param[in,out] *S points to an instance of the Q31 PID Control structure
+   * @param[in] in input sample to process
+   * @return out processed output sample.
+   *
+   * <b>Scaling and Overflow Behavior:</b> 
+   * \par 
+   * The function is implemented using an internal 64-bit accumulator. 
+   * The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit. 
+   * Thus, if the accumulator result overflows it wraps around rather than clip. 
+   * In order to avoid overflows completely the input signal must be scaled down by 2 bits as there are four additions. 
+   * After all multiply-accumulates are performed, the 2.62 accumulator is truncated to 1.32 format and then saturated to 1.31 format. 
+   */
+
+  __STATIC_INLINE q31_t arm_pid_q31(
+  arm_pid_instance_q31 * S,
+  q31_t in)
+  {
+    q63_t acc;
+    q31_t out;
+
+    /* acc = A0 * x[n]  */
+    acc = (q63_t) S->A0 * in;
+
+    /* acc += A1 * x[n-1] */
+    acc += (q63_t) S->A1 * S->state[0];
+
+    /* acc += A2 * x[n-2]  */
+    acc += (q63_t) S->A2 * S->state[1];
+
+    /* convert output to 1.31 format to add y[n-1] */
+    out = (q31_t) (acc >> 31u);
+
+    /* out += y[n-1] */
+    out += S->state[2];
+
+    /* Update state */
+    S->state[1] = S->state[0];
+    S->state[0] = in;
+    S->state[2] = out;
+
+    /* return to application */
+    return (out);
+
+  }
+
+  /**
+   * @brief  Process function for the Q15 PID Control.
+   * @param[in,out] *S points to an instance of the Q15 PID Control structure
+   * @param[in] in input sample to process
+   * @return out processed output sample.
+   *
+   * <b>Scaling and Overflow Behavior:</b> 
+   * \par 
+   * The function is implemented using a 64-bit internal accumulator. 
+   * Both Gains and state variables are represented in 1.15 format and multiplications yield a 2.30 result. 
+   * The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format. 
+   * There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved. 
+   * After all additions have been performed, the accumulator is truncated to 34.15 format by discarding low 15 bits. 
+   * Lastly, the accumulator is saturated to yield a result in 1.15 format.
+   */
+
+  __STATIC_INLINE q15_t arm_pid_q15(
+  arm_pid_instance_q15 * S,
+  q15_t in)
+  {
+    q63_t acc;
+    q15_t out;
+
+    /* Implementation of PID controller */
+
+#ifdef ARM_MATH_CM0
+
+    /* acc = A0 * x[n]  */
+    acc = ((q31_t) S->A0) * in;
+
+#else
+
+    /* acc = A0 * x[n]  */
+    acc = (q31_t) __SMUAD(S->A0, in);
+
+#endif
+
+#ifdef ARM_MATH_CM0
+
+    /* acc += A1 * x[n-1] + A2 * x[n-2]  */
+    acc += (q31_t) S->A1 * S->state[0];
+    acc += (q31_t) S->A2 * S->state[1];
+
+#else
+
+    /* acc += A1 * x[n-1] + A2 * x[n-2]  */
+    acc = __SMLALD(S->A1, (q31_t) __SIMD32(S->state), acc);
+
+#endif
+
+    /* acc += y[n-1] */
+    acc += (q31_t) S->state[2] << 15;
+
+    /* saturate the output */
+    out = (q15_t) (__SSAT((acc >> 15), 16));
+
+    /* Update state */
+    S->state[1] = S->state[0];
+    S->state[0] = in;
+    S->state[2] = out;
+
+    /* return to application */
+    return (out);
+
+  }
+
+  /**
+   * @} end of PID group
+   */
+
+
+  /**
+   * @brief Floating-point matrix inverse.
+   * @param[in]  *src points to the instance of the input floating-point matrix structure.
+   * @param[out] *dst points to the instance of the output floating-point matrix structure.
+   * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match.
+   * If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR.
+   */
+
+  arm_status arm_mat_inverse_f32(
+  const arm_matrix_instance_f32 * src,
+  arm_matrix_instance_f32 * dst);
+
+
+
+  /**
+   * @ingroup groupController
+   */
+
+
+  /**
+   * @defgroup clarke Vector Clarke Transform
+   * Forward Clarke transform converts the instantaneous stator phases into a two-coordinate time invariant vector.
+   * Generally the Clarke transform uses three-phase currents <code>Ia, Ib and Ic</code> to calculate currents
+   * in the two-phase orthogonal stator axis <code>Ialpha</code> and <code>Ibeta</code>.
+   * When <code>Ialpha</code> is superposed with <code>Ia</code> as shown in the figure below
+   * \image html clarke.gif Stator current space vector and its components in (a,b).
+   * and <code>Ia + Ib + Ic = 0</code>, in this condition <code>Ialpha</code> and <code>Ibeta</code>
+   * can be calculated using only <code>Ia</code> and <code>Ib</code>.
+   *
+   * The function operates on a single sample of data and each call to the function returns the processed output. 
+   * The library provides separate functions for Q31 and floating-point data types.
+   * \par Algorithm
+   * \image html clarkeFormula.gif
+   * where <code>Ia</code> and <code>Ib</code> are the instantaneous stator phases and
+   * <code>pIalpha</code> and <code>pIbeta</code> are the two coordinates of time invariant vector.
+   * \par Fixed-Point Behavior
+   * Care must be taken when using the Q31 version of the Clarke transform.
+   * In particular, the overflow and saturation behavior of the accumulator used must be considered.
+   * Refer to the function specific documentation below for usage guidelines.
+   */
+
+  /**
+   * @addtogroup clarke
+   * @{
+   */
+
+  /**
+   *
+   * @brief  Floating-point Clarke transform
+   * @param[in]       Ia       input three-phase coordinate <code>a</code>
+   * @param[in]       Ib       input three-phase coordinate <code>b</code>
+   * @param[out]      *pIalpha points to output two-phase orthogonal vector axis alpha
+   * @param[out]      *pIbeta  points to output two-phase orthogonal vector axis beta
+   * @return none.
+   */
+
+  __STATIC_INLINE void arm_clarke_f32(
+  float32_t Ia,
+  float32_t Ib,
+  float32_t * pIalpha,
+  float32_t * pIbeta)
+  {
+    /* Calculate pIalpha using the equation, pIalpha = Ia */
+    *pIalpha = Ia;
+
+    /* Calculate pIbeta using the equation, pIbeta = (1/sqrt(3)) * Ia + (2/sqrt(3)) * Ib */
+    *pIbeta =
+      ((float32_t) 0.57735026919 * Ia + (float32_t) 1.15470053838 * Ib);
+
+  }
+
+  /**
+   * @brief  Clarke transform for Q31 version
+   * @param[in]       Ia       input three-phase coordinate <code>a</code>
+   * @param[in]       Ib       input three-phase coordinate <code>b</code>
+   * @param[out]      *pIalpha points to output two-phase orthogonal vector axis alpha
+   * @param[out]      *pIbeta  points to output two-phase orthogonal vector axis beta
+   * @return none.
+   *
+   * <b>Scaling and Overflow Behavior:</b>
+   * \par
+   * The function is implemented using an internal 32-bit accumulator.
+   * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format.
+   * There is saturation on the addition, hence there is no risk of overflow.
+   */
+
+  __STATIC_INLINE void arm_clarke_q31(
+  q31_t Ia,
+  q31_t Ib,
+  q31_t * pIalpha,
+  q31_t * pIbeta)
+  {
+    q31_t product1, product2;                    /* Temporary variables used to store intermediate results */
+
+    /* Calculating pIalpha from Ia by equation pIalpha = Ia */
+    *pIalpha = Ia;
+
+    /* Intermediate product is calculated by (1/(sqrt(3)) * Ia) */
+    product1 = (q31_t) (((q63_t) Ia * 0x24F34E8B) >> 30);
+
+    /* Intermediate product is calculated by (2/sqrt(3) * Ib) */
+    product2 = (q31_t) (((q63_t) Ib * 0x49E69D16) >> 30);
+
+    /* pIbeta is calculated by adding the intermediate products */
+    *pIbeta = __QADD(product1, product2);
+  }
+
+  /**
+   * @} end of clarke group
+   */
+
+  /**
+   * @brief  Converts the elements of the Q7 vector to Q31 vector.
+   * @param[in]  *pSrc     input pointer
+   * @param[out]  *pDst    output pointer
+   * @param[in]  blockSize number of samples to process
+   * @return none.
+   */
+  void arm_q7_to_q31(
+  q7_t * pSrc,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+
+
+
+  /**
+   * @ingroup groupController
+   */
+
+  /**
+   * @defgroup inv_clarke Vector Inverse Clarke Transform
+   * Inverse Clarke transform converts the two-coordinate time invariant vector into instantaneous stator phases.
+   * 
+   * The function operates on a single sample of data and each call to the function returns the processed output. 
+   * The library provides separate functions for Q31 and floating-point data types.
+   * \par Algorithm
+   * \image html clarkeInvFormula.gif
+   * where <code>pIa</code> and <code>pIb</code> are the instantaneous stator phases and
+   * <code>Ialpha</code> and <code>Ibeta</code> are the two coordinates of time invariant vector.
+   * \par Fixed-Point Behavior
+   * Care must be taken when using the Q31 version of the Clarke transform.
+   * In particular, the overflow and saturation behavior of the accumulator used must be considered.
+   * Refer to the function specific documentation below for usage guidelines.
+   */
+
+  /**
+   * @addtogroup inv_clarke
+   * @{
+   */
+
+   /**
+   * @brief  Floating-point Inverse Clarke transform
+   * @param[in]       Ialpha  input two-phase orthogonal vector axis alpha
+   * @param[in]       Ibeta   input two-phase orthogonal vector axis beta
+   * @param[out]      *pIa    points to output three-phase coordinate <code>a</code>
+   * @param[out]      *pIb    points to output three-phase coordinate <code>b</code>
+   * @return none.
+   */
+
+
+  __STATIC_INLINE void arm_inv_clarke_f32(
+  float32_t Ialpha,
+  float32_t Ibeta,
+  float32_t * pIa,
+  float32_t * pIb)
+  {
+    /* Calculating pIa from Ialpha by equation pIa = Ialpha */
+    *pIa = Ialpha;
+
+    /* Calculating pIb from Ialpha and Ibeta by equation pIb = -(1/2) * Ialpha + (sqrt(3)/2) * Ibeta */
+    *pIb = -0.5 * Ialpha + (float32_t) 0.8660254039 *Ibeta;
+
+  }
+
+  /**
+   * @brief  Inverse Clarke transform for Q31 version 
+   * @param[in]       Ialpha  input two-phase orthogonal vector axis alpha
+   * @param[in]       Ibeta   input two-phase orthogonal vector axis beta
+   * @param[out]      *pIa    points to output three-phase coordinate <code>a</code>
+   * @param[out]      *pIb    points to output three-phase coordinate <code>b</code>
+   * @return none.
+   *
+   * <b>Scaling and Overflow Behavior:</b>
+   * \par
+   * The function is implemented using an internal 32-bit accumulator.
+   * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format.
+   * There is saturation on the subtraction, hence there is no risk of overflow.
+   */
+
+  __STATIC_INLINE void arm_inv_clarke_q31(
+  q31_t Ialpha,
+  q31_t Ibeta,
+  q31_t * pIa,
+  q31_t * pIb)
+  {
+    q31_t product1, product2;                    /* Temporary variables used to store intermediate results */
+
+    /* Calculating pIa from Ialpha by equation pIa = Ialpha */
+    *pIa = Ialpha;
+
+    /* Intermediate product is calculated by (1/(2*sqrt(3)) * Ia) */
+    product1 = (q31_t) (((q63_t) (Ialpha) * (0x40000000)) >> 31);
+
+    /* Intermediate product is calculated by (1/sqrt(3) * pIb) */
+    product2 = (q31_t) (((q63_t) (Ibeta) * (0x6ED9EBA1)) >> 31);
+
+    /* pIb is calculated by subtracting the products */
+    *pIb = __QSUB(product2, product1);
+
+  }
+
+  /**
+   * @} end of inv_clarke group
+   */
+
+  /**
+   * @brief  Converts the elements of the Q7 vector to Q15 vector.
+   * @param[in]  *pSrc     input pointer
+   * @param[out] *pDst     output pointer
+   * @param[in]  blockSize number of samples to process
+   * @return none.
+   */
+  void arm_q7_to_q15(
+  q7_t * pSrc,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+
+
+  /**
+   * @ingroup groupController
+   */
+
+  /**
+   * @defgroup park Vector Park Transform
+   *
+   * Forward Park transform converts the input two-coordinate vector to flux and torque components.
+   * The Park transform can be used to realize the transformation of the <code>Ialpha</code> and the <code>Ibeta</code> currents 
+   * from the stationary to the moving reference frame and control the spatial relationship between 
+   * the stator vector current and rotor flux vector.
+   * If we consider the d axis aligned with the rotor flux, the diagram below shows the 
+   * current vector and the relationship from the two reference frames:
+   * \image html park.gif "Stator current space vector and its component in (a,b) and in the d,q rotating reference frame"
+   *
+   * The function operates on a single sample of data and each call to the function returns the processed output. 
+   * The library provides separate functions for Q31 and floating-point data types.
+   * \par Algorithm
+   * \image html parkFormula.gif
+   * where <code>Ialpha</code> and <code>Ibeta</code> are the stator vector components,  
+   * <code>pId</code> and <code>pIq</code> are rotor vector components and <code>cosVal</code> and <code>sinVal</code> are the 
+   * cosine and sine values of theta (rotor flux position).
+   * \par Fixed-Point Behavior
+   * Care must be taken when using the Q31 version of the Park transform.
+   * In particular, the overflow and saturation behavior of the accumulator used must be considered.
+   * Refer to the function specific documentation below for usage guidelines.
+   */
+
+  /**
+   * @addtogroup park
+   * @{
+   */
+
+  /**
+   * @brief Floating-point Park transform
+   * @param[in]       Ialpha input two-phase vector coordinate alpha
+   * @param[in]       Ibeta  input two-phase vector coordinate beta
+   * @param[out]      *pId   points to output	rotor reference frame d
+   * @param[out]      *pIq   points to output	rotor reference frame q
+   * @param[in]       sinVal sine value of rotation angle theta
+   * @param[in]       cosVal cosine value of rotation angle theta
+   * @return none.
+   *
+   * The function implements the forward Park transform.
+   *
+   */
+
+  __STATIC_INLINE void arm_park_f32(
+  float32_t Ialpha,
+  float32_t Ibeta,
+  float32_t * pId,
+  float32_t * pIq,
+  float32_t sinVal,
+  float32_t cosVal)
+  {
+    /* Calculate pId using the equation, pId = Ialpha * cosVal + Ibeta * sinVal */
+    *pId = Ialpha * cosVal + Ibeta * sinVal;
+
+    /* Calculate pIq using the equation, pIq = - Ialpha * sinVal + Ibeta * cosVal */
+    *pIq = -Ialpha * sinVal + Ibeta * cosVal;
+
+  }
+
+  /**
+   * @brief  Park transform for Q31 version 
+   * @param[in]       Ialpha input two-phase vector coordinate alpha
+   * @param[in]       Ibeta  input two-phase vector coordinate beta
+   * @param[out]      *pId   points to output rotor reference frame d
+   * @param[out]      *pIq   points to output rotor reference frame q
+   * @param[in]       sinVal sine value of rotation angle theta
+   * @param[in]       cosVal cosine value of rotation angle theta
+   * @return none.
+   *
+   * <b>Scaling and Overflow Behavior:</b>
+   * \par
+   * The function is implemented using an internal 32-bit accumulator.
+   * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format.
+   * There is saturation on the addition and subtraction, hence there is no risk of overflow.
+   */
+
+
+  __STATIC_INLINE void arm_park_q31(
+  q31_t Ialpha,
+  q31_t Ibeta,
+  q31_t * pId,
+  q31_t * pIq,
+  q31_t sinVal,
+  q31_t cosVal)
+  {
+    q31_t product1, product2;                    /* Temporary variables used to store intermediate results */
+    q31_t product3, product4;                    /* Temporary variables used to store intermediate results */
+
+    /* Intermediate product is calculated by (Ialpha * cosVal) */
+    product1 = (q31_t) (((q63_t) (Ialpha) * (cosVal)) >> 31);
+
+    /* Intermediate product is calculated by (Ibeta * sinVal) */
+    product2 = (q31_t) (((q63_t) (Ibeta) * (sinVal)) >> 31);
+
+
+    /* Intermediate product is calculated by (Ialpha * sinVal) */
+    product3 = (q31_t) (((q63_t) (Ialpha) * (sinVal)) >> 31);
+
+    /* Intermediate product is calculated by (Ibeta * cosVal) */
+    product4 = (q31_t) (((q63_t) (Ibeta) * (cosVal)) >> 31);
+
+    /* Calculate pId by adding the two intermediate products 1 and 2 */
+    *pId = __QADD(product1, product2);
+
+    /* Calculate pIq by subtracting the two intermediate products 3 from 4 */
+    *pIq = __QSUB(product4, product3);
+  }
+
+  /**
+   * @} end of park group
+   */
+
+  /**
+   * @brief  Converts the elements of the Q7 vector to floating-point vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[out]  *pDst is output pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @return none.
+   */
+  void arm_q7_to_float(
+  q7_t * pSrc,
+  float32_t * pDst,
+  uint32_t blockSize);
+
+
+  /**
+   * @ingroup groupController
+   */
+
+  /**
+   * @defgroup inv_park Vector Inverse Park transform
+   * Inverse Park transform converts the input flux and torque components to two-coordinate vector.
+   *
+   * The function operates on a single sample of data and each call to the function returns the processed output. 
+   * The library provides separate functions for Q31 and floating-point data types.
+   * \par Algorithm
+   * \image html parkInvFormula.gif
+   * where <code>pIalpha</code> and <code>pIbeta</code> are the stator vector components,  
+   * <code>Id</code> and <code>Iq</code> are rotor vector components and <code>cosVal</code> and <code>sinVal</code> are the 
+   * cosine and sine values of theta (rotor flux position).
+   * \par Fixed-Point Behavior
+   * Care must be taken when using the Q31 version of the Park transform.
+   * In particular, the overflow and saturation behavior of the accumulator used must be considered.
+   * Refer to the function specific documentation below for usage guidelines.
+   */
+
+  /**
+   * @addtogroup inv_park
+   * @{
+   */
+
+   /**
+   * @brief  Floating-point Inverse Park transform
+   * @param[in]       Id        input coordinate of rotor reference frame d
+   * @param[in]       Iq        input coordinate of rotor reference frame q
+   * @param[out]      *pIalpha  points to output two-phase orthogonal vector axis alpha
+   * @param[out]      *pIbeta   points to output two-phase orthogonal vector axis beta
+   * @param[in]       sinVal    sine value of rotation angle theta
+   * @param[in]       cosVal    cosine value of rotation angle theta
+   * @return none.
+   */
+
+  __STATIC_INLINE void arm_inv_park_f32(
+  float32_t Id,
+  float32_t Iq,
+  float32_t * pIalpha,
+  float32_t * pIbeta,
+  float32_t sinVal,
+  float32_t cosVal)
+  {
+    /* Calculate pIalpha using the equation, pIalpha = Id * cosVal - Iq * sinVal */
+    *pIalpha = Id * cosVal - Iq * sinVal;
+
+    /* Calculate pIbeta using the equation, pIbeta = Id * sinVal + Iq * cosVal */
+    *pIbeta = Id * sinVal + Iq * cosVal;
+
+  }
+
+
+  /**
+   * @brief  Inverse Park transform for	Q31 version 
+   * @param[in]       Id        input coordinate of rotor reference frame d
+   * @param[in]       Iq        input coordinate of rotor reference frame q
+   * @param[out]      *pIalpha  points to output two-phase orthogonal vector axis alpha
+   * @param[out]      *pIbeta   points to output two-phase orthogonal vector axis beta
+   * @param[in]       sinVal    sine value of rotation angle theta
+   * @param[in]       cosVal    cosine value of rotation angle theta
+   * @return none.
+   *
+   * <b>Scaling and Overflow Behavior:</b>
+   * \par
+   * The function is implemented using an internal 32-bit accumulator.
+   * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format.
+   * There is saturation on the addition, hence there is no risk of overflow.
+   */
+
+
+  __STATIC_INLINE void arm_inv_park_q31(
+  q31_t Id,
+  q31_t Iq,
+  q31_t * pIalpha,
+  q31_t * pIbeta,
+  q31_t sinVal,
+  q31_t cosVal)
+  {
+    q31_t product1, product2;                    /* Temporary variables used to store intermediate results */
+    q31_t product3, product4;                    /* Temporary variables used to store intermediate results */
+
+    /* Intermediate product is calculated by (Id * cosVal) */
+    product1 = (q31_t) (((q63_t) (Id) * (cosVal)) >> 31);
+
+    /* Intermediate product is calculated by (Iq * sinVal) */
+    product2 = (q31_t) (((q63_t) (Iq) * (sinVal)) >> 31);
+
+
+    /* Intermediate product is calculated by (Id * sinVal) */
+    product3 = (q31_t) (((q63_t) (Id) * (sinVal)) >> 31);
+
+    /* Intermediate product is calculated by (Iq * cosVal) */
+    product4 = (q31_t) (((q63_t) (Iq) * (cosVal)) >> 31);
+
+    /* Calculate pIalpha by using the two intermediate products 1 and 2 */
+    *pIalpha = __QSUB(product1, product2);
+
+    /* Calculate pIbeta by using the two intermediate products 3 and 4 */
+    *pIbeta = __QADD(product4, product3);
+
+  }
+
+  /**
+   * @} end of Inverse park group
+   */
+
+
+  /**
+   * @brief  Converts the elements of the Q31 vector to floating-point vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[out]  *pDst is output pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @return none.
+   */
+  void arm_q31_to_float(
+  q31_t * pSrc,
+  float32_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @ingroup groupInterpolation
+   */
+
+  /**
+   * @defgroup LinearInterpolate Linear Interpolation
+   *
+   * Linear interpolation is a method of curve fitting using linear polynomials.
+   * Linear interpolation works by effectively drawing a straight line between two neighboring samples and returning the appropriate point along that line
+   *
+   * \par 
+   * \image html LinearInterp.gif "Linear interpolation"
+   *
+   * \par
+   * A  Linear Interpolate function calculates an output value(y), for the input(x)
+   * using linear interpolation of the input values x0, x1( nearest input values) and the output values y0 and y1(nearest output values)
+   *
+   * \par Algorithm:
+   * <pre>
+   *       y = y0 + (x - x0) * ((y1 - y0)/(x1-x0))
+   *       where x0, x1 are nearest values of input x
+   *             y0, y1 are nearest values to output y
+   * </pre>
+   *
+   * \par
+   * This set of functions implements Linear interpolation process
+   * for Q7, Q15, Q31, and floating-point data types.  The functions operate on a single
+   * sample of data and each call to the function returns a single processed value.
+   * <code>S</code> points to an instance of the Linear Interpolate function data structure.
+   * <code>x</code> is the input sample value. The functions returns the output value.
+   * 
+   * \par
+   * if x is outside of the table boundary, Linear interpolation returns first value of the table 
+   * if x is below input range and returns last value of table if x is above range.  
+   */
+
+  /**
+   * @addtogroup LinearInterpolate
+   * @{
+   */
+
+  /**
+   * @brief  Process function for the floating-point Linear Interpolation Function.
+   * @param[in,out] *S is an instance of the floating-point Linear Interpolation structure
+   * @param[in] x input sample to process
+   * @return y processed output sample.
+   *
+   */
+
+  __STATIC_INLINE float32_t arm_linear_interp_f32(
+  arm_linear_interp_instance_f32 * S,
+  float32_t x)
+  {
+
+    float32_t y;
+    float32_t x0, x1;                            /* Nearest input values */
+    float32_t y0, y1;                            /* Nearest output values */
+    float32_t xSpacing = S->xSpacing;            /* spacing between input values */
+    int32_t i;                                   /* Index variable */
+    float32_t *pYData = S->pYData;               /* pointer to output table */
+
+    /* Calculation of index */
+    i = (x - S->x1) / xSpacing;
+
+    if(i < 0)
+    {
+      /* Iniatilize output for below specified range as least output value of table */
+      y = pYData[0];
+    }
+    else if(i >= S->nValues)
+    {
+      /* Iniatilize output for above specified range as last output value of table */
+      y = pYData[S->nValues - 1];
+    }
+    else
+    {
+      /* Calculation of nearest input values */
+      x0 = S->x1 + i * xSpacing;
+      x1 = S->x1 + (i + 1) * xSpacing;
+
+      /* Read of nearest output values */
+      y0 = pYData[i];
+      y1 = pYData[i + 1];
+
+      /* Calculation of output */
+      y = y0 + (x - x0) * ((y1 - y0) / (x1 - x0));
+
+    }
+
+    /* returns output value */
+    return (y);
+  }
+
+   /**
+   *
+   * @brief  Process function for the Q31 Linear Interpolation Function.
+   * @param[in] *pYData  pointer to Q31 Linear Interpolation table
+   * @param[in] x input sample to process
+   * @param[in] nValues number of table values
+   * @return y processed output sample.
+   *
+   * \par
+   * Input sample <code>x</code> is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part.
+   * This function can support maximum of table size 2^12.
+   *
+   */
+
+
+  __STATIC_INLINE q31_t arm_linear_interp_q31(
+  q31_t * pYData,
+  q31_t x,
+  uint32_t nValues)
+  {
+    q31_t y;                                     /* output */
+    q31_t y0, y1;                                /* Nearest output values */
+    q31_t fract;                                 /* fractional part */
+    int32_t index;                               /* Index to read nearest output values */
+
+    /* Input is in 12.20 format */
+    /* 12 bits for the table index */
+    /* Index value calculation */
+    index = ((x & 0xFFF00000) >> 20);
+
+    if(index >= (nValues - 1))
+    {
+      return (pYData[nValues - 1]);
+    }
+    else if(index < 0)
+    {
+      return (pYData[0]);
+    }
+    else
+    {
+
+      /* 20 bits for the fractional part */
+      /* shift left by 11 to keep fract in 1.31 format */
+      fract = (x & 0x000FFFFF) << 11;
+
+      /* Read two nearest output values from the index in 1.31(q31) format */
+      y0 = pYData[index];
+      y1 = pYData[index + 1u];
+
+      /* Calculation of y0 * (1-fract) and y is in 2.30 format */
+      y = ((q31_t) ((q63_t) y0 * (0x7FFFFFFF - fract) >> 32));
+
+      /* Calculation of y0 * (1-fract) + y1 *fract and y is in 2.30 format */
+      y += ((q31_t) (((q63_t) y1 * fract) >> 32));
+
+      /* Convert y to 1.31 format */
+      return (y << 1u);
+
+    }
+
+  }
+
+  /**
+   *
+   * @brief  Process function for the Q15 Linear Interpolation Function.
+   * @param[in] *pYData  pointer to Q15 Linear Interpolation table
+   * @param[in] x input sample to process
+   * @param[in] nValues number of table values
+   * @return y processed output sample.
+   *
+   * \par
+   * Input sample <code>x</code> is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part.
+   * This function can support maximum of table size 2^12. 
+   *
+   */
+
+
+  __STATIC_INLINE q15_t arm_linear_interp_q15(
+  q15_t * pYData,
+  q31_t x,
+  uint32_t nValues)
+  {
+    q63_t y;                                     /* output */
+    q15_t y0, y1;                                /* Nearest output values */
+    q31_t fract;                                 /* fractional part */
+    int32_t index;                               /* Index to read nearest output values */
+
+    /* Input is in 12.20 format */
+    /* 12 bits for the table index */
+    /* Index value calculation */
+    index = ((x & 0xFFF00000) >> 20u);
+
+    if(index >= (nValues - 1))
+    {
+      return (pYData[nValues - 1]);
+    }
+    else if(index < 0)
+    {
+      return (pYData[0]);
+    }
+    else
+    {
+      /* 20 bits for the fractional part */
+      /* fract is in 12.20 format */
+      fract = (x & 0x000FFFFF);
+
+      /* Read two nearest output values from the index */
+      y0 = pYData[index];
+      y1 = pYData[index + 1u];
+
+      /* Calculation of y0 * (1-fract) and y is in 13.35 format */
+      y = ((q63_t) y0 * (0xFFFFF - fract));
+
+      /* Calculation of (y0 * (1-fract) + y1 * fract) and y is in 13.35 format */
+      y += ((q63_t) y1 * (fract));
+
+      /* convert y to 1.15 format */
+      return (y >> 20);
+    }
+
+
+  }
+
+  /**
+   *
+   * @brief  Process function for the Q7 Linear Interpolation Function.
+   * @param[in] *pYData  pointer to Q7 Linear Interpolation table
+   * @param[in] x input sample to process
+   * @param[in] nValues number of table values
+   * @return y processed output sample.
+   *
+   * \par
+   * Input sample <code>x</code> is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part.
+   * This function can support maximum of table size 2^12.
+   */
+
+
+  __STATIC_INLINE q7_t arm_linear_interp_q7(
+  q7_t * pYData,
+  q31_t x,
+  uint32_t nValues)
+  {
+    q31_t y;                                     /* output */
+    q7_t y0, y1;                                 /* Nearest output values */
+    q31_t fract;                                 /* fractional part */
+    int32_t index;                               /* Index to read nearest output values */
+
+    /* Input is in 12.20 format */
+    /* 12 bits for the table index */
+    /* Index value calculation */
+    index = ((x & 0xFFF00000) >> 20u);
+
+
+    if(index >= (nValues - 1))
+    {
+      return (pYData[nValues - 1]);
+    }
+    else if(index < 0)
+    {
+      return (pYData[0]);
+    }
+    else
+    {
+
+      /* 20 bits for the fractional part */
+      /* fract is in 12.20 format */
+      fract = (x & 0x000FFFFF);
+
+      /* Read two nearest output values from the index and are in 1.7(q7) format */
+      y0 = pYData[index];
+      y1 = pYData[index + 1u];
+
+      /* Calculation of y0 * (1-fract ) and y is in 13.27(q27) format */
+      y = ((y0 * (0xFFFFF - fract)));
+
+      /* Calculation of y1 * fract + y0 * (1-fract) and y is in 13.27(q27) format */
+      y += (y1 * fract);
+
+      /* convert y to 1.7(q7) format */
+      return (y >> 20u);
+
+    }
+
+  }
+  /**
+   * @} end of LinearInterpolate group
+   */
+
+  /**
+   * @brief  Fast approximation to the trigonometric sine function for floating-point data.
+   * @param[in] x input value in radians.
+   * @return  sin(x).
+   */
+
+  float32_t arm_sin_f32(
+  float32_t x);
+
+  /**
+   * @brief  Fast approximation to the trigonometric sine function for Q31 data.
+   * @param[in] x Scaled input value in radians.
+   * @return  sin(x).
+   */
+
+  q31_t arm_sin_q31(
+  q31_t x);
+
+  /**
+   * @brief  Fast approximation to the trigonometric sine function for Q15 data.
+   * @param[in] x Scaled input value in radians.
+   * @return  sin(x).
+   */
+
+  q15_t arm_sin_q15(
+  q15_t x);
+
+  /**
+   * @brief  Fast approximation to the trigonometric cosine function for floating-point data.
+   * @param[in] x input value in radians.
+   * @return  cos(x).
+   */
+
+  float32_t arm_cos_f32(
+  float32_t x);
+
+  /**
+   * @brief Fast approximation to the trigonometric cosine function for Q31 data.
+   * @param[in] x Scaled input value in radians.
+   * @return  cos(x).
+   */
+
+  q31_t arm_cos_q31(
+  q31_t x);
+
+  /**
+   * @brief  Fast approximation to the trigonometric cosine function for Q15 data.
+   * @param[in] x Scaled input value in radians.
+   * @return  cos(x).
+   */
+
+  q15_t arm_cos_q15(
+  q15_t x);
+
+
+  /**
+   * @ingroup groupFastMath
+   */
+
+
+  /**
+   * @defgroup SQRT Square Root
+   *
+   * Computes the square root of a number.
+   * There are separate functions for Q15, Q31, and floating-point data types.  
+   * The square root function is computed using the Newton-Raphson algorithm.
+   * This is an iterative algorithm of the form:
+   * <pre>
+   *      x1 = x0 - f(x0)/f'(x0)
+   * </pre>
+   * where <code>x1</code> is the current estimate,
+   * <code>x0</code> is the previous estimate and
+   * <code>f'(x0)</code> is the derivative of <code>f()</code> evaluated at <code>x0</code>.
+   * For the square root function, the algorithm reduces to:
+   * <pre>
+   *     x0 = in/2                         [initial guess]
+   *     x1 = 1/2 * ( x0 + in / x0)        [each iteration]
+   * </pre>
+   */
+
+
+  /**
+   * @addtogroup SQRT
+   * @{
+   */
+
+  /**
+   * @brief  Floating-point square root function.
+   * @param[in]  in     input value.
+   * @param[out] *pOut  square root of input value.
+   * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if
+   * <code>in</code> is negative value and returns zero output for negative values.
+   */
+
+  __STATIC_INLINE arm_status arm_sqrt_f32(
+  float32_t in,
+  float32_t * pOut)
+  {
+    if(in > 0)
+    {
+
+//    #if __FPU_USED
+    #if (__FPU_USED == 1) && defined ( __CC_ARM   )
+        *pOut = __sqrtf(in);
+    #elif (__FPU_USED == 1) && defined ( __TMS_740 )
+        *pOut = __builtin_sqrtf(in);
+    #else
+        *pOut = sqrtf(in);
+    #endif
+
+      return (ARM_MATH_SUCCESS);
+    }
+    else
+    {
+      *pOut = 0.0f;
+      return (ARM_MATH_ARGUMENT_ERROR);
+    }
+
+  }
+
+
+  /**
+   * @brief Q31 square root function.
+   * @param[in]   in    input value.  The range of the input value is [0 +1) or 0x00000000 to 0x7FFFFFFF.
+   * @param[out]  *pOut square root of input value.
+   * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if
+   * <code>in</code> is negative value and returns zero output for negative values.
+   */
+  arm_status arm_sqrt_q31(
+  q31_t in,
+  q31_t * pOut);
+
+  /**
+   * @brief  Q15 square root function.
+   * @param[in]   in     input value.  The range of the input value is [0 +1) or 0x0000 to 0x7FFF.
+   * @param[out]  *pOut  square root of input value.
+   * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if
+   * <code>in</code> is negative value and returns zero output for negative values.
+   */
+  arm_status arm_sqrt_q15(
+  q15_t in,
+  q15_t * pOut);
+
+  /**
+   * @} end of SQRT group
+   */
+
+
+
+
+
+
+  /**
+   * @brief floating-point Circular write function.
+   */
+
+  __STATIC_INLINE void arm_circularWrite_f32(
+  int32_t * circBuffer,
+  int32_t L,
+  uint16_t * writeOffset,
+  int32_t bufferInc,
+  const int32_t * src,
+  int32_t srcInc,
+  uint32_t blockSize)
+  {
+    uint32_t i = 0u;
+    int32_t wOffset;
+
+    /* Copy the value of Index pointer that points
+     * to the current location where the input samples to be copied */
+    wOffset = *writeOffset;
+
+    /* Loop over the blockSize */
+    i = blockSize;
+
+    while(i > 0u)
+    {
+      /* copy the input sample to the circular buffer */
+      circBuffer[wOffset] = *src;
+
+      /* Update the input pointer */
+      src += srcInc;
+
+      /* Circularly update wOffset.  Watch out for positive and negative value */
+      wOffset += bufferInc;
+      if(wOffset >= L)
+        wOffset -= L;
+
+      /* Decrement the loop counter */
+      i--;
+    }
+
+    /* Update the index pointer */
+    *writeOffset = wOffset;
+  }
+
+
+
+  /**
+   * @brief floating-point Circular Read function.
+   */
+  __STATIC_INLINE void arm_circularRead_f32(
+  int32_t * circBuffer,
+  int32_t L,
+  int32_t * readOffset,
+  int32_t bufferInc,
+  int32_t * dst,
+  int32_t * dst_base,
+  int32_t dst_length,
+  int32_t dstInc,
+  uint32_t blockSize)
+  {
+    uint32_t i = 0u;
+    int32_t rOffset, dst_end;
+
+    /* Copy the value of Index pointer that points
+     * to the current location from where the input samples to be read */
+    rOffset = *readOffset;
+    dst_end = (int32_t) (dst_base + dst_length);
+
+    /* Loop over the blockSize */
+    i = blockSize;
+
+    while(i > 0u)
+    {
+      /* copy the sample from the circular buffer to the destination buffer */
+      *dst = circBuffer[rOffset];
+
+      /* Update the input pointer */
+      dst += dstInc;
+
+      if(dst == (int32_t *) dst_end)
+      {
+        dst = dst_base;
+      }
+
+      /* Circularly update rOffset.  Watch out for positive and negative value  */
+      rOffset += bufferInc;
+
+      if(rOffset >= L)
+      {
+        rOffset -= L;
+      }
+
+      /* Decrement the loop counter */
+      i--;
+    }
+
+    /* Update the index pointer */
+    *readOffset = rOffset;
+  }
+
+  /**
+   * @brief Q15 Circular write function.
+   */
+
+  __STATIC_INLINE void arm_circularWrite_q15(
+  q15_t * circBuffer,
+  int32_t L,
+  uint16_t * writeOffset,
+  int32_t bufferInc,
+  const q15_t * src,
+  int32_t srcInc,
+  uint32_t blockSize)
+  {
+    uint32_t i = 0u;
+    int32_t wOffset;
+
+    /* Copy the value of Index pointer that points
+     * to the current location where the input samples to be copied */
+    wOffset = *writeOffset;
+
+    /* Loop over the blockSize */
+    i = blockSize;
+
+    while(i > 0u)
+    {
+      /* copy the input sample to the circular buffer */
+      circBuffer[wOffset] = *src;
+
+      /* Update the input pointer */
+      src += srcInc;
+
+      /* Circularly update wOffset.  Watch out for positive and negative value */
+      wOffset += bufferInc;
+      if(wOffset >= L)
+        wOffset -= L;
+
+      /* Decrement the loop counter */
+      i--;
+    }
+
+    /* Update the index pointer */
+    *writeOffset = wOffset;
+  }
+
+
+
+  /**
+   * @brief Q15 Circular Read function.
+   */
+  __STATIC_INLINE void arm_circularRead_q15(
+  q15_t * circBuffer,
+  int32_t L,
+  int32_t * readOffset,
+  int32_t bufferInc,
+  q15_t * dst,
+  q15_t * dst_base,
+  int32_t dst_length,
+  int32_t dstInc,
+  uint32_t blockSize)
+  {
+    uint32_t i = 0;
+    int32_t rOffset, dst_end;
+
+    /* Copy the value of Index pointer that points
+     * to the current location from where the input samples to be read */
+    rOffset = *readOffset;
+
+    dst_end = (int32_t) (dst_base + dst_length);
+
+    /* Loop over the blockSize */
+    i = blockSize;
+
+    while(i > 0u)
+    {
+      /* copy the sample from the circular buffer to the destination buffer */
+      *dst = circBuffer[rOffset];
+
+      /* Update the input pointer */
+      dst += dstInc;
+
+      if(dst == (q15_t *) dst_end)
+      {
+        dst = dst_base;
+      }
+
+      /* Circularly update wOffset.  Watch out for positive and negative value */
+      rOffset += bufferInc;
+
+      if(rOffset >= L)
+      {
+        rOffset -= L;
+      }
+
+      /* Decrement the loop counter */
+      i--;
+    }
+
+    /* Update the index pointer */
+    *readOffset = rOffset;
+  }
+
+
+  /**
+   * @brief Q7 Circular write function.
+   */
+
+  __STATIC_INLINE void arm_circularWrite_q7(
+  q7_t * circBuffer,
+  int32_t L,
+  uint16_t * writeOffset,
+  int32_t bufferInc,
+  const q7_t * src,
+  int32_t srcInc,
+  uint32_t blockSize)
+  {
+    uint32_t i = 0u;
+    int32_t wOffset;
+
+    /* Copy the value of Index pointer that points
+     * to the current location where the input samples to be copied */
+    wOffset = *writeOffset;
+
+    /* Loop over the blockSize */
+    i = blockSize;
+
+    while(i > 0u)
+    {
+      /* copy the input sample to the circular buffer */
+      circBuffer[wOffset] = *src;
+
+      /* Update the input pointer */
+      src += srcInc;
+
+      /* Circularly update wOffset.  Watch out for positive and negative value */
+      wOffset += bufferInc;
+      if(wOffset >= L)
+        wOffset -= L;
+
+      /* Decrement the loop counter */
+      i--;
+    }
+
+    /* Update the index pointer */
+    *writeOffset = wOffset;
+  }
+
+
+
+  /**
+   * @brief Q7 Circular Read function.
+   */
+  __STATIC_INLINE void arm_circularRead_q7(
+  q7_t * circBuffer,
+  int32_t L,
+  int32_t * readOffset,
+  int32_t bufferInc,
+  q7_t * dst,
+  q7_t * dst_base,
+  int32_t dst_length,
+  int32_t dstInc,
+  uint32_t blockSize)
+  {
+    uint32_t i = 0;
+    int32_t rOffset, dst_end;
+
+    /* Copy the value of Index pointer that points
+     * to the current location from where the input samples to be read */
+    rOffset = *readOffset;
+
+    dst_end = (int32_t) (dst_base + dst_length);
+
+    /* Loop over the blockSize */
+    i = blockSize;
+
+    while(i > 0u)
+    {
+      /* copy the sample from the circular buffer to the destination buffer */
+      *dst = circBuffer[rOffset];
+
+      /* Update the input pointer */
+      dst += dstInc;
+
+      if(dst == (q7_t *) dst_end)
+      {
+        dst = dst_base;
+      }
+
+      /* Circularly update rOffset.  Watch out for positive and negative value */
+      rOffset += bufferInc;
+
+      if(rOffset >= L)
+      {
+        rOffset -= L;
+      }
+
+      /* Decrement the loop counter */
+      i--;
+    }
+
+    /* Update the index pointer */
+    *readOffset = rOffset;
+  }
+
+
+  /**
+   * @brief  Sum of the squares of the elements of a Q31 vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output value.
+   * @return none.
+   */
+
+  void arm_power_q31(
+  q31_t * pSrc,
+  uint32_t blockSize,
+  q63_t * pResult);
+
+  /**
+   * @brief  Sum of the squares of the elements of a floating-point vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output value.
+   * @return none.
+   */
+
+  void arm_power_f32(
+  float32_t * pSrc,
+  uint32_t blockSize,
+  float32_t * pResult);
+
+  /**
+   * @brief  Sum of the squares of the elements of a Q15 vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output value.
+   * @return none.
+   */
+
+  void arm_power_q15(
+  q15_t * pSrc,
+  uint32_t blockSize,
+  q63_t * pResult);
+
+  /**
+   * @brief  Sum of the squares of the elements of a Q7 vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output value.
+   * @return none.
+   */
+
+  void arm_power_q7(
+  q7_t * pSrc,
+  uint32_t blockSize,
+  q31_t * pResult);
+
+  /**
+   * @brief  Mean value of a Q7 vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output value.
+   * @return none.
+   */
+
+  void arm_mean_q7(
+  q7_t * pSrc,
+  uint32_t blockSize,
+  q7_t * pResult);
+
+  /**
+   * @brief  Mean value of a Q15 vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output value.
+   * @return none.
+   */
+  void arm_mean_q15(
+  q15_t * pSrc,
+  uint32_t blockSize,
+  q15_t * pResult);
+
+  /**
+   * @brief  Mean value of a Q31 vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output value.
+   * @return none.
+   */
+  void arm_mean_q31(
+  q31_t * pSrc,
+  uint32_t blockSize,
+  q31_t * pResult);
+
+  /**
+   * @brief  Mean value of a floating-point vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output value.
+   * @return none.
+   */
+  void arm_mean_f32(
+  float32_t * pSrc,
+  uint32_t blockSize,
+  float32_t * pResult);
+
+  /**
+   * @brief  Variance of the elements of a floating-point vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output value.
+   * @return none.
+   */
+
+  void arm_var_f32(
+  float32_t * pSrc,
+  uint32_t blockSize,
+  float32_t * pResult);
+
+  /**
+   * @brief  Variance of the elements of a Q31 vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output value.
+   * @return none.
+   */
+
+  void arm_var_q31(
+  q31_t * pSrc,
+  uint32_t blockSize,
+  q63_t * pResult);
+
+  /**
+   * @brief  Variance of the elements of a Q15 vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output value.
+   * @return none.
+   */
+
+  void arm_var_q15(
+  q15_t * pSrc,
+  uint32_t blockSize,
+  q31_t * pResult);
+
+  /**
+   * @brief  Root Mean Square of the elements of a floating-point vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output value.
+   * @return none.
+   */
+
+  void arm_rms_f32(
+  float32_t * pSrc,
+  uint32_t blockSize,
+  float32_t * pResult);
+
+  /**
+   * @brief  Root Mean Square of the elements of a Q31 vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output value.
+   * @return none.
+   */
+
+  void arm_rms_q31(
+  q31_t * pSrc,
+  uint32_t blockSize,
+  q31_t * pResult);
+
+  /**
+   * @brief  Root Mean Square of the elements of a Q15 vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output value.
+   * @return none.
+   */
+
+  void arm_rms_q15(
+  q15_t * pSrc,
+  uint32_t blockSize,
+  q15_t * pResult);
+
+  /**
+   * @brief  Standard deviation of the elements of a floating-point vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output value.
+   * @return none.
+   */
+
+  void arm_std_f32(
+  float32_t * pSrc,
+  uint32_t blockSize,
+  float32_t * pResult);
+
+  /**
+   * @brief  Standard deviation of the elements of a Q31 vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output value.
+   * @return none.
+   */
+
+  void arm_std_q31(
+  q31_t * pSrc,
+  uint32_t blockSize,
+  q31_t * pResult);
+
+  /**
+   * @brief  Standard deviation of the elements of a Q15 vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output value.
+   * @return none.
+   */
+
+  void arm_std_q15(
+  q15_t * pSrc,
+  uint32_t blockSize,
+  q15_t * pResult);
+
+  /**
+   * @brief  Floating-point complex magnitude
+   * @param[in]  *pSrc points to the complex input vector
+   * @param[out]  *pDst points to the real output vector
+   * @param[in]  numSamples number of complex samples in the input vector
+   * @return none.
+   */
+
+  void arm_cmplx_mag_f32(
+  float32_t * pSrc,
+  float32_t * pDst,
+  uint32_t numSamples);
+
+  /**
+   * @brief  Q31 complex magnitude
+   * @param[in]  *pSrc points to the complex input vector
+   * @param[out]  *pDst points to the real output vector
+   * @param[in]  numSamples number of complex samples in the input vector
+   * @return none.
+   */
+
+  void arm_cmplx_mag_q31(
+  q31_t * pSrc,
+  q31_t * pDst,
+  uint32_t numSamples);
+
+  /**
+   * @brief  Q15 complex magnitude
+   * @param[in]  *pSrc points to the complex input vector
+   * @param[out]  *pDst points to the real output vector
+   * @param[in]  numSamples number of complex samples in the input vector
+   * @return none.
+   */
+
+  void arm_cmplx_mag_q15(
+  q15_t * pSrc,
+  q15_t * pDst,
+  uint32_t numSamples);
+
+  /**
+   * @brief  Q15 complex dot product
+   * @param[in]  *pSrcA points to the first input vector
+   * @param[in]  *pSrcB points to the second input vector
+   * @param[in]  numSamples number of complex samples in each vector
+   * @param[out]  *realResult real part of the result returned here
+   * @param[out]  *imagResult imaginary part of the result returned here
+   * @return none.
+   */
+
+  void arm_cmplx_dot_prod_q15(
+  q15_t * pSrcA,
+  q15_t * pSrcB,
+  uint32_t numSamples,
+  q31_t * realResult,
+  q31_t * imagResult);
+
+  /**
+   * @brief  Q31 complex dot product
+   * @param[in]  *pSrcA points to the first input vector
+   * @param[in]  *pSrcB points to the second input vector
+   * @param[in]  numSamples number of complex samples in each vector
+   * @param[out]  *realResult real part of the result returned here
+   * @param[out]  *imagResult imaginary part of the result returned here
+   * @return none.
+   */
+
+  void arm_cmplx_dot_prod_q31(
+  q31_t * pSrcA,
+  q31_t * pSrcB,
+  uint32_t numSamples,
+  q63_t * realResult,
+  q63_t * imagResult);
+
+  /**
+   * @brief  Floating-point complex dot product
+   * @param[in]  *pSrcA points to the first input vector
+   * @param[in]  *pSrcB points to the second input vector
+   * @param[in]  numSamples number of complex samples in each vector
+   * @param[out]  *realResult real part of the result returned here
+   * @param[out]  *imagResult imaginary part of the result returned here
+   * @return none.
+   */
+
+  void arm_cmplx_dot_prod_f32(
+  float32_t * pSrcA,
+  float32_t * pSrcB,
+  uint32_t numSamples,
+  float32_t * realResult,
+  float32_t * imagResult);
+
+  /**
+   * @brief  Q15 complex-by-real multiplication
+   * @param[in]  *pSrcCmplx points to the complex input vector
+   * @param[in]  *pSrcReal points to the real input vector
+   * @param[out]  *pCmplxDst points to the complex output vector
+   * @param[in]  numSamples number of samples in each vector
+   * @return none.
+   */
+
+  void arm_cmplx_mult_real_q15(
+  q15_t * pSrcCmplx,
+  q15_t * pSrcReal,
+  q15_t * pCmplxDst,
+  uint32_t numSamples);
+
+  /**
+   * @brief  Q31 complex-by-real multiplication
+   * @param[in]  *pSrcCmplx points to the complex input vector
+   * @param[in]  *pSrcReal points to the real input vector
+   * @param[out]  *pCmplxDst points to the complex output vector
+   * @param[in]  numSamples number of samples in each vector
+   * @return none.
+   */
+
+  void arm_cmplx_mult_real_q31(
+  q31_t * pSrcCmplx,
+  q31_t * pSrcReal,
+  q31_t * pCmplxDst,
+  uint32_t numSamples);
+
+  /**
+   * @brief  Floating-point complex-by-real multiplication
+   * @param[in]  *pSrcCmplx points to the complex input vector
+   * @param[in]  *pSrcReal points to the real input vector
+   * @param[out]  *pCmplxDst points to the complex output vector
+   * @param[in]  numSamples number of samples in each vector
+   * @return none.
+   */
+
+  void arm_cmplx_mult_real_f32(
+  float32_t * pSrcCmplx,
+  float32_t * pSrcReal,
+  float32_t * pCmplxDst,
+  uint32_t numSamples);
+
+  /**
+   * @brief  Minimum value of a Q7 vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *result is output pointer
+   * @param[in]  index is the array index of the minimum value in the input buffer.
+   * @return none.
+   */
+
+  void arm_min_q7(
+  q7_t * pSrc,
+  uint32_t blockSize,
+  q7_t * result,
+  uint32_t * index);
+
+  /**
+   * @brief  Minimum value of a Q15 vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output pointer
+   * @param[in]  *pIndex is the array index of the minimum value in the input buffer.
+   * @return none.
+   */
+
+  void arm_min_q15(
+  q15_t * pSrc,
+  uint32_t blockSize,
+  q15_t * pResult,
+  uint32_t * pIndex);
+
+  /**
+   * @brief  Minimum value of a Q31 vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output pointer
+   * @param[out]  *pIndex is the array index of the minimum value in the input buffer.
+   * @return none.
+   */
+  void arm_min_q31(
+  q31_t * pSrc,
+  uint32_t blockSize,
+  q31_t * pResult,
+  uint32_t * pIndex);
+
+  /**
+   * @brief  Minimum value of a floating-point vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @param[out]  *pResult is output pointer
+   * @param[out]  *pIndex is the array index of the minimum value in the input buffer.
+   * @return none.
+   */
+
+  void arm_min_f32(
+  float32_t * pSrc,
+  uint32_t blockSize,
+  float32_t * pResult,
+  uint32_t * pIndex);
+
+/**
+ * @brief Maximum value of a Q7 vector.
+ * @param[in]       *pSrc points to the input buffer
+ * @param[in]       blockSize length of the input vector
+ * @param[out]      *pResult maximum value returned here
+ * @param[out]      *pIndex index of maximum value returned here
+ * @return none.
+ */
+
+  void arm_max_q7(
+  q7_t * pSrc,
+  uint32_t blockSize,
+  q7_t * pResult,
+  uint32_t * pIndex);
+
+/**
+ * @brief Maximum value of a Q15 vector.
+ * @param[in]       *pSrc points to the input buffer
+ * @param[in]       blockSize length of the input vector
+ * @param[out]      *pResult maximum value returned here
+ * @param[out]      *pIndex index of maximum value returned here
+ * @return none.
+ */
+
+  void arm_max_q15(
+  q15_t * pSrc,
+  uint32_t blockSize,
+  q15_t * pResult,
+  uint32_t * pIndex);
+
+/**
+ * @brief Maximum value of a Q31 vector.
+ * @param[in]       *pSrc points to the input buffer
+ * @param[in]       blockSize length of the input vector
+ * @param[out]      *pResult maximum value returned here
+ * @param[out]      *pIndex index of maximum value returned here
+ * @return none.
+ */
+
+  void arm_max_q31(
+  q31_t * pSrc,
+  uint32_t blockSize,
+  q31_t * pResult,
+  uint32_t * pIndex);
+
+/**
+ * @brief Maximum value of a floating-point vector.
+ * @param[in]       *pSrc points to the input buffer
+ * @param[in]       blockSize length of the input vector
+ * @param[out]      *pResult maximum value returned here
+ * @param[out]      *pIndex index of maximum value returned here
+ * @return none.
+ */
+
+  void arm_max_f32(
+  float32_t * pSrc,
+  uint32_t blockSize,
+  float32_t * pResult,
+  uint32_t * pIndex);
+
+  /**
+   * @brief  Q15 complex-by-complex multiplication
+   * @param[in]  *pSrcA points to the first input vector
+   * @param[in]  *pSrcB points to the second input vector
+   * @param[out]  *pDst  points to the output vector
+   * @param[in]  numSamples number of complex samples in each vector
+   * @return none.
+   */
+
+  void arm_cmplx_mult_cmplx_q15(
+  q15_t * pSrcA,
+  q15_t * pSrcB,
+  q15_t * pDst,
+  uint32_t numSamples);
+
+  /**
+   * @brief  Q31 complex-by-complex multiplication
+   * @param[in]  *pSrcA points to the first input vector
+   * @param[in]  *pSrcB points to the second input vector
+   * @param[out]  *pDst  points to the output vector
+   * @param[in]  numSamples number of complex samples in each vector
+   * @return none.
+   */
+
+  void arm_cmplx_mult_cmplx_q31(
+  q31_t * pSrcA,
+  q31_t * pSrcB,
+  q31_t * pDst,
+  uint32_t numSamples);
+
+  /**
+   * @brief  Floating-point complex-by-complex multiplication
+   * @param[in]  *pSrcA points to the first input vector
+   * @param[in]  *pSrcB points to the second input vector
+   * @param[out]  *pDst  points to the output vector
+   * @param[in]  numSamples number of complex samples in each vector
+   * @return none.
+   */
+
+  void arm_cmplx_mult_cmplx_f32(
+  float32_t * pSrcA,
+  float32_t * pSrcB,
+  float32_t * pDst,
+  uint32_t numSamples);
+
+  /**
+   * @brief Converts the elements of the floating-point vector to Q31 vector. 
+   * @param[in]       *pSrc points to the floating-point input vector 
+   * @param[out]      *pDst points to the Q31 output vector
+   * @param[in]       blockSize length of the input vector 
+   * @return none. 
+   */
+  void arm_float_to_q31(
+  float32_t * pSrc,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Converts the elements of the floating-point vector to Q15 vector. 
+   * @param[in]       *pSrc points to the floating-point input vector 
+   * @param[out]      *pDst points to the Q15 output vector
+   * @param[in]       blockSize length of the input vector 
+   * @return          none
+   */
+  void arm_float_to_q15(
+  float32_t * pSrc,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief Converts the elements of the floating-point vector to Q7 vector. 
+   * @param[in]       *pSrc points to the floating-point input vector 
+   * @param[out]      *pDst points to the Q7 output vector
+   * @param[in]       blockSize length of the input vector 
+   * @return          none
+   */
+  void arm_float_to_q7(
+  float32_t * pSrc,
+  q7_t * pDst,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief  Converts the elements of the Q31 vector to Q15 vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[out]  *pDst is output pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @return none.
+   */
+  void arm_q31_to_q15(
+  q31_t * pSrc,
+  q15_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Converts the elements of the Q31 vector to Q7 vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[out]  *pDst is output pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @return none.
+   */
+  void arm_q31_to_q7(
+  q31_t * pSrc,
+  q7_t * pDst,
+  uint32_t blockSize);
+
+  /**
+   * @brief  Converts the elements of the Q15 vector to floating-point vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[out]  *pDst is output pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @return none.
+   */
+  void arm_q15_to_float(
+  q15_t * pSrc,
+  float32_t * pDst,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief  Converts the elements of the Q15 vector to Q31 vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[out]  *pDst is output pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @return none.
+   */
+  void arm_q15_to_q31(
+  q15_t * pSrc,
+  q31_t * pDst,
+  uint32_t blockSize);
+
+
+  /**
+   * @brief  Converts the elements of the Q15 vector to Q7 vector.
+   * @param[in]  *pSrc is input pointer
+   * @param[out]  *pDst is output pointer
+   * @param[in]  blockSize is the number of samples to process
+   * @return none.
+   */
+  void arm_q15_to_q7(
+  q15_t * pSrc,
+  q7_t * pDst,
+  uint32_t blockSize);
+
+
+  /**
+   * @ingroup groupInterpolation
+   */
+
+  /**
+   * @defgroup BilinearInterpolate Bilinear Interpolation
+   *
+   * Bilinear interpolation is an extension of linear interpolation applied to a two dimensional grid.
+   * The underlying function <code>f(x, y)</code> is sampled on a regular grid and the interpolation process
+   * determines values between the grid points.
+   * Bilinear interpolation is equivalent to two step linear interpolation, first in the x-dimension and then in the y-dimension.
+   * Bilinear interpolation is often used in image processing to rescale images.
+   * The CMSIS DSP library provides bilinear interpolation functions for Q7, Q15, Q31, and floating-point data types.
+   *
+   * <b>Algorithm</b>
+   * \par
+   * The instance structure used by the bilinear interpolation functions describes a two dimensional data table.
+   * For floating-point, the instance structure is defined as:
+   * <pre>
+   *   typedef struct
+   *   {
+   *     uint16_t numRows;
+   *     uint16_t numCols;
+   *     float32_t *pData;
+   * } arm_bilinear_interp_instance_f32;
+   * </pre>
+   *
+   * \par
+   * where <code>numRows</code> specifies the number of rows in the table;
+   * <code>numCols</code> specifies the number of columns in the table;
+   * and <code>pData</code> points to an array of size <code>numRows*numCols</code> values.
+   * The data table <code>pTable</code> is organized in row order and the supplied data values fall on integer indexes.
+   * That is, table element (x,y) is located at <code>pTable[x + y*numCols]</code> where x and y are integers.
+   *
+   * \par
+   * Let <code>(x, y)</code> specify the desired interpolation point.  Then define:
+   * <pre>
+   *     XF = floor(x)
+   *     YF = floor(y)
+   * </pre>
+   * \par
+   * The interpolated output point is computed as:
+   * <pre>
+   *  f(x, y) = f(XF, YF) * (1-(x-XF)) * (1-(y-YF))
+   *           + f(XF+1, YF) * (x-XF)*(1-(y-YF))
+   *           + f(XF, YF+1) * (1-(x-XF))*(y-YF)
+   *           + f(XF+1, YF+1) * (x-XF)*(y-YF)
+   * </pre>
+   * Note that the coordinates (x, y) contain integer and fractional components.  
+   * The integer components specify which portion of the table to use while the
+   * fractional components control the interpolation processor.
+   *
+   * \par
+   * if (x,y) are outside of the table boundary, Bilinear interpolation returns zero output. 
+   */
+
+  /**
+   * @addtogroup BilinearInterpolate
+   * @{
+   */
+
+  /**
+  *
+  * @brief  Floating-point bilinear interpolation.
+  * @param[in,out] *S points to an instance of the interpolation structure.
+  * @param[in] X interpolation coordinate.
+  * @param[in] Y interpolation coordinate.
+  * @return out interpolated value.
+  */
+
+
+  __STATIC_INLINE float32_t arm_bilinear_interp_f32(
+  const arm_bilinear_interp_instance_f32 * S,
+  float32_t X,
+  float32_t Y)
+  {
+    float32_t out;
+    float32_t f00, f01, f10, f11;
+    float32_t *pData = S->pData;
+    int32_t xIndex, yIndex, index;
+    float32_t xdiff, ydiff;
+    float32_t b1, b2, b3, b4;
+
+    xIndex = (int32_t) X;
+    yIndex = (int32_t) Y;
+
+    /* Care taken for table outside boundary */
+    /* Returns zero output when values are outside table boundary */
+    if(xIndex < 0 || xIndex > (S->numRows - 1) || yIndex < 0
+       || yIndex > (S->numCols - 1))
+    {
+      return (0);
+    }
+
+    /* Calculation of index for two nearest points in X-direction */
+    index = (xIndex - 1) + (yIndex - 1) * S->numCols;
+
+
+    /* Read two nearest points in X-direction */
+    f00 = pData[index];
+    f01 = pData[index + 1];
+
+    /* Calculation of index for two nearest points in Y-direction */
+    index = (xIndex - 1) + (yIndex) * S->numCols;
+
+
+    /* Read two nearest points in Y-direction */
+    f10 = pData[index];
+    f11 = pData[index + 1];
+
+    /* Calculation of intermediate values */
+    b1 = f00;
+    b2 = f01 - f00;
+    b3 = f10 - f00;
+    b4 = f00 - f01 - f10 + f11;
+
+    /* Calculation of fractional part in X */
+    xdiff = X - xIndex;
+
+    /* Calculation of fractional part in Y */
+    ydiff = Y - yIndex;
+
+    /* Calculation of bi-linear interpolated output */
+    out = b1 + b2 * xdiff + b3 * ydiff + b4 * xdiff * ydiff;
+
+    /* return to application */
+    return (out);
+
+  }
+
+  /**
+  *
+  * @brief  Q31 bilinear interpolation.
+  * @param[in,out] *S points to an instance of the interpolation structure.
+  * @param[in] X interpolation coordinate in 12.20 format.
+  * @param[in] Y interpolation coordinate in 12.20 format.
+  * @return out interpolated value.
+  */
+
+  __STATIC_INLINE q31_t arm_bilinear_interp_q31(
+  arm_bilinear_interp_instance_q31 * S,
+  q31_t X,
+  q31_t Y)
+  {
+    q31_t out;                                   /* Temporary output */
+    q31_t acc = 0;                               /* output */
+    q31_t xfract, yfract;                        /* X, Y fractional parts */
+    q31_t x1, x2, y1, y2;                        /* Nearest output values */
+    int32_t rI, cI;                              /* Row and column indices */
+    q31_t *pYData = S->pData;                    /* pointer to output table values */
+    uint32_t nCols = S->numCols;                 /* num of rows */
+
+
+    /* Input is in 12.20 format */
+    /* 12 bits for the table index */
+    /* Index value calculation */
+    rI = ((X & 0xFFF00000) >> 20u);
+
+    /* Input is in 12.20 format */
+    /* 12 bits for the table index */
+    /* Index value calculation */
+    cI = ((Y & 0xFFF00000) >> 20u);
+
+    /* Care taken for table outside boundary */
+    /* Returns zero output when values are outside table boundary */
+    if(rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1))
+    {
+      return (0);
+    }
+
+    /* 20 bits for the fractional part */
+    /* shift left xfract by 11 to keep 1.31 format */
+    xfract = (X & 0x000FFFFF) << 11u;
+
+    /* Read two nearest output values from the index */
+    x1 = pYData[(rI) + nCols * (cI)];
+    x2 = pYData[(rI) + nCols * (cI) + 1u];
+
+    /* 20 bits for the fractional part */
+    /* shift left yfract by 11 to keep 1.31 format */
+    yfract = (Y & 0x000FFFFF) << 11u;
+
+    /* Read two nearest output values from the index */
+    y1 = pYData[(rI) + nCols * (cI + 1)];
+    y2 = pYData[(rI) + nCols * (cI + 1) + 1u];
+
+    /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 3.29(q29) format */
+    out = ((q31_t) (((q63_t) x1 * (0x7FFFFFFF - xfract)) >> 32));
+    acc = ((q31_t) (((q63_t) out * (0x7FFFFFFF - yfract)) >> 32));
+
+    /* x2 * (xfract) * (1-yfract)  in 3.29(q29) and adding to acc */
+    out = ((q31_t) ((q63_t) x2 * (0x7FFFFFFF - yfract) >> 32));
+    acc += ((q31_t) ((q63_t) out * (xfract) >> 32));
+
+    /* y1 * (1 - xfract) * (yfract)  in 3.29(q29) and adding to acc */
+    out = ((q31_t) ((q63_t) y1 * (0x7FFFFFFF - xfract) >> 32));
+    acc += ((q31_t) ((q63_t) out * (yfract) >> 32));
+
+    /* y2 * (xfract) * (yfract)  in 3.29(q29) and adding to acc */
+    out = ((q31_t) ((q63_t) y2 * (xfract) >> 32));
+    acc += ((q31_t) ((q63_t) out * (yfract) >> 32));
+
+    /* Convert acc to 1.31(q31) format */
+    return (acc << 2u);
+
+  }
+
+  /**
+  * @brief  Q15 bilinear interpolation.
+  * @param[in,out] *S points to an instance of the interpolation structure.
+  * @param[in] X interpolation coordinate in 12.20 format.
+  * @param[in] Y interpolation coordinate in 12.20 format.
+  * @return out interpolated value.
+  */
+
+  __STATIC_INLINE q15_t arm_bilinear_interp_q15(
+  arm_bilinear_interp_instance_q15 * S,
+  q31_t X,
+  q31_t Y)
+  {
+    q63_t acc = 0;                               /* output */
+    q31_t out;                                   /* Temporary output */
+    q15_t x1, x2, y1, y2;                        /* Nearest output values */
+    q31_t xfract, yfract;                        /* X, Y fractional parts */
+    int32_t rI, cI;                              /* Row and column indices */
+    q15_t *pYData = S->pData;                    /* pointer to output table values */
+    uint32_t nCols = S->numCols;                 /* num of rows */
+
+    /* Input is in 12.20 format */
+    /* 12 bits for the table index */
+    /* Index value calculation */
+    rI = ((X & 0xFFF00000) >> 20);
+
+    /* Input is in 12.20 format */
+    /* 12 bits for the table index */
+    /* Index value calculation */
+    cI = ((Y & 0xFFF00000) >> 20);
+
+    /* Care taken for table outside boundary */
+    /* Returns zero output when values are outside table boundary */
+    if(rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1))
+    {
+      return (0);
+    }
+
+    /* 20 bits for the fractional part */
+    /* xfract should be in 12.20 format */
+    xfract = (X & 0x000FFFFF);
+
+    /* Read two nearest output values from the index */
+    x1 = pYData[(rI) + nCols * (cI)];
+    x2 = pYData[(rI) + nCols * (cI) + 1u];
+
+
+    /* 20 bits for the fractional part */
+    /* yfract should be in 12.20 format */
+    yfract = (Y & 0x000FFFFF);
+
+    /* Read two nearest output values from the index */
+    y1 = pYData[(rI) + nCols * (cI + 1)];
+    y2 = pYData[(rI) + nCols * (cI + 1) + 1u];
+
+    /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 13.51 format */
+
+    /* x1 is in 1.15(q15), xfract in 12.20 format and out is in 13.35 format */
+    /* convert 13.35 to 13.31 by right shifting  and out is in 1.31 */
+    out = (q31_t) (((q63_t) x1 * (0xFFFFF - xfract)) >> 4u);
+    acc = ((q63_t) out * (0xFFFFF - yfract));
+
+    /* x2 * (xfract) * (1-yfract)  in 1.51 and adding to acc */
+    out = (q31_t) (((q63_t) x2 * (0xFFFFF - yfract)) >> 4u);
+    acc += ((q63_t) out * (xfract));
+
+    /* y1 * (1 - xfract) * (yfract)  in 1.51 and adding to acc */
+    out = (q31_t) (((q63_t) y1 * (0xFFFFF - xfract)) >> 4u);
+    acc += ((q63_t) out * (yfract));
+
+    /* y2 * (xfract) * (yfract)  in 1.51 and adding to acc */
+    out = (q31_t) (((q63_t) y2 * (xfract)) >> 4u);
+    acc += ((q63_t) out * (yfract));
+
+    /* acc is in 13.51 format and down shift acc by 36 times */
+    /* Convert out to 1.15 format */
+    return (acc >> 36);
+
+  }
+
+  /**
+  * @brief  Q7 bilinear interpolation.
+  * @param[in,out] *S points to an instance of the interpolation structure.
+  * @param[in] X interpolation coordinate in 12.20 format.
+  * @param[in] Y interpolation coordinate in 12.20 format.
+  * @return out interpolated value.
+  */
+
+  __STATIC_INLINE q7_t arm_bilinear_interp_q7(
+  arm_bilinear_interp_instance_q7 * S,
+  q31_t X,
+  q31_t Y)
+  {
+    q63_t acc = 0;                               /* output */
+    q31_t out;                                   /* Temporary output */
+    q31_t xfract, yfract;                        /* X, Y fractional parts */
+    q7_t x1, x2, y1, y2;                         /* Nearest output values */
+    int32_t rI, cI;                              /* Row and column indices */
+    q7_t *pYData = S->pData;                     /* pointer to output table values */
+    uint32_t nCols = S->numCols;                 /* num of rows */
+
+    /* Input is in 12.20 format */
+    /* 12 bits for the table index */
+    /* Index value calculation */
+    rI = ((X & 0xFFF00000) >> 20);
+
+    /* Input is in 12.20 format */
+    /* 12 bits for the table index */
+    /* Index value calculation */
+    cI = ((Y & 0xFFF00000) >> 20);
+
+    /* Care taken for table outside boundary */
+    /* Returns zero output when values are outside table boundary */
+    if(rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1))
+    {
+      return (0);
+    }
+
+    /* 20 bits for the fractional part */
+    /* xfract should be in 12.20 format */
+    xfract = (X & 0x000FFFFF);
+
+    /* Read two nearest output values from the index */
+    x1 = pYData[(rI) + nCols * (cI)];
+    x2 = pYData[(rI) + nCols * (cI) + 1u];
+
+
+    /* 20 bits for the fractional part */
+    /* yfract should be in 12.20 format */
+    yfract = (Y & 0x000FFFFF);
+
+    /* Read two nearest output values from the index */
+    y1 = pYData[(rI) + nCols * (cI + 1)];
+    y2 = pYData[(rI) + nCols * (cI + 1) + 1u];
+
+    /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 16.47 format */
+    out = ((x1 * (0xFFFFF - xfract)));
+    acc = (((q63_t) out * (0xFFFFF - yfract)));
+
+    /* x2 * (xfract) * (1-yfract)  in 2.22 and adding to acc */
+    out = ((x2 * (0xFFFFF - yfract)));
+    acc += (((q63_t) out * (xfract)));
+
+    /* y1 * (1 - xfract) * (yfract)  in 2.22 and adding to acc */
+    out = ((y1 * (0xFFFFF - xfract)));
+    acc += (((q63_t) out * (yfract)));
+
+    /* y2 * (xfract) * (yfract)  in 2.22 and adding to acc */
+    out = ((y2 * (yfract)));
+    acc += (((q63_t) out * (xfract)));
+
+    /* acc in 16.47 format and down shift by 40 to convert to 1.7 format */
+    return (acc >> 40);
+
+  }
+
+  /**
+   * @} end of BilinearInterpolate group
+   */
+
+
+
+
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+
+#endif /* _ARM_MATH_H */
+
+
+/**
+ *
+ * End of file.
+ */
diff --git a/teensy3/avr/eeprom.h b/teensy3/avr/eeprom.h
new file mode 100644
index 0000000000000000000000000000000000000000..d63ec09216cb7d079d77c6c37742a88081f39748
--- /dev/null
+++ b/teensy3/avr/eeprom.h
@@ -0,0 +1,9 @@
+#ifndef _AVR_EEPROM_H_
+#define _AVR_EEPROM_H_ 1
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define E2END 0x80
+
+#endif
diff --git a/teensy3/avr/interrupt.h b/teensy3/avr/interrupt.h
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/teensy3/avr/io.h b/teensy3/avr/io.h
new file mode 100644
index 0000000000000000000000000000000000000000..489948146bf84d6cb93992d4971ee8585418a8e1
--- /dev/null
+++ b/teensy3/avr/io.h
@@ -0,0 +1 @@
+#include "../avr_emulation.h"
diff --git a/teensy3/avr/pgmspace.h b/teensy3/avr/pgmspace.h
new file mode 100644
index 0000000000000000000000000000000000000000..7594d6dfbcfff0afd1fe892388a5503d3eadd6bb
--- /dev/null
+++ b/teensy3/avr/pgmspace.h
@@ -0,0 +1,44 @@
+#ifndef __PGMSPACE_H_
+#define __PGMSPACE_H_ 1
+
+#include <inttypes.h>
+
+#define PROGMEM
+#define PGM_P  const char *
+#define PSTR(str) (str)
+
+#define _SFR_BYTE(n) (n)
+
+typedef void prog_void;
+typedef char prog_char;
+typedef unsigned char prog_uchar;
+typedef int8_t prog_int8_t;
+typedef uint8_t prog_uint8_t;
+typedef int16_t prog_int16_t;
+typedef uint16_t prog_uint16_t;
+typedef int32_t prog_int32_t;
+typedef uint32_t prog_uint32_t;
+
+#define memcpy_P(dest, src, num) memcpy((dest), (src), (num))
+#define strcpy_P(dest, src) strcpy((dest), (src))
+#define strcat_P(dest, src) strcat((dest), (src))
+#define strcmp_P(a, b) strcmp((a), (b))
+#define strstr_P(a, b) strstr((a), (b))
+#define strlen_P(s) strlen((const char *)(s))
+#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
diff --git a/teensy3/avr_emulation.h b/teensy3/avr_emulation.h
new file mode 100644
index 0000000000000000000000000000000000000000..98cf9e10f0aacfde3bd46e1dc3347588fedf380d
--- /dev/null
+++ b/teensy3/avr_emulation.h
@@ -0,0 +1,1125 @@
+/* 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_emulation_h_
+#define _avr_emulation_h_
+
+#include "mk20dx128.h"
+#include "core_pins.h"
+#include "pins_arduino.h"
+
+#ifdef __cplusplus
+
+#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000)
+#define GPIO_BITBAND(reg, bit) (*(uint32_t *)GPIO_BITBAND_ADDR((reg), (bit)))
+#define CONFIG_PULLUP (PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS)
+#define CONFIG_NOPULLUP (PORT_PCR_MUX(1))
+
+class PORTDemulation
+{
+public:
+	inline PORTDemulation & operator = (int val) __attribute__((always_inline)) {
+		digitalWriteFast(0, (val & (1<<0)));
+		if (!(CORE_PIN0_DDRREG & CORE_PIN0_BIT)) 
+			CORE_PIN0_CONFIG = ((val & (1<<0)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		digitalWriteFast(1, (val & (1<<1)));
+		if (!(CORE_PIN1_DDRREG & CORE_PIN1_BIT)) 
+			CORE_PIN1_CONFIG = ((val & (1<<1)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		digitalWriteFast(2, (val & (1<<2)));
+		if (!(CORE_PIN2_DDRREG & CORE_PIN2_BIT)) 
+			CORE_PIN2_CONFIG = ((val & (1<<2)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		digitalWriteFast(3, (val & (1<<3)));
+		if (!(CORE_PIN3_DDRREG & CORE_PIN3_BIT)) 
+			CORE_PIN3_CONFIG = ((val & (1<<3)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		digitalWriteFast(4, (val & (1<<4)));
+		if (!(CORE_PIN4_DDRREG & CORE_PIN4_BIT)) 
+			CORE_PIN4_CONFIG = ((val & (1<<4)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		digitalWriteFast(5, (val & (1<<5)));
+		if (!(CORE_PIN5_DDRREG & CORE_PIN5_BIT)) 
+			CORE_PIN5_CONFIG = ((val & (1<<5)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		digitalWriteFast(6, (val & (1<<6)));
+		if (!(CORE_PIN6_DDRREG & CORE_PIN6_BIT)) 
+			CORE_PIN6_CONFIG = ((val & (1<<6)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		digitalWriteFast(7, (val & (1<<7)));
+		if (!(CORE_PIN7_DDRREG & CORE_PIN7_BIT)) 
+			CORE_PIN7_CONFIG = ((val & (1<<7)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		return *this;
+	}
+	inline PORTDemulation & operator |= (int val) __attribute__((always_inline)) {
+		if (val & (1<<0)) {
+			digitalWriteFast(0, HIGH);
+			if (!(CORE_PIN0_DDRREG & CORE_PIN0_BIT)) CORE_PIN0_CONFIG = CONFIG_PULLUP;
+		}
+		if (val & (1<<1)) {
+			digitalWriteFast(1, HIGH);
+			if (!(CORE_PIN1_DDRREG & CORE_PIN1_BIT)) CORE_PIN1_CONFIG = CONFIG_PULLUP;
+		}
+		if (val & (1<<2)) {
+			digitalWriteFast(2, HIGH);
+			if (!(CORE_PIN2_DDRREG & CORE_PIN2_BIT)) CORE_PIN2_CONFIG = CONFIG_PULLUP;
+		}
+		if (val & (1<<3)) {
+			digitalWriteFast(3, HIGH);
+			if (!(CORE_PIN3_DDRREG & CORE_PIN3_BIT)) CORE_PIN3_CONFIG = CONFIG_PULLUP;
+		}
+		if (val & (1<<4)) {
+			digitalWriteFast(4, HIGH);
+			if (!(CORE_PIN4_DDRREG & CORE_PIN4_BIT)) CORE_PIN4_CONFIG = CONFIG_PULLUP;
+		}
+		if (val & (1<<5)) {
+			digitalWriteFast(5, HIGH);
+			if (!(CORE_PIN5_DDRREG & CORE_PIN5_BIT)) CORE_PIN5_CONFIG = CONFIG_PULLUP;
+		}
+		if (val & (1<<6)) {
+			digitalWriteFast(6, HIGH);
+			if (!(CORE_PIN6_DDRREG & CORE_PIN6_BIT)) CORE_PIN6_CONFIG = CONFIG_PULLUP;
+		}
+		if (val & (1<<7)) {
+			digitalWriteFast(7, HIGH);
+			if (!(CORE_PIN7_DDRREG & CORE_PIN7_BIT)) CORE_PIN7_CONFIG = CONFIG_PULLUP;
+		}
+		return *this;
+	}
+	inline PORTDemulation & operator &= (int val) __attribute__((always_inline)) {
+		if (!(val & (1<<0))) {
+			digitalWriteFast(0, LOW);
+			if (!(CORE_PIN0_DDRREG & CORE_PIN0_BIT)) CORE_PIN0_CONFIG = CONFIG_NOPULLUP;
+		}
+		if (!(val & (1<<1))) {
+			digitalWriteFast(1, LOW);
+			if (!(CORE_PIN1_DDRREG & CORE_PIN1_BIT)) CORE_PIN1_CONFIG = CONFIG_NOPULLUP;
+		}
+		if (!(val & (1<<2))) {
+			digitalWriteFast(2, LOW);
+			if (!(CORE_PIN2_DDRREG & CORE_PIN2_BIT)) CORE_PIN2_CONFIG = CONFIG_NOPULLUP;
+		}
+		if (!(val & (1<<3))) {
+			digitalWriteFast(3, LOW);
+			if (!(CORE_PIN3_DDRREG & CORE_PIN3_BIT)) CORE_PIN3_CONFIG = CONFIG_NOPULLUP;
+		}
+		if (!(val & (1<<4))) {
+			digitalWriteFast(4, LOW);
+			if (!(CORE_PIN4_DDRREG & CORE_PIN4_BIT)) CORE_PIN4_CONFIG = CONFIG_NOPULLUP;
+		}
+		if (!(val & (1<<5))) {
+			digitalWriteFast(5, LOW);
+			if (!(CORE_PIN5_DDRREG & CORE_PIN5_BIT)) CORE_PIN5_CONFIG = CONFIG_NOPULLUP;
+		}
+		if (!(val & (1<<6))) {
+			digitalWriteFast(6, LOW);
+			if (!(CORE_PIN6_DDRREG & CORE_PIN6_BIT)) CORE_PIN6_CONFIG = CONFIG_NOPULLUP;
+		}
+		if (!(val & (1<<7))) {
+			digitalWriteFast(7, LOW);
+			if (!(CORE_PIN7_DDRREG & CORE_PIN7_BIT)) CORE_PIN7_CONFIG = CONFIG_NOPULLUP;
+		}
+		return *this;
+	}
+};
+extern PORTDemulation PORTD;
+
+class PINDemulation
+{
+public:
+	inline int operator & (int val) const __attribute__((always_inline)) {
+		int ret = 0;
+		if ((val & (1<<0)) && digitalReadFast(0)) ret |= (1<<0);
+		if ((val & (1<<1)) && digitalReadFast(1)) ret |= (1<<1);
+		if ((val & (1<<2)) && digitalReadFast(2)) ret |= (1<<2);
+		if ((val & (1<<3)) && digitalReadFast(3)) ret |= (1<<3);
+		if ((val & (1<<4)) && digitalReadFast(4)) ret |= (1<<4);
+		if ((val & (1<<5)) && digitalReadFast(5)) ret |= (1<<5);
+		if ((val & (1<<6)) && digitalReadFast(6)) ret |= (1<<6);
+		if ((val & (1<<7)) && digitalReadFast(7)) ret |= (1<<7);
+		return ret;
+	}
+	operator int () const __attribute__((always_inline)) {
+		int ret = 0;
+		if (digitalReadFast(0)) ret |= (1<<0);
+		if (digitalReadFast(1)) ret |= (1<<1);
+		if (digitalReadFast(2)) ret |= (1<<2);
+		if (digitalReadFast(3)) ret |= (1<<3);
+		if (digitalReadFast(4)) ret |= (1<<4);
+		if (digitalReadFast(5)) ret |= (1<<5);
+		if (digitalReadFast(6)) ret |= (1<<6);
+		if (digitalReadFast(7)) ret |= (1<<7);
+		return ret;
+	}
+};
+extern PINDemulation PIND;
+
+class DDRDemulation
+{
+public:
+	inline DDRDemulation & operator = (int val) __attribute__((always_inline)) {
+		if (val & (1<<0)) set0(); else clr0();
+		if (val & (1<<1)) set1(); else clr1();
+		if (val & (1<<2)) set2(); else clr2();
+		if (val & (1<<3)) set3(); else clr3();
+		if (val & (1<<4)) set4(); else clr4();
+		if (val & (1<<5)) set5(); else clr5();
+		if (val & (1<<6)) set6(); else clr6();
+		if (val & (1<<7)) set7(); else clr7();
+		return *this;
+	}
+	inline DDRDemulation & operator |= (int val) __attribute__((always_inline)) {
+		if (val & (1<<0)) set0();
+		if (val & (1<<1)) set1();
+		if (val & (1<<2)) set2();
+		if (val & (1<<3)) set3();
+		if (val & (1<<4)) set4();
+		if (val & (1<<5)) set5();
+		if (val & (1<<6)) set6();
+		if (val & (1<<7)) set7();
+		return *this;
+	}
+	inline DDRDemulation & operator &= (int val) __attribute__((always_inline)) {
+		if (!(val & (1<<0))) clr0();
+		if (!(val & (1<<1))) clr1();
+		if (!(val & (1<<2))) clr2();
+		if (!(val & (1<<3))) clr3();
+		if (!(val & (1<<4))) clr4();
+		if (!(val & (1<<5))) clr5();
+		if (!(val & (1<<6))) clr6();
+		if (!(val & (1<<7))) clr7();
+		return *this;
+	}
+private:
+	inline void set0() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN0_DDRREG, CORE_PIN0_BIT) = 1;
+		CORE_PIN0_CONFIG = CONFIG_PULLUP;
+	}
+	inline void set1() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN1_DDRREG, CORE_PIN1_BIT) = 1;
+		CORE_PIN1_CONFIG = CONFIG_PULLUP;
+	}
+	inline void set2() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN2_DDRREG, CORE_PIN2_BIT) = 1;
+		CORE_PIN2_CONFIG = CONFIG_PULLUP;
+	}
+	inline void set3() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN3_DDRREG, CORE_PIN3_BIT) = 1;
+		CORE_PIN3_CONFIG = CONFIG_PULLUP;
+	}
+	inline void set4() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN4_DDRREG, CORE_PIN4_BIT) = 1;
+		CORE_PIN4_CONFIG = CONFIG_PULLUP;
+	}
+	inline void set5() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN5_DDRREG, CORE_PIN5_BIT) = 1;
+		CORE_PIN5_CONFIG = CONFIG_PULLUP;
+	}
+	inline void set6() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN6_DDRREG, CORE_PIN6_BIT) = 1;
+		CORE_PIN6_CONFIG = CONFIG_PULLUP;
+	}
+	inline void set7() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN7_DDRREG, CORE_PIN7_BIT) = 1;
+		CORE_PIN7_CONFIG = CONFIG_PULLUP;
+	}
+	inline void clr0() __attribute__((always_inline)) {
+		CORE_PIN0_CONFIG = ((CORE_PIN0_PORTREG & CORE_PIN0_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN0_DDRREG, CORE_PIN0_BIT) = 0;
+	}
+	inline void clr1() __attribute__((always_inline)) {
+		CORE_PIN1_CONFIG = ((CORE_PIN1_PORTREG & CORE_PIN1_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN1_DDRREG, CORE_PIN1_BIT) = 0;
+	}
+	inline void clr2() __attribute__((always_inline)) {
+		CORE_PIN2_CONFIG = ((CORE_PIN2_PORTREG & CORE_PIN2_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN2_DDRREG, CORE_PIN2_BIT) = 0;
+	}
+	inline void clr3() __attribute__((always_inline)) {
+		CORE_PIN3_CONFIG = ((CORE_PIN3_PORTREG & CORE_PIN3_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN3_DDRREG, CORE_PIN3_BIT) = 0;
+	}
+	inline void clr4() __attribute__((always_inline)) {
+		CORE_PIN4_CONFIG = ((CORE_PIN4_PORTREG & CORE_PIN4_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN4_DDRREG, CORE_PIN4_BIT) = 0;
+	}
+	inline void clr5() __attribute__((always_inline)) {
+		CORE_PIN5_CONFIG = ((CORE_PIN5_PORTREG & CORE_PIN5_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN5_DDRREG, CORE_PIN5_BIT) = 0;
+	}
+	inline void clr6() __attribute__((always_inline)) {
+		CORE_PIN6_CONFIG = ((CORE_PIN6_PORTREG & CORE_PIN6_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN6_DDRREG, CORE_PIN6_BIT) = 0;
+	}
+	inline void clr7() __attribute__((always_inline)) {
+		CORE_PIN7_CONFIG = ((CORE_PIN7_PORTREG & CORE_PIN7_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN7_DDRREG, CORE_PIN7_BIT) = 0;
+	}
+};
+
+extern DDRDemulation DDRD;
+
+
+
+
+
+
+class PORTBemulation
+{
+public:
+	inline PORTBemulation & operator = (int val) __attribute__((always_inline)) {
+		digitalWriteFast(8, (val & (1<<0)));
+		if (!(CORE_PIN8_DDRREG & CORE_PIN8_BIT)) 
+			CORE_PIN8_CONFIG = ((val & (1<<0)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		digitalWriteFast(9, (val & (1<<1)));
+		if (!(CORE_PIN9_DDRREG & CORE_PIN9_BIT)) 
+			CORE_PIN9_CONFIG = ((val & (1<<1)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		digitalWriteFast(10, (val & (1<<2)));
+		if (!(CORE_PIN10_DDRREG & CORE_PIN10_BIT)) 
+			CORE_PIN10_CONFIG = ((val & (1<<2)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		digitalWriteFast(11, (val & (1<<3)));
+		if (!(CORE_PIN11_DDRREG & CORE_PIN11_BIT)) 
+			CORE_PIN11_CONFIG = ((val & (1<<3)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		digitalWriteFast(12, (val & (1<<4)));
+		if (!(CORE_PIN12_DDRREG & CORE_PIN12_BIT)) 
+			CORE_PIN12_CONFIG = ((val & (1<<4)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		digitalWriteFast(13, (val & (1<<5)));
+		if (!(CORE_PIN13_DDRREG & CORE_PIN13_BIT)) 
+			CORE_PIN13_CONFIG = ((val & (1<<5)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		return *this;
+	}
+	inline PORTBemulation & operator |= (int val) __attribute__((always_inline)) {
+		if (val & (1<<0)) {
+			digitalWriteFast(8, HIGH);
+			if (!(CORE_PIN7_DDRREG & CORE_PIN7_BIT)) CORE_PIN8_CONFIG = CONFIG_PULLUP;
+		}
+		if (val & (1<<1)) {
+			digitalWriteFast(9, HIGH);
+			if (!(CORE_PIN7_DDRREG & CORE_PIN7_BIT)) CORE_PIN9_CONFIG = CONFIG_PULLUP;
+		}
+		if (val & (1<<2)) {
+			digitalWriteFast(10, HIGH);
+			if (!(CORE_PIN10_DDRREG & CORE_PIN10_BIT)) CORE_PIN10_CONFIG = CONFIG_PULLUP;
+		}
+		if (val & (1<<3)) {
+			digitalWriteFast(11, HIGH);
+			if (!(CORE_PIN11_DDRREG & CORE_PIN11_BIT)) CORE_PIN11_CONFIG = CONFIG_PULLUP;
+		}
+		if (val & (1<<4)) {
+			digitalWriteFast(12, HIGH);
+			if (!(CORE_PIN12_DDRREG & CORE_PIN12_BIT)) CORE_PIN12_CONFIG = CONFIG_PULLUP;
+		}
+		if (val & (1<<5)) {
+			digitalWriteFast(13, HIGH);
+			if (!(CORE_PIN13_DDRREG & CORE_PIN13_BIT)) CORE_PIN13_CONFIG = CONFIG_PULLUP;
+		}
+		return *this;
+	}
+	inline PORTBemulation & operator &= (int val) __attribute__((always_inline)) {
+		if (!(val & (1<<0))) {
+			digitalWriteFast(8, LOW);
+			if (!(CORE_PIN8_DDRREG & CORE_PIN8_BIT)) CORE_PIN8_CONFIG = CONFIG_NOPULLUP;
+		}
+		if (!(val & (1<<1))) {
+			digitalWriteFast(9, LOW);
+			if (!(CORE_PIN9_DDRREG & CORE_PIN9_BIT)) CORE_PIN9_CONFIG = CONFIG_NOPULLUP;
+		}
+		if (!(val & (1<<2))) {
+			digitalWriteFast(10, LOW);
+			if (!(CORE_PIN10_DDRREG & CORE_PIN10_BIT)) CORE_PIN10_CONFIG = CONFIG_NOPULLUP;
+		}
+		if (!(val & (1<<3))) {
+			digitalWriteFast(11, LOW);
+			if (!(CORE_PIN11_DDRREG & CORE_PIN11_BIT)) CORE_PIN11_CONFIG = CONFIG_NOPULLUP;
+		}
+		if (!(val & (1<<4))) {
+			digitalWriteFast(12, LOW);
+			if (!(CORE_PIN12_DDRREG & CORE_PIN12_BIT)) CORE_PIN12_CONFIG = CONFIG_NOPULLUP;
+		}
+		if (!(val & (1<<5))) {
+			digitalWriteFast(13, LOW);
+			if (!(CORE_PIN13_DDRREG & CORE_PIN13_BIT)) CORE_PIN13_CONFIG = CONFIG_NOPULLUP;
+		}
+		return *this;
+	}
+};
+extern PORTBemulation PORTB;
+
+class PINBemulation
+{
+public:
+	inline int operator & (int val) const __attribute__((always_inline)) {
+		int ret = 0;
+		if ((val & (1<<0)) && digitalReadFast(8)) ret |= (1<<0);
+		if ((val & (1<<1)) && digitalReadFast(9)) ret |= (1<<1);
+		if ((val & (1<<2)) && digitalReadFast(10)) ret |= (1<<2);
+		if ((val & (1<<3)) && digitalReadFast(11)) ret |= (1<<3);
+		if ((val & (1<<4)) && digitalReadFast(12)) ret |= (1<<4);
+		if ((val & (1<<5)) && digitalReadFast(13)) ret |= (1<<5);
+		return ret;
+	}
+	operator int () const __attribute__((always_inline)) {
+		int ret = 0;
+		if (digitalReadFast(8)) ret |= (1<<0);
+		if (digitalReadFast(9)) ret |= (1<<1);
+		if (digitalReadFast(10)) ret |= (1<<2);
+		if (digitalReadFast(11)) ret |= (1<<3);
+		if (digitalReadFast(12)) ret |= (1<<4);
+		if (digitalReadFast(13)) ret |= (1<<5);
+		return ret;
+	}
+};
+extern PINBemulation PINB;
+
+class DDRBemulation
+{
+public:
+	inline DDRBemulation & operator = (int val) __attribute__((always_inline)) {
+		if (val & (1<<0)) set0(); else clr0();
+		if (val & (1<<1)) set1(); else clr1();
+		if (val & (1<<2)) set2(); else clr2();
+		if (val & (1<<3)) set3(); else clr3();
+		if (val & (1<<4)) set4(); else clr4();
+		if (val & (1<<5)) set5(); else clr5();
+		return *this;
+	}
+	inline DDRBemulation & operator |= (int val) __attribute__((always_inline)) {
+		if (val & (1<<0)) set0();
+		if (val & (1<<1)) set1();
+		if (val & (1<<2)) set2();
+		if (val & (1<<3)) set3();
+		if (val & (1<<4)) set4();
+		if (val & (1<<5)) set5();
+		return *this;
+	}
+	inline DDRBemulation & operator &= (int val) __attribute__((always_inline)) {
+		if (!(val & (1<<0))) clr0();
+		if (!(val & (1<<1))) clr1();
+		if (!(val & (1<<2))) clr2();
+		if (!(val & (1<<3))) clr3();
+		if (!(val & (1<<4))) clr4();
+		if (!(val & (1<<5))) clr5();
+		return *this;
+	}
+private:
+	inline void set0() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN8_DDRREG, CORE_PIN8_BIT) = 1;
+		CORE_PIN8_CONFIG = CONFIG_PULLUP;
+	}
+	inline void set1() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN9_DDRREG, CORE_PIN9_BIT) = 1;
+		CORE_PIN9_CONFIG = CONFIG_PULLUP;
+	}
+	inline void set2() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN10_DDRREG, CORE_PIN10_BIT) = 1;
+		CORE_PIN10_CONFIG = CONFIG_PULLUP;
+	}
+	inline void set3() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN11_DDRREG, CORE_PIN11_BIT) = 1;
+		CORE_PIN11_CONFIG = CONFIG_PULLUP;
+	}
+	inline void set4() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN12_DDRREG, CORE_PIN12_BIT) = 1;
+		CORE_PIN12_CONFIG = CONFIG_PULLUP;
+	}
+	inline void set5() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN13_DDRREG, CORE_PIN13_BIT) = 1;
+		CORE_PIN13_CONFIG = CONFIG_PULLUP;
+	}
+	inline void clr0() __attribute__((always_inline)) {
+		CORE_PIN8_CONFIG = ((CORE_PIN8_PORTREG & CORE_PIN8_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN8_DDRREG, CORE_PIN8_BIT) = 0;
+	}
+	inline void clr1() __attribute__((always_inline)) {
+		CORE_PIN9_CONFIG = ((CORE_PIN9_PORTREG & CORE_PIN9_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN9_DDRREG, CORE_PIN9_BIT) = 0;
+	}
+	inline void clr2() __attribute__((always_inline)) {
+		CORE_PIN10_CONFIG = ((CORE_PIN10_PORTREG & CORE_PIN10_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN10_DDRREG, CORE_PIN10_BIT) = 0;
+	}
+	inline void clr3() __attribute__((always_inline)) {
+		CORE_PIN11_CONFIG = ((CORE_PIN11_PORTREG & CORE_PIN11_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN11_DDRREG, CORE_PIN11_BIT) = 0;
+	}
+	inline void clr4() __attribute__((always_inline)) {
+		CORE_PIN12_CONFIG = ((CORE_PIN12_PORTREG & CORE_PIN12_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN12_DDRREG, CORE_PIN12_BIT) = 0;
+	}
+	inline void clr5() __attribute__((always_inline)) {
+		CORE_PIN13_CONFIG = ((CORE_PIN13_PORTREG & CORE_PIN13_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN13_DDRREG, CORE_PIN13_BIT) = 0;
+	}
+};
+
+extern DDRBemulation DDRB;
+
+
+
+
+
+
+class PORTCemulation
+{
+public:
+	inline PORTCemulation & operator = (int val) __attribute__((always_inline)) {
+		digitalWriteFast(14, (val & (1<<0)));
+		if (!(CORE_PIN14_DDRREG & CORE_PIN14_BIT)) 
+			CORE_PIN14_CONFIG = ((val & (1<<0)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		digitalWriteFast(15, (val & (1<<1)));
+		if (!(CORE_PIN15_DDRREG & CORE_PIN15_BIT)) 
+			CORE_PIN15_CONFIG = ((val & (1<<1)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		digitalWriteFast(16, (val & (1<<2)));
+		if (!(CORE_PIN16_DDRREG & CORE_PIN16_BIT)) 
+			CORE_PIN16_CONFIG = ((val & (1<<2)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		digitalWriteFast(17, (val & (1<<3)));
+		if (!(CORE_PIN17_DDRREG & CORE_PIN17_BIT)) 
+			CORE_PIN17_CONFIG = ((val & (1<<3)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		digitalWriteFast(18, (val & (1<<4)));
+		if (!(CORE_PIN18_DDRREG & CORE_PIN18_BIT)) 
+			CORE_PIN18_CONFIG = ((val & (1<<4)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		digitalWriteFast(19, (val & (1<<5)));
+		if (!(CORE_PIN19_DDRREG & CORE_PIN19_BIT)) 
+			CORE_PIN19_CONFIG = ((val & (1<<5)) ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		return *this;
+	}
+	inline PORTCemulation & operator |= (int val) __attribute__((always_inline)) {
+		if (val & (1<<0)) {
+			digitalWriteFast(14, HIGH);
+			if (!(CORE_PIN14_DDRREG & CORE_PIN14_BIT)) CORE_PIN14_CONFIG = CONFIG_PULLUP;
+		}
+		if (val & (1<<1)) {
+			digitalWriteFast(15, HIGH);
+			if (!(CORE_PIN15_DDRREG & CORE_PIN15_BIT)) CORE_PIN15_CONFIG = CONFIG_PULLUP;
+		}
+		if (val & (1<<2)) {
+			digitalWriteFast(16, HIGH);
+			if (!(CORE_PIN16_DDRREG & CORE_PIN16_BIT)) CORE_PIN16_CONFIG = CONFIG_PULLUP;
+		}
+		if (val & (1<<3)) {
+			digitalWriteFast(17, HIGH);
+			if (!(CORE_PIN17_DDRREG & CORE_PIN17_BIT)) CORE_PIN17_CONFIG = CONFIG_PULLUP;
+		}
+		if (val & (1<<4)) {
+			digitalWriteFast(18, HIGH);
+			if (!(CORE_PIN18_DDRREG & CORE_PIN18_BIT)) CORE_PIN18_CONFIG = CONFIG_PULLUP;
+		}
+		if (val & (1<<5)) {
+			digitalWriteFast(19, HIGH);
+			if (!(CORE_PIN19_DDRREG & CORE_PIN19_BIT)) CORE_PIN19_CONFIG = CONFIG_PULLUP;
+		}
+		return *this;
+	}
+	inline PORTCemulation & operator &= (int val) __attribute__((always_inline)) {
+		if (!(val & (1<<0))) {
+			digitalWriteFast(14, LOW);
+			if (!(CORE_PIN14_DDRREG & CORE_PIN14_BIT)) CORE_PIN14_CONFIG = CONFIG_NOPULLUP;
+		}
+		if (!(val & (1<<1))) {
+			digitalWriteFast(15, LOW);
+			if (!(CORE_PIN15_DDRREG & CORE_PIN15_BIT)) CORE_PIN15_CONFIG = CONFIG_NOPULLUP;
+		}
+		if (!(val & (1<<2))) {
+			digitalWriteFast(16, LOW);
+			if (!(CORE_PIN16_DDRREG & CORE_PIN16_BIT)) CORE_PIN16_CONFIG = CONFIG_NOPULLUP;
+		}
+		if (!(val & (1<<3))) {
+			digitalWriteFast(17, LOW);
+			if (!(CORE_PIN17_DDRREG & CORE_PIN17_BIT)) CORE_PIN17_CONFIG = CONFIG_NOPULLUP;
+		}
+		if (!(val & (1<<4))) {
+			digitalWriteFast(18, LOW);
+			if (!(CORE_PIN18_DDRREG & CORE_PIN18_BIT)) CORE_PIN18_CONFIG = CONFIG_NOPULLUP;
+		}
+		if (!(val & (1<<5))) {
+			digitalWriteFast(19, LOW);
+			if (!(CORE_PIN19_DDRREG & CORE_PIN19_BIT)) CORE_PIN19_CONFIG = CONFIG_NOPULLUP;
+		}
+		return *this;
+	}
+};
+extern PORTCemulation PORTC;
+
+class PINCemulation
+{
+public:
+	inline int operator & (int val) const __attribute__((always_inline)) {
+		int ret = 0;
+		if ((val & (1<<0)) && digitalReadFast(8)) ret |= (1<<0);
+		if ((val & (1<<1)) && digitalReadFast(9)) ret |= (1<<1);
+		if ((val & (1<<2)) && digitalReadFast(10)) ret |= (1<<2);
+		if ((val & (1<<3)) && digitalReadFast(11)) ret |= (1<<3);
+		if ((val & (1<<4)) && digitalReadFast(12)) ret |= (1<<4);
+		if ((val & (1<<5)) && digitalReadFast(13)) ret |= (1<<5);
+		return ret;
+	}
+	operator int () const __attribute__((always_inline)) {
+		int ret = 0;
+		if (digitalReadFast(8)) ret |= (1<<0);
+		if (digitalReadFast(9)) ret |= (1<<1);
+		if (digitalReadFast(10)) ret |= (1<<2);
+		if (digitalReadFast(11)) ret |= (1<<3);
+		if (digitalReadFast(12)) ret |= (1<<4);
+		if (digitalReadFast(13)) ret |= (1<<5);
+		return ret;
+	}
+};
+extern PINCemulation PINC;
+
+class DDRCemulation
+{
+public:
+	inline DDRCemulation & operator = (int val) __attribute__((always_inline)) {
+		if (val & (1<<0)) set0(); else clr0();
+		if (val & (1<<1)) set1(); else clr1();
+		if (val & (1<<2)) set2(); else clr2();
+		if (val & (1<<3)) set3(); else clr3();
+		if (val & (1<<4)) set4(); else clr4();
+		if (val & (1<<5)) set5(); else clr5();
+		return *this;
+	}
+	inline DDRCemulation & operator |= (int val) __attribute__((always_inline)) {
+		if (val & (1<<0)) set0();
+		if (val & (1<<1)) set1();
+		if (val & (1<<2)) set2();
+		if (val & (1<<3)) set3();
+		if (val & (1<<4)) set4();
+		if (val & (1<<5)) set5();
+		return *this;
+	}
+	inline DDRCemulation & operator &= (int val) __attribute__((always_inline)) {
+		if (!(val & (1<<0))) clr0();
+		if (!(val & (1<<1))) clr1();
+		if (!(val & (1<<2))) clr2();
+		if (!(val & (1<<3))) clr3();
+		if (!(val & (1<<4))) clr4();
+		if (!(val & (1<<5))) clr5();
+		return *this;
+	}
+private:
+	inline void set0() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN14_DDRREG, CORE_PIN14_BIT) = 1;
+		CORE_PIN14_CONFIG = CONFIG_PULLUP;
+	}
+	inline void set1() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN15_DDRREG, CORE_PIN15_BIT) = 1;
+		CORE_PIN15_CONFIG = CONFIG_PULLUP;
+	}
+	inline void set2() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN16_DDRREG, CORE_PIN16_BIT) = 1;
+		CORE_PIN16_CONFIG = CONFIG_PULLUP;
+	}
+	inline void set3() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN17_DDRREG, CORE_PIN17_BIT) = 1;
+		CORE_PIN17_CONFIG = CONFIG_PULLUP;
+	}
+	inline void set4() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN18_DDRREG, CORE_PIN18_BIT) = 1;
+		CORE_PIN18_CONFIG = CONFIG_PULLUP;
+	}
+	inline void set5() __attribute__((always_inline)) {
+		GPIO_BITBAND(CORE_PIN19_DDRREG, CORE_PIN19_BIT) = 1;
+		CORE_PIN19_CONFIG = CONFIG_PULLUP;
+	}
+	inline void clr0() __attribute__((always_inline)) {
+		CORE_PIN14_CONFIG = ((CORE_PIN14_PORTREG & CORE_PIN14_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN14_DDRREG, CORE_PIN14_BIT) = 0;
+	}
+	inline void clr1() __attribute__((always_inline)) {
+		CORE_PIN15_CONFIG = ((CORE_PIN15_PORTREG & CORE_PIN15_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN15_DDRREG, CORE_PIN15_BIT) = 0;
+	}
+	inline void clr2() __attribute__((always_inline)) {
+		CORE_PIN16_CONFIG = ((CORE_PIN16_PORTREG & CORE_PIN16_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN16_DDRREG, CORE_PIN16_BIT) = 0;
+	}
+	inline void clr3() __attribute__((always_inline)) {
+		CORE_PIN17_CONFIG = ((CORE_PIN17_PORTREG & CORE_PIN17_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN17_DDRREG, CORE_PIN17_BIT) = 0;
+	}
+	inline void clr4() __attribute__((always_inline)) {
+		CORE_PIN18_CONFIG = ((CORE_PIN18_PORTREG & CORE_PIN18_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN18_DDRREG, CORE_PIN18_BIT) = 0;
+	}
+	inline void clr5() __attribute__((always_inline)) {
+		CORE_PIN19_CONFIG = ((CORE_PIN19_PORTREG & CORE_PIN19_BITMASK)
+		  ? CONFIG_PULLUP : CONFIG_NOPULLUP);
+		GPIO_BITBAND(CORE_PIN19_DDRREG, CORE_PIN19_BIT) = 0;
+	}
+};
+
+extern DDRCemulation DDRC;
+
+
+#define PINB0 0
+#define PINB1 1
+#define PINB2 2
+#define PINB3 3
+#define PINB4 4
+#define PINB5 5
+#define PINB6 6
+#define PINB7 7
+#define DDB0 0
+#define DDB1 1
+#define DDB2 2
+#define DDB3 3
+#define DDB4 4
+#define DDB5 5
+#define DDB6 6
+#define DDB7 7
+#define PORTB0 0
+#define PORTB1 1
+#define PORTB2 2
+#define PORTB3 3
+#define PORTB4 4
+#define PORTB5 5
+#define PORTB6 6
+#define PORTB7 7
+#define PINC0 0
+#define PINC1 1
+#define PINC2 2
+#define PINC3 3
+#define PINC4 4
+#define PINC5 5
+#define PINC6 6
+#define DDC0 0
+#define DDC1 1
+#define DDC2 2
+#define DDC3 3
+#define DDC4 4
+#define DDC5 5
+#define DDC6 6
+#define PORTC0 0
+#define PORTC1 1
+#define PORTC2 2
+#define PORTC3 3
+#define PORTC4 4
+#define PORTC5 5
+#define PORTC6 6
+#define PIND0 0
+#define PIND1 1
+#define PIND2 2
+#define PIND3 3
+#define PIND4 4
+#define PIND5 5
+#define PIND6 6
+#define PIND7 7
+#define DDD0 0
+#define DDD1 1
+#define DDD2 2
+#define DDD3 3
+#define DDD4 4
+#define DDD5 5
+#define DDD6 6
+#define DDD7 7
+#define PORTD0 0
+#define PORTD1 1
+#define PORTD2 2
+#define PORTD3 3
+#define PORTD4 4
+#define PORTD5 5
+#define PORTD6 6
+#define PORTD7 7
+
+
+
+
+
+#if 0
+extern "C" {
+void serial_print(const char *p);
+void serial_phex(uint32_t n);
+void serial_phex16(uint32_t n);
+void serial_phex32(uint32_t n);
+}
+#endif
+
+
+// SPI Control Register ­ SPCR
+#define SPIE	7	// SPI Interrupt Enable - not supported
+#define SPE	6	// SPI Enable
+#define DORD	5	// DORD: Data Order
+#define MSTR	4	// MSTR: Master/Slave Select
+#define CPOL	3	// CPOL: Clock Polarity
+#define CPHA	2	// CPHA: Clock Phase
+#define SPR1	1	// Clock: 3 = 125 kHz, 2 = 250 kHz, 1 = 1 MHz, 0->4 MHz
+#define SPR0	0
+// SPI Status Register ­ SPSR
+#define SPIF	7	// SPIF: SPI Interrupt Flag
+#define WCOL	6	// WCOL: Write COLlision Flag - not implemented
+#define SPI2X	0	// SPI2X: Double SPI Speed Bit
+// SPI Data Register ­ SPDR
+
+class SPCRemulation;
+class SPSRemulation;
+class SPDRemulation;
+
+class SPCRemulation
+{
+public:
+	inline SPCRemulation & operator = (int val) __attribute__((always_inline)) {
+		uint32_t ctar, mcr, sim6;
+		//serial_print("SPCR=");
+		//serial_phex(val);
+		//serial_print("\n");
+		sim6 = SIM_SCGC6;
+		if (!(sim6 & SIM_SCGC6_SPI0)) {
+			//serial_print("init1\n");
+			SIM_SCGC6 = sim6 | SIM_SCGC6_SPI0;
+			SPI0_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
+		}
+		if (!(val & (1<<SPE))) {
+			SPI0_MCR |= SPI_MCR_MDIS; // TODO: use bitband for atomic access
+		}
+		ctar = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1);
+		if (val & (1<<DORD))  ctar |= SPI_CTAR_LSBFE;
+		if (val & (1<<CPOL))  ctar |= SPI_CTAR_CPOL;
+		if (val & (1<<CPHA)) {
+			ctar |= SPI_CTAR_CPHA;
+			if ((val & 3) == 0) {
+				ctar |= SPI_CTAR_BR(1) | SPI_CTAR_ASC(1);
+			} else if ((val & 3) == 1) {
+				ctar |= SPI_CTAR_BR(4) | SPI_CTAR_ASC(4);
+			} else if ((val & 3) == 2) {
+				ctar |= SPI_CTAR_BR(6) | SPI_CTAR_ASC(6);
+			} else {
+				ctar |= SPI_CTAR_BR(7) | SPI_CTAR_ASC(7);
+			}
+		} else {
+			if ((val & 3) == 0) {
+				ctar |= SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
+			} else if ((val & 3) == 1) {
+				ctar |= SPI_CTAR_BR(4) | SPI_CTAR_CSSCK(4);
+			} else if ((val & 3) == 2) {
+				ctar |= SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(6);
+			} else {
+				ctar |= SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(7);
+			}
+		}
+		ctar |= (SPI0_CTAR0 & SPI_CTAR_DBR);
+		update_ctar(ctar);
+		mcr = SPI_MCR_DCONF(0);
+		if (val & (1<<MSTR)) mcr |= SPI_MCR_MSTR;
+		if (val & (1<<SPE)) {
+			mcr &= ~(SPI_MCR_MDIS | SPI_MCR_HALT);
+			SPI0_MCR = mcr;
+			enable_pins();
+		} else {
+			mcr |= (SPI_MCR_MDIS | SPI_MCR_HALT);
+			SPI0_MCR = mcr;
+			disable_pins();
+		}
+		//serial_print("MCR:");
+		//serial_phex32(SPI0_MCR);
+		//serial_print(", CTAR0:");
+		//serial_phex32(SPI0_CTAR0);
+		//serial_print("\n");
+		return *this;
+	}
+	inline SPCRemulation & operator |= (int val) __attribute__((always_inline)) {
+		uint32_t sim6;
+		//serial_print("SPCR |= ");
+		//serial_phex(val);
+		//serial_print("\n");
+		sim6 = SIM_SCGC6;
+		if (!(sim6 & SIM_SCGC6_SPI0)) {
+			//serial_print("init2\n");
+			SIM_SCGC6 = sim6 | SIM_SCGC6_SPI0;
+			SPI0_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1) | SPI_CTAR_BR(1);
+		}
+		if (val & ((1<<DORD)|(1<<CPOL)|(1<<CPHA)|3)) {
+			uint32_t ctar = SPI0_CTAR0;
+			if (val & (1<<DORD)) ctar |= SPI_CTAR_LSBFE; // TODO: use bitband
+			if (val & (1<<CPOL)) ctar |= SPI_CTAR_CPOL;
+			if ((val & 3) == 1) {
+				// TODO: implement - is this ever really needed
+			} else if ((val & 3) == 2) {
+				// TODO: implement - is this ever really needed
+			} else if ((val & 3) == 3) {
+				// TODO: implement - is this ever really needed
+			}
+			if (val & (1<<CPHA) && !(ctar & SPI_CTAR_CPHA)) {
+				ctar |= SPI_CTAR_CPHA;
+				// TODO: clear SPI_CTAR_CSSCK, set SPI_CTAR_ASC
+			}
+			update_ctar(ctar);
+		}
+		if (val & (1<<MSTR)) SPI0_MCR |= SPI_MCR_MSTR;
+		if (val & (1<<SPE)) {
+			SPI0_MCR &= ~(SPI_MCR_MDIS | SPI_MCR_HALT);
+			enable_pins();
+		}
+		//serial_print("MCR:");
+		//serial_phex32(SPI0_MCR);
+		//serial_print(", CTAR0:");
+		//serial_phex32(SPI0_CTAR0);
+		//serial_print("\n");
+		return *this;
+	}
+	inline SPCRemulation & operator &= (int val) __attribute__((always_inline)) {
+		//serial_print("SPCR &= ");
+		//serial_phex(val);
+		//serial_print("\n");
+		SIM_SCGC6 |= SIM_SCGC6_SPI0;
+		if (!(val & (1<<SPE))) {
+			SPI0_MCR |= (SPI_MCR_MDIS | SPI_MCR_HALT);
+			disable_pins();
+		}
+		if ((val & ((1<<DORD)|(1<<CPOL)|(1<<CPHA)|3)) != ((1<<DORD)|(1<<CPOL)|(1<<CPHA)|3)) {
+			uint32_t ctar = SPI0_CTAR0;
+			if (!(val & (1<<DORD))) ctar &= ~SPI_CTAR_LSBFE; // TODO: use bitband
+			if (!(val & (1<<CPOL))) ctar &= ~SPI_CTAR_CPOL;
+			if ((val & 3) == 0) {
+				// TODO: implement - is this ever really needed
+			} else if ((val & 3) == 1) {
+				// TODO: implement - is this ever really needed
+			} else if ((val & 3) == 2) {
+				// TODO: implement - is this ever really needed
+			}
+			if (!(val & (1<<CPHA)) && (ctar & SPI_CTAR_CPHA)) {
+				ctar &= ~SPI_CTAR_CPHA;
+				// TODO: set SPI_CTAR_ASC, clear SPI_CTAR_CSSCK
+			}
+			update_ctar(ctar);
+		}
+		if (!(val & (1<<MSTR))) SPI0_MCR &= ~SPI_MCR_MSTR;
+		return *this;
+	}
+	inline int operator & (int val) const __attribute__((always_inline)) {
+		int ret = 0;
+		//serial_print("SPCR & ");
+		//serial_phex(val);
+		//serial_print("\n");
+		if ((val & (1<<DORD)) && (SPI0_CTAR0 & SPI_CTAR_LSBFE)) ret |= (1<<DORD);
+		if ((val & (1<<CPOL)) && (SPI0_CTAR0 & SPI_CTAR_CPOL)) ret |= (1<<CPOL);
+		if ((val & (1<<CPHA)) && (SPI0_CTAR0 & SPI_CTAR_CPHA)) ret |= (1<<CPHA);
+		if ((val & 3) == 3) {
+			uint32_t dbr = SPI0_CTAR0 & 15;
+			if (dbr <= 1) {
+			} else if (dbr <= 4) {
+				ret |= (1<<SPR0);
+			} else if (dbr <= 6) {
+				ret |= (1<<SPR1);
+			} else {
+				ret |= (1<<SPR1)|(1<<SPR0);
+			}
+		} else if ((val & 3) == 1) {
+			// TODO: implement - is this ever really needed
+		} else if ((val & 3) == 2) {
+			// TODO: implement - is this ever really needed
+		}
+		if (val & (1<<SPE) && (!(SPI0_MCR & SPI_MCR_MDIS))) ret |= (1<<SPE);
+		if (val & (1<<MSTR) && (SPI0_MCR & SPI_MCR_MSTR)) ret |= (1<<MSTR);
+		//serial_print("ret = ");
+		//serial_phex(ret);
+		//serial_print("\n");
+		return ret;
+	}
+	operator int () const __attribute__((always_inline)) {
+		int ret = 0;
+		if ((SIM_SCGC6 & SIM_SCGC6_SPI0)) {
+			int ctar = SPI0_CTAR0;
+			if (ctar & SPI_CTAR_LSBFE) ret |= (1<<DORD);
+			if (ctar & SPI_CTAR_CPOL) ret |= (1<<CPOL);
+			if (ctar & SPI_CTAR_CPHA) ret |= (1<<CPHA);
+			ctar &= 15;
+			if (ctar <= 1) {
+			} else if (ctar <= 4) {
+				ret |= (1<<SPR0);
+			} else if (ctar <= 6) {
+				ret |= (1<<SPR1);
+			} else {
+				ret |= (1<<SPR1)|(1<<SPR0);
+			}
+			int mcr = SPI0_MCR;
+			if (!(mcr & SPI_MCR_MDIS)) ret |= (1<<SPE);
+			if (mcr & SPI_MCR_MSTR) ret |= (1<<MSTR);
+		}
+		return ret;
+	}
+	friend class SPSRemulation;
+private:
+	static inline void update_ctar(uint32_t ctar) __attribute__((always_inline)) {
+		if (SPI0_CTAR0 == ctar) return;
+		uint32_t mcr = SPI0_MCR;
+		if (mcr & SPI_MCR_MDIS) {
+			SPI0_CTAR0 = ctar;
+		} else {
+			SPI0_MCR = mcr | SPI_MCR_MDIS | SPI_MCR_HALT;
+			SPI0_CTAR0 = ctar;
+			SPI0_MCR = mcr;
+		}
+	}
+	inline void enable_pins(void) __attribute__((always_inline)) {
+		//serial_print("enable_pins\n");
+		CORE_PIN11_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2);
+		CORE_PIN12_CONFIG = PORT_PCR_MUX(2);
+		CORE_PIN13_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2);
+	}
+	inline void disable_pins(void) __attribute__((always_inline)) {
+		//serial_print("disable_pins\n");
+		CORE_PIN11_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
+		CORE_PIN12_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
+		CORE_PIN13_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
+	}
+};
+extern SPCRemulation SPCR;
+
+class SPSRemulation
+{
+public:
+	inline SPSRemulation & operator = (int val) __attribute__((always_inline)) {
+		//serial_print("SPSR=");
+		//serial_phex(val);
+		//serial_print("\n");
+		uint32_t ctar = SPI0_CTAR0;
+		if (val & (1<<SPI2X)) {
+			ctar |= SPI_CTAR_DBR;
+		} else {
+			ctar &= ~SPI_CTAR_DBR;
+		}
+		SPCRemulation::update_ctar(ctar);
+		//serial_print("MCR:");
+		//serial_phex32(SPI0_MCR);
+		//serial_print(", CTAR0:");
+		//serial_phex32(SPI0_CTAR0);
+		//serial_print("\n");
+		return *this;
+	}
+	inline SPSRemulation & operator |= (int val) __attribute__((always_inline)) {
+		//serial_print("SPSR |= ");
+		//serial_phex(val);
+		//serial_print("\n");
+		if (val & (1<<SPI2X)) SPCRemulation::update_ctar(SPI0_CTAR0 |= SPI_CTAR_DBR);
+		return *this;
+	}
+	inline SPSRemulation & operator &= (int val) __attribute__((always_inline)) {
+		//serial_print("SPSR &= ");
+		//serial_phex(val);
+		//serial_print("\n");
+		if (!(val & (1<<SPI2X))) SPCRemulation::update_ctar(SPI0_CTAR0 &= ~SPI_CTAR_DBR);
+		return *this;
+	}
+	inline int operator & (int val) const __attribute__((always_inline)) {
+		int ret = 0;
+		//serial_print("SPSR & ");
+		//serial_phex(val);
+		//serial_print("\n");
+		// TODO: using SPI_SR_TCF isn't quite right.  Control returns to the
+		// caller after the final edge that captures data, which is 1/2 cycle
+		// sooner than AVR returns.  At 500 kHz and slower SPI, this can make
+		// a difference when digitalWrite is used to manually control the CS
+		// pin, and perhaps it could matter at high clocks if faster register
+		// access is used?  But does it really matter?  Do any SPI chips in
+		// practice really perform differently if CS negates early, after the
+		// final bit is clocked, but before the end of the whole clock cycle?
+		if ((val & (1<<SPIF)) && (SPI0_SR & SPI_SR_TCF)) ret = (1<<SPIF);
+		if ((val & (1<<SPI2X)) && (SPI0_CTAR0 & SPI_CTAR_DBR)) ret |= (1<<SPI2X);
+		//delayMicroseconds(50000);
+		return ret;
+	}
+	operator int () const __attribute__((always_inline)) {
+		int ret = 0;
+		//serial_print("SPSR (int)\n");
+		if (SPI0_SR & SPI_SR_TCF) ret = (1<<SPIF);
+		if (SPI0_CTAR0 & SPI_CTAR_DBR) ret |= (1<<SPI2X);
+		return ret;
+	}
+};
+extern SPSRemulation SPSR;
+
+class SPDRemulation
+{
+public:
+	inline SPDRemulation & operator = (int val) __attribute__((always_inline)) {
+		//serial_print("SPDR = ");
+		//serial_phex(val);
+		//serial_print("\n");
+		SPI0_MCR |= SPI_MCR_CLR_RXF; // discard any received data
+		SPI0_SR = SPI_SR_TCF;
+		//SPI0_SR = SPI_SR_EOQF;
+		//SPI0_PUSHR = (val & 255) | SPI0_PUSHR_EOQ;
+		SPI0_PUSHR = (val & 255);
+		return *this;
+	}
+	operator int () const __attribute__((always_inline)) {
+		uint32_t val;
+		val = SPI0_POPR & 255;
+		//serial_print("SPDR (int) ");
+		//serial_phex(val);
+		//serial_print("\n");
+		return val;
+	}
+};
+extern SPDRemulation SPDR;
+
+
+class SREGemulation
+{
+public:
+	operator int () const __attribute__((always_inline)) {
+		uint32_t primask;
+		asm volatile("mrs %0, primask\n" : "=r" (primask)::);
+		if (primask) return 0;
+		return (1<<7);
+	}
+	inline SREGemulation & operator = (int val) __attribute__((always_inline)) {
+		if (val & (1<<7)) {
+			__enable_irq();
+		} else {
+			__disable_irq();
+		}
+		return *this;
+	}
+};
+extern SREGemulation SREG;
+
+// these are not intended for public consumption...
+#undef GPIO_BITBAND_ADDR
+#undef GPIO_BITBAND
+#undef CONFIG_PULLUP
+#undef CONFIG_NOPULLUP
+
+#endif // __cplusplus
+
+#endif
diff --git a/teensy3/avr_functions.h b/teensy3/avr_functions.h
new file mode 100644
index 0000000000000000000000000000000000000000..8e752541185e00b24b402707b99abd060dbfed94
--- /dev/null
+++ b/teensy3/avr_functions.h
@@ -0,0 +1,69 @@
+/* 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));
+float eeprom_read_float(const float *addr) __attribute__ ((pure));
+void eeprom_read_block(void *buf, const void *addr, uint32_t len); // TODO: implement
+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_float(float *addr, float value); // TODO: inline call
+void eeprom_write_block(const void *buf, void *addr, uint32_t len); // TODO: implement
+void eeprom_update_byte(uint8_t *addrp, uint8_t value); // TODO: inline call
+void eeprom_update_word(uint16_t *addrp, uint16_t value); // TODO: inline call
+void eeprom_update_dword(uint32_t *addrp, uint32_t value); // TODO: inline call
+void eeprom_update_float(float *addr, float __value); // TODO: inline call
+void eeprom_update_block(const void *buf, void *addr, uint32_t len); // TODO: inline call
+
+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
diff --git a/teensy3/binary.h b/teensy3/binary.h
new file mode 100644
index 0000000000000000000000000000000000000000..af1498033ab2fcabf7d8cbb7b241a82ba5e091f0
--- /dev/null
+++ b/teensy3/binary.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
diff --git a/teensy3/core_cm4.h b/teensy3/core_cm4.h
new file mode 100644
index 0000000000000000000000000000000000000000..024302e4a67a47884a961dd6ef057c2f84d4aa9c
--- /dev/null
+++ b/teensy3/core_cm4.h
@@ -0,0 +1,1757 @@
+/**************************************************************************//**
+ * @file     core_cm4.h
+ * @brief    CMSIS Cortex-M4 Core Peripheral Access Layer Header File
+ * @version  V3.01
+ * @date     22. 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.
+ *
+ ******************************************************************************/
+#if defined ( __ICCARM__ )
+ #pragma system_include  /* treat file as system include file for MISRA check */
+#endif
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#ifndef __CORE_CM4_H_GENERIC
+#define __CORE_CM4_H_GENERIC
+
+/** \page CMSIS_MISRA_Exceptions  MISRA-C:2004 Compliance Exceptions
+  CMSIS violates the following MISRA-C:2004 rules:
+
+   \li Required Rule 8.5, object/function definition in header file.<br>
+     Function definitions in header files are used to allow 'inlining'.
+
+   \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.<br>
+     Unions are used for effective representation of core registers.
+
+   \li Advisory Rule 19.7, Function-like macro defined.<br>
+     Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ *                 CMSIS definitions
+ ******************************************************************************/
+/** \ingroup Cortex_M4
+  @{
+ */
+
+/*  CMSIS CM4 definitions */
+#define __CM4_CMSIS_VERSION_MAIN  (0x03)                                   /*!< [31:16] CMSIS HAL main version   */
+#define __CM4_CMSIS_VERSION_SUB   (0x01)                                   /*!< [15:0]  CMSIS HAL sub version    */
+#define __CM4_CMSIS_VERSION       ((__CM4_CMSIS_VERSION_MAIN << 16) | \
+                                    __CM4_CMSIS_VERSION_SUB          )     /*!< CMSIS HAL version number         */
+
+#define __CORTEX_M                (0x04)                                   /*!< Cortex-M Core                    */
+
+
+#if   defined ( __CC_ARM )
+  #define __ASM            __asm                                      /*!< asm keyword for ARM Compiler          */
+  #define __INLINE         __inline                                   /*!< inline keyword for ARM Compiler       */
+  #define __STATIC_INLINE  static __inline
+
+#elif defined ( __ICCARM__ )
+  #define __ASM            __asm                                      /*!< asm keyword for IAR Compiler          */
+  #define __INLINE         inline                                     /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */
+  #define __STATIC_INLINE  static inline
+
+#elif defined ( __TMS470__ )
+  #define __ASM            __asm                                      /*!< asm keyword for TI CCS Compiler       */
+  #define __STATIC_INLINE  static inline
+
+#elif defined ( __GNUC__ )
+  #define __ASM            __asm                                      /*!< asm keyword for GNU Compiler          */
+  #define __INLINE         inline                                     /*!< inline keyword for GNU Compiler       */
+  #define __STATIC_INLINE  static inline
+
+#elif defined ( __TASKING__ )
+  #define __ASM            __asm                                      /*!< asm keyword for TASKING Compiler      */
+  #define __INLINE         inline                                     /*!< inline keyword for TASKING Compiler   */
+  #define __STATIC_INLINE  static inline
+
+#endif
+
+/** __FPU_USED indicates whether an FPU is used or not. For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions.
+*/
+#if defined ( __CC_ARM )
+  #if defined __TARGET_FPU_VFP
+    #if (__FPU_PRESENT == 1)
+      #define __FPU_USED       1
+    #else
+      #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+      #define __FPU_USED       0
+    #endif
+  #else
+    #define __FPU_USED         0
+  #endif
+
+#elif defined ( __ICCARM__ )
+  #if defined __ARMVFP__
+    #if (__FPU_PRESENT == 1)
+      #define __FPU_USED       1
+    #else
+      #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+      #define __FPU_USED       0
+    #endif
+  #else
+    #define __FPU_USED         0
+  #endif
+
+#elif defined ( __TMS470__ )
+  #if defined __TI_VFP_SUPPORT__
+    #if (__FPU_PRESENT == 1)
+      #define __FPU_USED       1
+    #else
+      #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+      #define __FPU_USED       0
+    #endif
+  #else
+    #define __FPU_USED         0
+  #endif
+
+#elif defined ( __GNUC__ )
+  #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+    #if (__FPU_PRESENT == 1)
+      #define __FPU_USED       1
+    #else
+      #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+      #define __FPU_USED       0
+    #endif
+  #else
+    #define __FPU_USED         0
+  #endif
+
+#elif defined ( __TASKING__ )
+  #if defined __FPU_VFP__
+    #if (__FPU_PRESENT == 1)
+      #define __FPU_USED       1
+    #else
+      #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+      #define __FPU_USED       0
+    #endif
+  #else
+    #define __FPU_USED         0
+  #endif
+#endif
+
+#include <stdint.h>                      /* standard types definitions                      */
+#include <core_cmInstr.h>                /* Core Instruction Access                         */
+#include <core_cmFunc.h>                 /* Core Function Access                            */
+#include <core_cm4_simd.h>               /* Compiler specific SIMD Intrinsics               */
+
+#endif /* __CORE_CM4_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_CM4_H_DEPENDANT
+#define __CORE_CM4_H_DEPENDANT
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+  #ifndef __CM4_REV
+    #define __CM4_REV               0x0000
+    #warning "__CM4_REV not defined in device header file; using default!"
+  #endif
+
+  #ifndef __FPU_PRESENT
+    #define __FPU_PRESENT             0
+    #warning "__FPU_PRESENT not defined in device header file; using default!"
+  #endif
+
+  #ifndef __MPU_PRESENT
+    #define __MPU_PRESENT             0
+    #warning "__MPU_PRESENT not defined in device header file; using default!"
+  #endif
+
+  #ifndef __NVIC_PRIO_BITS
+    #define __NVIC_PRIO_BITS          4
+    #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+  #endif
+
+  #ifndef __Vendor_SysTickConfig
+    #define __Vendor_SysTickConfig    0
+    #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+  #endif
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+    \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+    <strong>IO Type Qualifiers</strong> are used
+    \li to specify the access to peripheral variables.
+    \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+  #define   __I     volatile             /*!< Defines 'read only' permissions                 */
+#else
+  #define   __I     volatile const       /*!< Defines 'read only' permissions                 */
+#endif
+#define     __O     volatile             /*!< Defines 'write only' permissions                */
+#define     __IO    volatile             /*!< Defines 'read / write' permissions              */
+
+/*@} end of group Cortex_M4 */
+
+
+
+/*******************************************************************************
+ *                 Register Abstraction
+  Core Register contain:
+  - Core Register
+  - Core NVIC Register
+  - Core SCB Register
+  - Core SysTick Register
+  - Core Debug Register
+  - Core MPU Register
+  - Core FPU Register
+ ******************************************************************************/
+/** \defgroup CMSIS_core_register Defines and Type Definitions
+    \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/** \ingroup    CMSIS_core_register
+    \defgroup   CMSIS_CORE  Status and Control Registers
+    \brief  Core Register type definitions.
+  @{
+ */
+
+/** \brief  Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+  struct
+  {
+#if (__CORTEX_M != 0x04)
+    uint32_t _reserved0:27;              /*!< bit:  0..26  Reserved                           */
+#else
+    uint32_t _reserved0:16;              /*!< bit:  0..15  Reserved                           */
+    uint32_t GE:4;                       /*!< bit: 16..19  Greater than or Equal flags        */
+    uint32_t _reserved1:7;               /*!< bit: 20..26  Reserved                           */
+#endif
+    uint32_t Q:1;                        /*!< bit:     27  Saturation condition flag          */
+    uint32_t V:1;                        /*!< bit:     28  Overflow condition code flag       */
+    uint32_t C:1;                        /*!< bit:     29  Carry condition code flag          */
+    uint32_t Z:1;                        /*!< bit:     30  Zero condition code flag           */
+    uint32_t N:1;                        /*!< bit:     31  Negative condition code flag       */
+  } b;                                   /*!< Structure used for bit  access                  */
+  uint32_t w;                            /*!< Type      used for word access                  */
+} APSR_Type;
+
+
+/** \brief  Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+  struct
+  {
+    uint32_t ISR:9;                      /*!< bit:  0.. 8  Exception number                   */
+    uint32_t _reserved0:23;              /*!< bit:  9..31  Reserved                           */
+  } b;                                   /*!< Structure used for bit  access                  */
+  uint32_t w;                            /*!< Type      used for word access                  */
+} IPSR_Type;
+
+
+/** \brief  Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+  struct
+  {
+    uint32_t ISR:9;                      /*!< bit:  0.. 8  Exception number                   */
+#if (__CORTEX_M != 0x04)
+    uint32_t _reserved0:15;              /*!< bit:  9..23  Reserved                           */
+#else
+    uint32_t _reserved0:7;               /*!< bit:  9..15  Reserved                           */
+    uint32_t GE:4;                       /*!< bit: 16..19  Greater than or Equal flags        */
+    uint32_t _reserved1:4;               /*!< bit: 20..23  Reserved                           */
+#endif
+    uint32_t T:1;                        /*!< bit:     24  Thumb bit        (read 0)          */
+    uint32_t IT:2;                       /*!< bit: 25..26  saved IT state   (read 0)          */
+    uint32_t Q:1;                        /*!< bit:     27  Saturation condition flag          */
+    uint32_t V:1;                        /*!< bit:     28  Overflow condition code flag       */
+    uint32_t C:1;                        /*!< bit:     29  Carry condition code flag          */
+    uint32_t Z:1;                        /*!< bit:     30  Zero condition code flag           */
+    uint32_t N:1;                        /*!< bit:     31  Negative condition code flag       */
+  } b;                                   /*!< Structure used for bit  access                  */
+  uint32_t w;                            /*!< Type      used for word access                  */
+} xPSR_Type;
+
+
+/** \brief  Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+  struct
+  {
+    uint32_t nPRIV:1;                    /*!< bit:      0  Execution privilege in Thread mode */
+    uint32_t SPSEL:1;                    /*!< bit:      1  Stack to be used                   */
+    uint32_t FPCA:1;                     /*!< bit:      2  FP extension active flag           */
+    uint32_t _reserved0:29;              /*!< bit:  3..31  Reserved                           */
+  } b;                                   /*!< Structure used for bit  access                  */
+  uint32_t w;                            /*!< Type      used for word access                  */
+} CONTROL_Type;
+
+/*@} end of group CMSIS_CORE */
+
+
+/** \ingroup    CMSIS_core_register
+    \defgroup   CMSIS_NVIC  Nested Vectored Interrupt Controller (NVIC)
+    \brief      Type definitions for the NVIC Registers
+  @{
+ */
+
+/** \brief  Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+  __IO uint32_t ISER[8];                 /*!< Offset: 0x000 (R/W)  Interrupt Set Enable Register           */
+       uint32_t RESERVED0[24];
+  __IO uint32_t ICER[8];                 /*!< Offset: 0x080 (R/W)  Interrupt Clear Enable Register         */
+       uint32_t RSERVED1[24];
+  __IO uint32_t ISPR[8];                 /*!< Offset: 0x100 (R/W)  Interrupt Set Pending Register          */
+       uint32_t RESERVED2[24];
+  __IO uint32_t ICPR[8];                 /*!< Offset: 0x180 (R/W)  Interrupt Clear Pending Register        */
+       uint32_t RESERVED3[24];
+  __IO uint32_t IABR[8];                 /*!< Offset: 0x200 (R/W)  Interrupt Active bit Register           */
+       uint32_t RESERVED4[56];
+  __IO uint8_t  IP[240];                 /*!< Offset: 0x300 (R/W)  Interrupt Priority Register (8Bit wide) */
+       uint32_t RESERVED5[644];
+  __O  uint32_t STIR;                    /*!< Offset: 0xE00 ( /W)  Software Trigger Interrupt Register     */
+}  NVIC_Type;
+
+/* Software Triggered Interrupt Register Definitions */
+#define NVIC_STIR_INTID_Pos                 0                                          /*!< STIR: INTLINESNUM Position */
+#define NVIC_STIR_INTID_Msk                (0x1FFUL << NVIC_STIR_INTID_Pos)            /*!< STIR: INTLINESNUM Mask */
+
+/*@} end of group CMSIS_NVIC */
+
+
+/** \ingroup  CMSIS_core_register
+    \defgroup CMSIS_SCB     System Control Block (SCB)
+    \brief      Type definitions for the System Control Block Registers
+  @{
+ */
+
+/** \brief  Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+  __I  uint32_t CPUID;                   /*!< Offset: 0x000 (R/ )  CPUID Base Register                                   */
+  __IO uint32_t ICSR;                    /*!< Offset: 0x004 (R/W)  Interrupt Control and State Register                  */
+  __IO uint32_t VTOR;                    /*!< Offset: 0x008 (R/W)  Vector Table Offset Register                          */
+  __IO uint32_t AIRCR;                   /*!< Offset: 0x00C (R/W)  Application Interrupt and Reset Control Register      */
+  __IO uint32_t SCR;                     /*!< Offset: 0x010 (R/W)  System Control Register                               */
+  __IO uint32_t CCR;                     /*!< Offset: 0x014 (R/W)  Configuration Control Register                        */
+  __IO uint8_t  SHP[12];                 /*!< Offset: 0x018 (R/W)  System Handlers Priority Registers (4-7, 8-11, 12-15) */
+  __IO uint32_t SHCSR;                   /*!< Offset: 0x024 (R/W)  System Handler Control and State Register             */
+  __IO uint32_t CFSR;                    /*!< Offset: 0x028 (R/W)  Configurable Fault Status Register                    */
+  __IO uint32_t HFSR;                    /*!< Offset: 0x02C (R/W)  HardFault Status Register                             */
+  __IO uint32_t DFSR;                    /*!< Offset: 0x030 (R/W)  Debug Fault Status Register                           */
+  __IO uint32_t MMFAR;                   /*!< Offset: 0x034 (R/W)  MemManage Fault Address Register                      */
+  __IO uint32_t BFAR;                    /*!< Offset: 0x038 (R/W)  BusFault Address Register                             */
+  __IO uint32_t AFSR;                    /*!< Offset: 0x03C (R/W)  Auxiliary Fault Status Register                       */
+  __I  uint32_t PFR[2];                  /*!< Offset: 0x040 (R/ )  Processor Feature Register                            */
+  __I  uint32_t DFR;                     /*!< Offset: 0x048 (R/ )  Debug Feature Register                                */
+  __I  uint32_t ADR;                     /*!< Offset: 0x04C (R/ )  Auxiliary Feature Register                            */
+  __I  uint32_t MMFR[4];                 /*!< Offset: 0x050 (R/ )  Memory Model Feature Register                         */
+  __I  uint32_t ISAR[5];                 /*!< Offset: 0x060 (R/ )  Instruction Set Attributes Register                   */
+       uint32_t RESERVED0[5];
+  __IO uint32_t CPACR;                   /*!< Offset: 0x088 (R/W)  Coprocessor Access Control Register                   */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos          24                                             /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk          (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos)          /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos              20                                             /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk              (0xFUL << SCB_CPUID_VARIANT_Pos)               /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos         16                                             /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk         (0xFUL << SCB_CPUID_ARCHITECTURE_Pos)          /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos                4                                             /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk               (0xFFFUL << SCB_CPUID_PARTNO_Pos)              /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos              0                                             /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk             (0xFUL << SCB_CPUID_REVISION_Pos)              /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_NMIPENDSET_Pos            31                                             /*!< SCB ICSR: NMIPENDSET Position */
+#define SCB_ICSR_NMIPENDSET_Msk            (1UL << SCB_ICSR_NMIPENDSET_Pos)               /*!< SCB ICSR: NMIPENDSET Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos             28                                             /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk             (1UL << SCB_ICSR_PENDSVSET_Pos)                /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos             27                                             /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk             (1UL << SCB_ICSR_PENDSVCLR_Pos)                /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos             26                                             /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk             (1UL << SCB_ICSR_PENDSTSET_Pos)                /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos             25                                             /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk             (1UL << SCB_ICSR_PENDSTCLR_Pos)                /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_ISRPREEMPT_Pos            23                                             /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk            (1UL << SCB_ICSR_ISRPREEMPT_Pos)               /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos            22                                             /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk            (1UL << SCB_ICSR_ISRPENDING_Pos)               /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos           12                                             /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk           (0x1FFUL << SCB_ICSR_VECTPENDING_Pos)          /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_RETTOBASE_Pos             11                                             /*!< SCB ICSR: RETTOBASE Position */
+#define SCB_ICSR_RETTOBASE_Msk             (1UL << SCB_ICSR_RETTOBASE_Pos)                /*!< SCB ICSR: RETTOBASE Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos             0                                             /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk            (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos)           /*!< SCB ICSR: VECTACTIVE Mask */
+
+/* SCB Vector Table Offset Register Definitions */
+#define SCB_VTOR_TBLOFF_Pos                 7                                             /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk                (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos)           /*!< SCB VTOR: TBLOFF Mask */
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos              16                                             /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk              (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos)            /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos          16                                             /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk          (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos)        /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos            15                                             /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk            (1UL << SCB_AIRCR_ENDIANESS_Pos)               /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_PRIGROUP_Pos              8                                             /*!< SCB AIRCR: PRIGROUP Position */
+#define SCB_AIRCR_PRIGROUP_Msk             (7UL << SCB_AIRCR_PRIGROUP_Pos)                /*!< SCB AIRCR: PRIGROUP Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos           2                                             /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk          (1UL << SCB_AIRCR_SYSRESETREQ_Pos)             /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos         1                                             /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk        (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos)           /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+#define SCB_AIRCR_VECTRESET_Pos             0                                             /*!< SCB AIRCR: VECTRESET Position */
+#define SCB_AIRCR_VECTRESET_Msk            (1UL << SCB_AIRCR_VECTRESET_Pos)               /*!< SCB AIRCR: VECTRESET Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos               4                                             /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk              (1UL << SCB_SCR_SEVONPEND_Pos)                 /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos               2                                             /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk              (1UL << SCB_SCR_SLEEPDEEP_Pos)                 /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos             1                                             /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk            (1UL << SCB_SCR_SLEEPONEXIT_Pos)               /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_STKALIGN_Pos                9                                             /*!< SCB CCR: STKALIGN Position */
+#define SCB_CCR_STKALIGN_Msk               (1UL << SCB_CCR_STKALIGN_Pos)                  /*!< SCB CCR: STKALIGN Mask */
+
+#define SCB_CCR_BFHFNMIGN_Pos               8                                             /*!< SCB CCR: BFHFNMIGN Position */
+#define SCB_CCR_BFHFNMIGN_Msk              (1UL << SCB_CCR_BFHFNMIGN_Pos)                 /*!< SCB CCR: BFHFNMIGN Mask */
+
+#define SCB_CCR_DIV_0_TRP_Pos               4                                             /*!< SCB CCR: DIV_0_TRP Position */
+#define SCB_CCR_DIV_0_TRP_Msk              (1UL << SCB_CCR_DIV_0_TRP_Pos)                 /*!< SCB CCR: DIV_0_TRP Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos             3                                             /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk            (1UL << SCB_CCR_UNALIGN_TRP_Pos)               /*!< SCB CCR: UNALIGN_TRP Mask */
+
+#define SCB_CCR_USERSETMPEND_Pos            1                                             /*!< SCB CCR: USERSETMPEND Position */
+#define SCB_CCR_USERSETMPEND_Msk           (1UL << SCB_CCR_USERSETMPEND_Pos)              /*!< SCB CCR: USERSETMPEND Mask */
+
+#define SCB_CCR_NONBASETHRDENA_Pos          0                                             /*!< SCB CCR: NONBASETHRDENA Position */
+#define SCB_CCR_NONBASETHRDENA_Msk         (1UL << SCB_CCR_NONBASETHRDENA_Pos)            /*!< SCB CCR: NONBASETHRDENA Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_USGFAULTENA_Pos          18                                             /*!< SCB SHCSR: USGFAULTENA Position */
+#define SCB_SHCSR_USGFAULTENA_Msk          (1UL << SCB_SHCSR_USGFAULTENA_Pos)             /*!< SCB SHCSR: USGFAULTENA Mask */
+
+#define SCB_SHCSR_BUSFAULTENA_Pos          17                                             /*!< SCB SHCSR: BUSFAULTENA Position */
+#define SCB_SHCSR_BUSFAULTENA_Msk          (1UL << SCB_SHCSR_BUSFAULTENA_Pos)             /*!< SCB SHCSR: BUSFAULTENA Mask */
+
+#define SCB_SHCSR_MEMFAULTENA_Pos          16                                             /*!< SCB SHCSR: MEMFAULTENA Position */
+#define SCB_SHCSR_MEMFAULTENA_Msk          (1UL << SCB_SHCSR_MEMFAULTENA_Pos)             /*!< SCB SHCSR: MEMFAULTENA Mask */
+
+#define SCB_SHCSR_SVCALLPENDED_Pos         15                                             /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk         (1UL << SCB_SHCSR_SVCALLPENDED_Pos)            /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+#define SCB_SHCSR_BUSFAULTPENDED_Pos       14                                             /*!< SCB SHCSR: BUSFAULTPENDED Position */
+#define SCB_SHCSR_BUSFAULTPENDED_Msk       (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos)          /*!< SCB SHCSR: BUSFAULTPENDED Mask */
+
+#define SCB_SHCSR_MEMFAULTPENDED_Pos       13                                             /*!< SCB SHCSR: MEMFAULTPENDED Position */
+#define SCB_SHCSR_MEMFAULTPENDED_Msk       (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos)          /*!< SCB SHCSR: MEMFAULTPENDED Mask */
+
+#define SCB_SHCSR_USGFAULTPENDED_Pos       12                                             /*!< SCB SHCSR: USGFAULTPENDED Position */
+#define SCB_SHCSR_USGFAULTPENDED_Msk       (1UL << SCB_SHCSR_USGFAULTPENDED_Pos)          /*!< SCB SHCSR: USGFAULTPENDED Mask */
+
+#define SCB_SHCSR_SYSTICKACT_Pos           11                                             /*!< SCB SHCSR: SYSTICKACT Position */
+#define SCB_SHCSR_SYSTICKACT_Msk           (1UL << SCB_SHCSR_SYSTICKACT_Pos)              /*!< SCB SHCSR: SYSTICKACT Mask */
+
+#define SCB_SHCSR_PENDSVACT_Pos            10                                             /*!< SCB SHCSR: PENDSVACT Position */
+#define SCB_SHCSR_PENDSVACT_Msk            (1UL << SCB_SHCSR_PENDSVACT_Pos)               /*!< SCB SHCSR: PENDSVACT Mask */
+
+#define SCB_SHCSR_MONITORACT_Pos            8                                             /*!< SCB SHCSR: MONITORACT Position */
+#define SCB_SHCSR_MONITORACT_Msk           (1UL << SCB_SHCSR_MONITORACT_Pos)              /*!< SCB SHCSR: MONITORACT Mask */
+
+#define SCB_SHCSR_SVCALLACT_Pos             7                                             /*!< SCB SHCSR: SVCALLACT Position */
+#define SCB_SHCSR_SVCALLACT_Msk            (1UL << SCB_SHCSR_SVCALLACT_Pos)               /*!< SCB SHCSR: SVCALLACT Mask */
+
+#define SCB_SHCSR_USGFAULTACT_Pos           3                                             /*!< SCB SHCSR: USGFAULTACT Position */
+#define SCB_SHCSR_USGFAULTACT_Msk          (1UL << SCB_SHCSR_USGFAULTACT_Pos)             /*!< SCB SHCSR: USGFAULTACT Mask */
+
+#define SCB_SHCSR_BUSFAULTACT_Pos           1                                             /*!< SCB SHCSR: BUSFAULTACT Position */
+#define SCB_SHCSR_BUSFAULTACT_Msk          (1UL << SCB_SHCSR_BUSFAULTACT_Pos)             /*!< SCB SHCSR: BUSFAULTACT Mask */
+
+#define SCB_SHCSR_MEMFAULTACT_Pos           0                                             /*!< SCB SHCSR: MEMFAULTACT Position */
+#define SCB_SHCSR_MEMFAULTACT_Msk          (1UL << SCB_SHCSR_MEMFAULTACT_Pos)             /*!< SCB SHCSR: MEMFAULTACT Mask */
+
+/* SCB Configurable Fault Status Registers Definitions */
+#define SCB_CFSR_USGFAULTSR_Pos            16                                             /*!< SCB CFSR: Usage Fault Status Register Position */
+#define SCB_CFSR_USGFAULTSR_Msk            (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos)          /*!< SCB CFSR: Usage Fault Status Register Mask */
+
+#define SCB_CFSR_BUSFAULTSR_Pos             8                                             /*!< SCB CFSR: Bus Fault Status Register Position */
+#define SCB_CFSR_BUSFAULTSR_Msk            (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos)            /*!< SCB CFSR: Bus Fault Status Register Mask */
+
+#define SCB_CFSR_MEMFAULTSR_Pos             0                                             /*!< SCB CFSR: Memory Manage Fault Status Register Position */
+#define SCB_CFSR_MEMFAULTSR_Msk            (0xFFUL << SCB_CFSR_MEMFAULTSR_Pos)            /*!< SCB CFSR: Memory Manage Fault Status Register Mask */
+
+/* SCB Hard Fault Status Registers Definitions */
+#define SCB_HFSR_DEBUGEVT_Pos              31                                             /*!< SCB HFSR: DEBUGEVT Position */
+#define SCB_HFSR_DEBUGEVT_Msk              (1UL << SCB_HFSR_DEBUGEVT_Pos)                 /*!< SCB HFSR: DEBUGEVT Mask */
+
+#define SCB_HFSR_FORCED_Pos                30                                             /*!< SCB HFSR: FORCED Position */
+#define SCB_HFSR_FORCED_Msk                (1UL << SCB_HFSR_FORCED_Pos)                   /*!< SCB HFSR: FORCED Mask */
+
+#define SCB_HFSR_VECTTBL_Pos                1                                             /*!< SCB HFSR: VECTTBL Position */
+#define SCB_HFSR_VECTTBL_Msk               (1UL << SCB_HFSR_VECTTBL_Pos)                  /*!< SCB HFSR: VECTTBL Mask */
+
+/* SCB Debug Fault Status Register Definitions */
+#define SCB_DFSR_EXTERNAL_Pos               4                                             /*!< SCB DFSR: EXTERNAL Position */
+#define SCB_DFSR_EXTERNAL_Msk              (1UL << SCB_DFSR_EXTERNAL_Pos)                 /*!< SCB DFSR: EXTERNAL Mask */
+
+#define SCB_DFSR_VCATCH_Pos                 3                                             /*!< SCB DFSR: VCATCH Position */
+#define SCB_DFSR_VCATCH_Msk                (1UL << SCB_DFSR_VCATCH_Pos)                   /*!< SCB DFSR: VCATCH Mask */
+
+#define SCB_DFSR_DWTTRAP_Pos                2                                             /*!< SCB DFSR: DWTTRAP Position */
+#define SCB_DFSR_DWTTRAP_Msk               (1UL << SCB_DFSR_DWTTRAP_Pos)                  /*!< SCB DFSR: DWTTRAP Mask */
+
+#define SCB_DFSR_BKPT_Pos                   1                                             /*!< SCB DFSR: BKPT Position */
+#define SCB_DFSR_BKPT_Msk                  (1UL << SCB_DFSR_BKPT_Pos)                     /*!< SCB DFSR: BKPT Mask */
+
+#define SCB_DFSR_HALTED_Pos                 0                                             /*!< SCB DFSR: HALTED Position */
+#define SCB_DFSR_HALTED_Msk                (1UL << SCB_DFSR_HALTED_Pos)                   /*!< SCB DFSR: HALTED Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/** \ingroup  CMSIS_core_register
+    \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB)
+    \brief      Type definitions for the System Control and ID Register not in the SCB
+  @{
+ */
+
+/** \brief  Structure type to access the System Control and ID Register not in the SCB.
+ */
+typedef struct
+{
+       uint32_t RESERVED0[1];
+  __I  uint32_t ICTR;                    /*!< Offset: 0x004 (R/ )  Interrupt Controller Type Register      */
+  __IO uint32_t ACTLR;                   /*!< Offset: 0x008 (R/W)  Auxiliary Control Register              */
+} SCnSCB_Type;
+
+/* Interrupt Controller Type Register Definitions */
+#define SCnSCB_ICTR_INTLINESNUM_Pos         0                                          /*!< ICTR: INTLINESNUM Position */
+#define SCnSCB_ICTR_INTLINESNUM_Msk        (0xFUL << SCnSCB_ICTR_INTLINESNUM_Pos)      /*!< ICTR: INTLINESNUM Mask */
+
+/* Auxiliary Control Register Definitions */
+#define SCnSCB_ACTLR_DISOOFP_Pos            9                                          /*!< ACTLR: DISOOFP Position */
+#define SCnSCB_ACTLR_DISOOFP_Msk           (1UL << SCnSCB_ACTLR_DISOOFP_Pos)           /*!< ACTLR: DISOOFP Mask */
+
+#define SCnSCB_ACTLR_DISFPCA_Pos            8                                          /*!< ACTLR: DISFPCA Position */
+#define SCnSCB_ACTLR_DISFPCA_Msk           (1UL << SCnSCB_ACTLR_DISFPCA_Pos)           /*!< ACTLR: DISFPCA Mask */
+
+#define SCnSCB_ACTLR_DISFOLD_Pos            2                                          /*!< ACTLR: DISFOLD Position */
+#define SCnSCB_ACTLR_DISFOLD_Msk           (1UL << SCnSCB_ACTLR_DISFOLD_Pos)           /*!< ACTLR: DISFOLD Mask */
+
+#define SCnSCB_ACTLR_DISDEFWBUF_Pos         1                                          /*!< ACTLR: DISDEFWBUF Position */
+#define SCnSCB_ACTLR_DISDEFWBUF_Msk        (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos)        /*!< ACTLR: DISDEFWBUF Mask */
+
+#define SCnSCB_ACTLR_DISMCYCINT_Pos         0                                          /*!< ACTLR: DISMCYCINT Position */
+#define SCnSCB_ACTLR_DISMCYCINT_Msk        (1UL << SCnSCB_ACTLR_DISMCYCINT_Pos)        /*!< ACTLR: DISMCYCINT Mask */
+
+/*@} end of group CMSIS_SCnotSCB */
+
+
+/** \ingroup  CMSIS_core_register
+    \defgroup CMSIS_SysTick     System Tick Timer (SysTick)
+    \brief      Type definitions for the System Timer Registers.
+  @{
+ */
+
+/** \brief  Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+  __IO uint32_t CTRL;                    /*!< Offset: 0x000 (R/W)  SysTick Control and Status Register */
+  __IO uint32_t LOAD;                    /*!< Offset: 0x004 (R/W)  SysTick Reload Value Register       */
+  __IO uint32_t VAL;                     /*!< Offset: 0x008 (R/W)  SysTick Current Value Register      */
+  __I  uint32_t CALIB;                   /*!< Offset: 0x00C (R/ )  SysTick Calibration Register        */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos         16                                             /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk         (1UL << SysTick_CTRL_COUNTFLAG_Pos)            /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos          2                                             /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk         (1UL << SysTick_CTRL_CLKSOURCE_Pos)            /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos            1                                             /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk           (1UL << SysTick_CTRL_TICKINT_Pos)              /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos             0                                             /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk            (1UL << SysTick_CTRL_ENABLE_Pos)               /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos             0                                             /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk            (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos)        /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos             0                                             /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk            (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos)        /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos            31                                             /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk            (1UL << SysTick_CALIB_NOREF_Pos)               /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos             30                                             /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk             (1UL << SysTick_CALIB_SKEW_Pos)                /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos             0                                             /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk            (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos)        /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+
+/** \ingroup  CMSIS_core_register
+    \defgroup CMSIS_ITM     Instrumentation Trace Macrocell (ITM)
+    \brief      Type definitions for the Instrumentation Trace Macrocell (ITM)
+  @{
+ */
+
+/** \brief  Structure type to access the Instrumentation Trace Macrocell Register (ITM).
+ */
+typedef struct
+{
+  __O  union
+  {
+    __O  uint8_t    u8;                  /*!< Offset: 0x000 ( /W)  ITM Stimulus Port 8-bit                   */
+    __O  uint16_t   u16;                 /*!< Offset: 0x000 ( /W)  ITM Stimulus Port 16-bit                  */
+    __O  uint32_t   u32;                 /*!< Offset: 0x000 ( /W)  ITM Stimulus Port 32-bit                  */
+  }  PORT [32];                          /*!< Offset: 0x000 ( /W)  ITM Stimulus Port Registers               */
+       uint32_t RESERVED0[864];
+  __IO uint32_t TER;                     /*!< Offset: 0xE00 (R/W)  ITM Trace Enable Register                 */
+       uint32_t RESERVED1[15];
+  __IO uint32_t TPR;                     /*!< Offset: 0xE40 (R/W)  ITM Trace Privilege Register              */
+       uint32_t RESERVED2[15];
+  __IO uint32_t TCR;                     /*!< Offset: 0xE80 (R/W)  ITM Trace Control Register                */
+       uint32_t RESERVED3[29];                                  
+  __O  uint32_t IWR;                     /*!< Offset: 0xEF8 ( /W)  ITM Integration Write Register            */
+  __I  uint32_t IRR;                     /*!< Offset: 0xEFC (R/ )  ITM Integration Read Register             */
+  __IO uint32_t IMCR;                    /*!< Offset: 0xF00 (R/W)  ITM Integration Mode Control Register     */
+       uint32_t RESERVED4[43];                                  
+  __O  uint32_t LAR;                     /*!< Offset: 0xFB0 ( /W)  ITM Lock Access Register                  */
+  __I  uint32_t LSR;                     /*!< Offset: 0xFB4 (R/ )  ITM Lock Status Register                  */
+       uint32_t RESERVED5[6];                                   
+  __I  uint32_t PID4;                    /*!< Offset: 0xFD0 (R/ )  ITM Peripheral Identification Register #4 */
+  __I  uint32_t PID5;                    /*!< Offset: 0xFD4 (R/ )  ITM Peripheral Identification Register #5 */
+  __I  uint32_t PID6;                    /*!< Offset: 0xFD8 (R/ )  ITM Peripheral Identification Register #6 */
+  __I  uint32_t PID7;                    /*!< Offset: 0xFDC (R/ )  ITM Peripheral Identification Register #7 */
+  __I  uint32_t PID0;                    /*!< Offset: 0xFE0 (R/ )  ITM Peripheral Identification Register #0 */
+  __I  uint32_t PID1;                    /*!< Offset: 0xFE4 (R/ )  ITM Peripheral Identification Register #1 */
+  __I  uint32_t PID2;                    /*!< Offset: 0xFE8 (R/ )  ITM Peripheral Identification Register #2 */
+  __I  uint32_t PID3;                    /*!< Offset: 0xFEC (R/ )  ITM Peripheral Identification Register #3 */
+  __I  uint32_t CID0;                    /*!< Offset: 0xFF0 (R/ )  ITM Component  Identification Register #0 */
+  __I  uint32_t CID1;                    /*!< Offset: 0xFF4 (R/ )  ITM Component  Identification Register #1 */
+  __I  uint32_t CID2;                    /*!< Offset: 0xFF8 (R/ )  ITM Component  Identification Register #2 */
+  __I  uint32_t CID3;                    /*!< Offset: 0xFFC (R/ )  ITM Component  Identification Register #3 */
+} ITM_Type;
+
+/* ITM Trace Privilege Register Definitions */
+#define ITM_TPR_PRIVMASK_Pos                0                                             /*!< ITM TPR: PRIVMASK Position */
+#define ITM_TPR_PRIVMASK_Msk               (0xFUL << ITM_TPR_PRIVMASK_Pos)                /*!< ITM TPR: PRIVMASK Mask */
+
+/* ITM Trace Control Register Definitions */
+#define ITM_TCR_BUSY_Pos                   23                                             /*!< ITM TCR: BUSY Position */
+#define ITM_TCR_BUSY_Msk                   (1UL << ITM_TCR_BUSY_Pos)                      /*!< ITM TCR: BUSY Mask */
+
+#define ITM_TCR_TraceBusID_Pos             16                                             /*!< ITM TCR: ATBID Position */
+#define ITM_TCR_TraceBusID_Msk             (0x7FUL << ITM_TCR_TraceBusID_Pos)             /*!< ITM TCR: ATBID Mask */
+
+#define ITM_TCR_GTSFREQ_Pos                10                                             /*!< ITM TCR: Global timestamp frequency Position */
+#define ITM_TCR_GTSFREQ_Msk                (3UL << ITM_TCR_GTSFREQ_Pos)                   /*!< ITM TCR: Global timestamp frequency Mask */
+
+#define ITM_TCR_TSPrescale_Pos              8                                             /*!< ITM TCR: TSPrescale Position */
+#define ITM_TCR_TSPrescale_Msk             (3UL << ITM_TCR_TSPrescale_Pos)                /*!< ITM TCR: TSPrescale Mask */
+
+#define ITM_TCR_SWOENA_Pos                  4                                             /*!< ITM TCR: SWOENA Position */
+#define ITM_TCR_SWOENA_Msk                 (1UL << ITM_TCR_SWOENA_Pos)                    /*!< ITM TCR: SWOENA Mask */
+
+#define ITM_TCR_DWTENA_Pos                  3                                             /*!< ITM TCR: DWTENA Position */
+#define ITM_TCR_DWTENA_Msk                 (1UL << ITM_TCR_DWTENA_Pos)                    /*!< ITM TCR: DWTENA Mask */
+
+#define ITM_TCR_SYNCENA_Pos                 2                                             /*!< ITM TCR: SYNCENA Position */
+#define ITM_TCR_SYNCENA_Msk                (1UL << ITM_TCR_SYNCENA_Pos)                   /*!< ITM TCR: SYNCENA Mask */
+
+#define ITM_TCR_TSENA_Pos                   1                                             /*!< ITM TCR: TSENA Position */
+#define ITM_TCR_TSENA_Msk                  (1UL << ITM_TCR_TSENA_Pos)                     /*!< ITM TCR: TSENA Mask */
+
+#define ITM_TCR_ITMENA_Pos                  0                                             /*!< ITM TCR: ITM Enable bit Position */
+#define ITM_TCR_ITMENA_Msk                 (1UL << ITM_TCR_ITMENA_Pos)                    /*!< ITM TCR: ITM Enable bit Mask */
+
+/* ITM Integration Write Register Definitions */
+#define ITM_IWR_ATVALIDM_Pos                0                                             /*!< ITM IWR: ATVALIDM Position */
+#define ITM_IWR_ATVALIDM_Msk               (1UL << ITM_IWR_ATVALIDM_Pos)                  /*!< ITM IWR: ATVALIDM Mask */
+
+/* ITM Integration Read Register Definitions */
+#define ITM_IRR_ATREADYM_Pos                0                                             /*!< ITM IRR: ATREADYM Position */
+#define ITM_IRR_ATREADYM_Msk               (1UL << ITM_IRR_ATREADYM_Pos)                  /*!< ITM IRR: ATREADYM Mask */
+
+/* ITM Integration Mode Control Register Definitions */
+#define ITM_IMCR_INTEGRATION_Pos            0                                             /*!< ITM IMCR: INTEGRATION Position */
+#define ITM_IMCR_INTEGRATION_Msk           (1UL << ITM_IMCR_INTEGRATION_Pos)              /*!< ITM IMCR: INTEGRATION Mask */
+
+/* ITM Lock Status Register Definitions */
+#define ITM_LSR_ByteAcc_Pos                 2                                             /*!< ITM LSR: ByteAcc Position */
+#define ITM_LSR_ByteAcc_Msk                (1UL << ITM_LSR_ByteAcc_Pos)                   /*!< ITM LSR: ByteAcc Mask */
+
+#define ITM_LSR_Access_Pos                  1                                             /*!< ITM LSR: Access Position */
+#define ITM_LSR_Access_Msk                 (1UL << ITM_LSR_Access_Pos)                    /*!< ITM LSR: Access Mask */
+
+#define ITM_LSR_Present_Pos                 0                                             /*!< ITM LSR: Present Position */
+#define ITM_LSR_Present_Msk                (1UL << ITM_LSR_Present_Pos)                   /*!< ITM LSR: Present Mask */
+
+/*@}*/ /* end of group CMSIS_ITM */
+
+
+/** \ingroup  CMSIS_core_register
+    \defgroup CMSIS_DWT     Data Watchpoint and Trace (DWT)
+    \brief      Type definitions for the Data Watchpoint and Trace (DWT)
+  @{
+ */
+
+/** \brief  Structure type to access the Data Watchpoint and Trace Register (DWT).
+ */
+typedef struct
+{
+  __IO uint32_t CTRL;                    /*!< Offset: 0x000 (R/W)  Control Register                          */
+  __IO uint32_t CYCCNT;                  /*!< Offset: 0x004 (R/W)  Cycle Count Register                      */
+  __IO uint32_t CPICNT;                  /*!< Offset: 0x008 (R/W)  CPI Count Register                        */
+  __IO uint32_t EXCCNT;                  /*!< Offset: 0x00C (R/W)  Exception Overhead Count Register         */
+  __IO uint32_t SLEEPCNT;                /*!< Offset: 0x010 (R/W)  Sleep Count Register                      */
+  __IO uint32_t LSUCNT;                  /*!< Offset: 0x014 (R/W)  LSU Count Register                        */
+  __IO uint32_t FOLDCNT;                 /*!< Offset: 0x018 (R/W)  Folded-instruction Count Register         */
+  __I  uint32_t PCSR;                    /*!< Offset: 0x01C (R/ )  Program Counter Sample Register           */
+  __IO uint32_t COMP0;                   /*!< Offset: 0x020 (R/W)  Comparator Register 0                     */
+  __IO uint32_t MASK0;                   /*!< Offset: 0x024 (R/W)  Mask Register 0                           */
+  __IO uint32_t FUNCTION0;               /*!< Offset: 0x028 (R/W)  Function Register 0                       */
+       uint32_t RESERVED0[1];
+  __IO uint32_t COMP1;                   /*!< Offset: 0x030 (R/W)  Comparator Register 1                     */
+  __IO uint32_t MASK1;                   /*!< Offset: 0x034 (R/W)  Mask Register 1                           */
+  __IO uint32_t FUNCTION1;               /*!< Offset: 0x038 (R/W)  Function Register 1                       */
+       uint32_t RESERVED1[1];
+  __IO uint32_t COMP2;                   /*!< Offset: 0x040 (R/W)  Comparator Register 2                     */
+  __IO uint32_t MASK2;                   /*!< Offset: 0x044 (R/W)  Mask Register 2                           */
+  __IO uint32_t FUNCTION2;               /*!< Offset: 0x048 (R/W)  Function Register 2                       */
+       uint32_t RESERVED2[1];
+  __IO uint32_t COMP3;                   /*!< Offset: 0x050 (R/W)  Comparator Register 3                     */
+  __IO uint32_t MASK3;                   /*!< Offset: 0x054 (R/W)  Mask Register 3                           */
+  __IO uint32_t FUNCTION3;               /*!< Offset: 0x058 (R/W)  Function Register 3                       */
+} DWT_Type;
+
+/* DWT Control Register Definitions */
+#define DWT_CTRL_NUMCOMP_Pos               28                                          /*!< DWT CTRL: NUMCOMP Position */
+#define DWT_CTRL_NUMCOMP_Msk               (0xFUL << DWT_CTRL_NUMCOMP_Pos)             /*!< DWT CTRL: NUMCOMP Mask */
+
+#define DWT_CTRL_NOTRCPKT_Pos              27                                          /*!< DWT CTRL: NOTRCPKT Position */
+#define DWT_CTRL_NOTRCPKT_Msk              (0x1UL << DWT_CTRL_NOTRCPKT_Pos)            /*!< DWT CTRL: NOTRCPKT Mask */
+
+#define DWT_CTRL_NOEXTTRIG_Pos             26                                          /*!< DWT CTRL: NOEXTTRIG Position */
+#define DWT_CTRL_NOEXTTRIG_Msk             (0x1UL << DWT_CTRL_NOEXTTRIG_Pos)           /*!< DWT CTRL: NOEXTTRIG Mask */
+
+#define DWT_CTRL_NOCYCCNT_Pos              25                                          /*!< DWT CTRL: NOCYCCNT Position */
+#define DWT_CTRL_NOCYCCNT_Msk              (0x1UL << DWT_CTRL_NOCYCCNT_Pos)            /*!< DWT CTRL: NOCYCCNT Mask */
+
+#define DWT_CTRL_NOPRFCNT_Pos              24                                          /*!< DWT CTRL: NOPRFCNT Position */
+#define DWT_CTRL_NOPRFCNT_Msk              (0x1UL << DWT_CTRL_NOPRFCNT_Pos)            /*!< DWT CTRL: NOPRFCNT Mask */
+
+#define DWT_CTRL_CYCEVTENA_Pos             22                                          /*!< DWT CTRL: CYCEVTENA Position */
+#define DWT_CTRL_CYCEVTENA_Msk             (0x1UL << DWT_CTRL_CYCEVTENA_Pos)           /*!< DWT CTRL: CYCEVTENA Mask */
+
+#define DWT_CTRL_FOLDEVTENA_Pos            21                                          /*!< DWT CTRL: FOLDEVTENA Position */
+#define DWT_CTRL_FOLDEVTENA_Msk            (0x1UL << DWT_CTRL_FOLDEVTENA_Pos)          /*!< DWT CTRL: FOLDEVTENA Mask */
+
+#define DWT_CTRL_LSUEVTENA_Pos             20                                          /*!< DWT CTRL: LSUEVTENA Position */
+#define DWT_CTRL_LSUEVTENA_Msk             (0x1UL << DWT_CTRL_LSUEVTENA_Pos)           /*!< DWT CTRL: LSUEVTENA Mask */
+
+#define DWT_CTRL_SLEEPEVTENA_Pos           19                                          /*!< DWT CTRL: SLEEPEVTENA Position */
+#define DWT_CTRL_SLEEPEVTENA_Msk           (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos)         /*!< DWT CTRL: SLEEPEVTENA Mask */
+
+#define DWT_CTRL_EXCEVTENA_Pos             18                                          /*!< DWT CTRL: EXCEVTENA Position */
+#define DWT_CTRL_EXCEVTENA_Msk             (0x1UL << DWT_CTRL_EXCEVTENA_Pos)           /*!< DWT CTRL: EXCEVTENA Mask */
+
+#define DWT_CTRL_CPIEVTENA_Pos             17                                          /*!< DWT CTRL: CPIEVTENA Position */
+#define DWT_CTRL_CPIEVTENA_Msk             (0x1UL << DWT_CTRL_CPIEVTENA_Pos)           /*!< DWT CTRL: CPIEVTENA Mask */
+
+#define DWT_CTRL_EXCTRCENA_Pos             16                                          /*!< DWT CTRL: EXCTRCENA Position */
+#define DWT_CTRL_EXCTRCENA_Msk             (0x1UL << DWT_CTRL_EXCTRCENA_Pos)           /*!< DWT CTRL: EXCTRCENA Mask */
+
+#define DWT_CTRL_PCSAMPLENA_Pos            12                                          /*!< DWT CTRL: PCSAMPLENA Position */
+#define DWT_CTRL_PCSAMPLENA_Msk            (0x1UL << DWT_CTRL_PCSAMPLENA_Pos)          /*!< DWT CTRL: PCSAMPLENA Mask */
+
+#define DWT_CTRL_SYNCTAP_Pos               10                                          /*!< DWT CTRL: SYNCTAP Position */
+#define DWT_CTRL_SYNCTAP_Msk               (0x3UL << DWT_CTRL_SYNCTAP_Pos)             /*!< DWT CTRL: SYNCTAP Mask */
+
+#define DWT_CTRL_CYCTAP_Pos                 9                                          /*!< DWT CTRL: CYCTAP Position */
+#define DWT_CTRL_CYCTAP_Msk                (0x1UL << DWT_CTRL_CYCTAP_Pos)              /*!< DWT CTRL: CYCTAP Mask */
+
+#define DWT_CTRL_POSTINIT_Pos               5                                          /*!< DWT CTRL: POSTINIT Position */
+#define DWT_CTRL_POSTINIT_Msk              (0xFUL << DWT_CTRL_POSTINIT_Pos)            /*!< DWT CTRL: POSTINIT Mask */
+
+#define DWT_CTRL_POSTPRESET_Pos             1                                          /*!< DWT CTRL: POSTPRESET Position */
+#define DWT_CTRL_POSTPRESET_Msk            (0xFUL << DWT_CTRL_POSTPRESET_Pos)          /*!< DWT CTRL: POSTPRESET Mask */
+
+#define DWT_CTRL_CYCCNTENA_Pos              0                                          /*!< DWT CTRL: CYCCNTENA Position */
+#define DWT_CTRL_CYCCNTENA_Msk             (0x1UL << DWT_CTRL_CYCCNTENA_Pos)           /*!< DWT CTRL: CYCCNTENA Mask */
+
+/* DWT CPI Count Register Definitions */
+#define DWT_CPICNT_CPICNT_Pos               0                                          /*!< DWT CPICNT: CPICNT Position */
+#define DWT_CPICNT_CPICNT_Msk              (0xFFUL << DWT_CPICNT_CPICNT_Pos)           /*!< DWT CPICNT: CPICNT Mask */
+
+/* DWT Exception Overhead Count Register Definitions */
+#define DWT_EXCCNT_EXCCNT_Pos               0                                          /*!< DWT EXCCNT: EXCCNT Position */
+#define DWT_EXCCNT_EXCCNT_Msk              (0xFFUL << DWT_EXCCNT_EXCCNT_Pos)           /*!< DWT EXCCNT: EXCCNT Mask */
+
+/* DWT Sleep Count Register Definitions */
+#define DWT_SLEEPCNT_SLEEPCNT_Pos           0                                          /*!< DWT SLEEPCNT: SLEEPCNT Position */
+#define DWT_SLEEPCNT_SLEEPCNT_Msk          (0xFFUL << DWT_SLEEPCNT_SLEEPCNT_Pos)       /*!< DWT SLEEPCNT: SLEEPCNT Mask */
+
+/* DWT LSU Count Register Definitions */
+#define DWT_LSUCNT_LSUCNT_Pos               0                                          /*!< DWT LSUCNT: LSUCNT Position */
+#define DWT_LSUCNT_LSUCNT_Msk              (0xFFUL << DWT_LSUCNT_LSUCNT_Pos)           /*!< DWT LSUCNT: LSUCNT Mask */
+
+/* DWT Folded-instruction Count Register Definitions */
+#define DWT_FOLDCNT_FOLDCNT_Pos             0                                          /*!< DWT FOLDCNT: FOLDCNT Position */
+#define DWT_FOLDCNT_FOLDCNT_Msk            (0xFFUL << DWT_FOLDCNT_FOLDCNT_Pos)         /*!< DWT FOLDCNT: FOLDCNT Mask */
+
+/* DWT Comparator Mask Register Definitions */
+#define DWT_MASK_MASK_Pos                   0                                          /*!< DWT MASK: MASK Position */
+#define DWT_MASK_MASK_Msk                  (0x1FUL << DWT_MASK_MASK_Pos)               /*!< DWT MASK: MASK Mask */
+
+/* DWT Comparator Function Register Definitions */
+#define DWT_FUNCTION_MATCHED_Pos           24                                          /*!< DWT FUNCTION: MATCHED Position */
+#define DWT_FUNCTION_MATCHED_Msk           (0x1UL << DWT_FUNCTION_MATCHED_Pos)         /*!< DWT FUNCTION: MATCHED Mask */
+
+#define DWT_FUNCTION_DATAVADDR1_Pos        16                                          /*!< DWT FUNCTION: DATAVADDR1 Position */
+#define DWT_FUNCTION_DATAVADDR1_Msk        (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos)      /*!< DWT FUNCTION: DATAVADDR1 Mask */
+
+#define DWT_FUNCTION_DATAVADDR0_Pos        12                                          /*!< DWT FUNCTION: DATAVADDR0 Position */
+#define DWT_FUNCTION_DATAVADDR0_Msk        (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos)      /*!< DWT FUNCTION: DATAVADDR0 Mask */
+
+#define DWT_FUNCTION_DATAVSIZE_Pos         10                                          /*!< DWT FUNCTION: DATAVSIZE Position */
+#define DWT_FUNCTION_DATAVSIZE_Msk         (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos)       /*!< DWT FUNCTION: DATAVSIZE Mask */
+
+#define DWT_FUNCTION_LNK1ENA_Pos            9                                          /*!< DWT FUNCTION: LNK1ENA Position */
+#define DWT_FUNCTION_LNK1ENA_Msk           (0x1UL << DWT_FUNCTION_LNK1ENA_Pos)         /*!< DWT FUNCTION: LNK1ENA Mask */
+
+#define DWT_FUNCTION_DATAVMATCH_Pos         8                                          /*!< DWT FUNCTION: DATAVMATCH Position */
+#define DWT_FUNCTION_DATAVMATCH_Msk        (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos)      /*!< DWT FUNCTION: DATAVMATCH Mask */
+
+#define DWT_FUNCTION_CYCMATCH_Pos           7                                          /*!< DWT FUNCTION: CYCMATCH Position */
+#define DWT_FUNCTION_CYCMATCH_Msk          (0x1UL << DWT_FUNCTION_CYCMATCH_Pos)        /*!< DWT FUNCTION: CYCMATCH Mask */
+
+#define DWT_FUNCTION_EMITRANGE_Pos          5                                          /*!< DWT FUNCTION: EMITRANGE Position */
+#define DWT_FUNCTION_EMITRANGE_Msk         (0x1UL << DWT_FUNCTION_EMITRANGE_Pos)       /*!< DWT FUNCTION: EMITRANGE Mask */
+
+#define DWT_FUNCTION_FUNCTION_Pos           0                                          /*!< DWT FUNCTION: FUNCTION Position */
+#define DWT_FUNCTION_FUNCTION_Msk          (0xFUL << DWT_FUNCTION_FUNCTION_Pos)        /*!< DWT FUNCTION: FUNCTION Mask */
+
+/*@}*/ /* end of group CMSIS_DWT */
+
+
+/** \ingroup  CMSIS_core_register
+    \defgroup CMSIS_TPI     Trace Port Interface (TPI)
+    \brief      Type definitions for the Trace Port Interface (TPI)
+  @{
+ */
+
+/** \brief  Structure type to access the Trace Port Interface Register (TPI).
+ */
+typedef struct
+{
+  __IO uint32_t SSPSR;                   /*!< Offset: 0x000 (R/ )  Supported Parallel Port Size Register     */
+  __IO uint32_t CSPSR;                   /*!< Offset: 0x004 (R/W)  Current Parallel Port Size Register */
+       uint32_t RESERVED0[2];
+  __IO uint32_t ACPR;                    /*!< Offset: 0x010 (R/W)  Asynchronous Clock Prescaler Register */
+       uint32_t RESERVED1[55];
+  __IO uint32_t SPPR;                    /*!< Offset: 0x0F0 (R/W)  Selected Pin Protocol Register */
+       uint32_t RESERVED2[131];
+  __I  uint32_t FFSR;                    /*!< Offset: 0x300 (R/ )  Formatter and Flush Status Register */
+  __IO uint32_t FFCR;                    /*!< Offset: 0x304 (R/W)  Formatter and Flush Control Register */
+  __I  uint32_t FSCR;                    /*!< Offset: 0x308 (R/ )  Formatter Synchronization Counter Register */
+       uint32_t RESERVED3[759];
+  __I  uint32_t TRIGGER;                 /*!< Offset: 0xEE8 (R/ )  TRIGGER */
+  __I  uint32_t FIFO0;                   /*!< Offset: 0xEEC (R/ )  Integration ETM Data */
+  __I  uint32_t ITATBCTR2;               /*!< Offset: 0xEF0 (R/ )  ITATBCTR2 */
+       uint32_t RESERVED4[1];
+  __I  uint32_t ITATBCTR0;               /*!< Offset: 0xEF8 (R/ )  ITATBCTR0 */
+  __I  uint32_t FIFO1;                   /*!< Offset: 0xEFC (R/ )  Integration ITM Data */
+  __IO uint32_t ITCTRL;                  /*!< Offset: 0xF00 (R/W)  Integration Mode Control */
+       uint32_t RESERVED5[39];
+  __IO uint32_t CLAIMSET;                /*!< Offset: 0xFA0 (R/W)  Claim tag set */
+  __IO uint32_t CLAIMCLR;                /*!< Offset: 0xFA4 (R/W)  Claim tag clear */
+       uint32_t RESERVED7[8];
+  __I  uint32_t DEVID;                   /*!< Offset: 0xFC8 (R/ )  TPIU_DEVID */
+  __I  uint32_t DEVTYPE;                 /*!< Offset: 0xFCC (R/ )  TPIU_DEVTYPE */
+} TPI_Type;
+
+/* TPI Asynchronous Clock Prescaler Register Definitions */
+#define TPI_ACPR_PRESCALER_Pos              0                                          /*!< TPI ACPR: PRESCALER Position */
+#define TPI_ACPR_PRESCALER_Msk             (0x1FFFUL << TPI_ACPR_PRESCALER_Pos)        /*!< TPI ACPR: PRESCALER Mask */
+
+/* TPI Selected Pin Protocol Register Definitions */
+#define TPI_SPPR_TXMODE_Pos                 0                                          /*!< TPI SPPR: TXMODE Position */
+#define TPI_SPPR_TXMODE_Msk                (0x3UL << TPI_SPPR_TXMODE_Pos)              /*!< TPI SPPR: TXMODE Mask */
+
+/* TPI Formatter and Flush Status Register Definitions */
+#define TPI_FFSR_FtNonStop_Pos              3                                          /*!< TPI FFSR: FtNonStop Position */
+#define TPI_FFSR_FtNonStop_Msk             (0x1UL << TPI_FFSR_FtNonStop_Pos)           /*!< TPI FFSR: FtNonStop Mask */
+
+#define TPI_FFSR_TCPresent_Pos              2                                          /*!< TPI FFSR: TCPresent Position */
+#define TPI_FFSR_TCPresent_Msk             (0x1UL << TPI_FFSR_TCPresent_Pos)           /*!< TPI FFSR: TCPresent Mask */
+
+#define TPI_FFSR_FtStopped_Pos              1                                          /*!< TPI FFSR: FtStopped Position */
+#define TPI_FFSR_FtStopped_Msk             (0x1UL << TPI_FFSR_FtStopped_Pos)           /*!< TPI FFSR: FtStopped Mask */
+
+#define TPI_FFSR_FlInProg_Pos               0                                          /*!< TPI FFSR: FlInProg Position */
+#define TPI_FFSR_FlInProg_Msk              (0x1UL << TPI_FFSR_FlInProg_Pos)            /*!< TPI FFSR: FlInProg Mask */
+
+/* TPI Formatter and Flush Control Register Definitions */
+#define TPI_FFCR_TrigIn_Pos                 8                                          /*!< TPI FFCR: TrigIn Position */
+#define TPI_FFCR_TrigIn_Msk                (0x1UL << TPI_FFCR_TrigIn_Pos)              /*!< TPI FFCR: TrigIn Mask */
+
+#define TPI_FFCR_EnFCont_Pos                1                                          /*!< TPI FFCR: EnFCont Position */
+#define TPI_FFCR_EnFCont_Msk               (0x1UL << TPI_FFCR_EnFCont_Pos)             /*!< TPI FFCR: EnFCont Mask */
+
+/* TPI TRIGGER Register Definitions */
+#define TPI_TRIGGER_TRIGGER_Pos             0                                          /*!< TPI TRIGGER: TRIGGER Position */
+#define TPI_TRIGGER_TRIGGER_Msk            (0x1UL << TPI_TRIGGER_TRIGGER_Pos)          /*!< TPI TRIGGER: TRIGGER Mask */
+
+/* TPI Integration ETM Data Register Definitions (FIFO0) */
+#define TPI_FIFO0_ITM_ATVALID_Pos          29                                          /*!< TPI FIFO0: ITM_ATVALID Position */
+#define TPI_FIFO0_ITM_ATVALID_Msk          (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos)        /*!< TPI FIFO0: ITM_ATVALID Mask */
+
+#define TPI_FIFO0_ITM_bytecount_Pos        27                                          /*!< TPI FIFO0: ITM_bytecount Position */
+#define TPI_FIFO0_ITM_bytecount_Msk        (0x3UL << TPI_FIFO0_ITM_bytecount_Pos)      /*!< TPI FIFO0: ITM_bytecount Mask */
+
+#define TPI_FIFO0_ETM_ATVALID_Pos          26                                          /*!< TPI FIFO0: ETM_ATVALID Position */
+#define TPI_FIFO0_ETM_ATVALID_Msk          (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos)        /*!< TPI FIFO0: ETM_ATVALID Mask */
+
+#define TPI_FIFO0_ETM_bytecount_Pos        24                                          /*!< TPI FIFO0: ETM_bytecount Position */
+#define TPI_FIFO0_ETM_bytecount_Msk        (0x3UL << TPI_FIFO0_ETM_bytecount_Pos)      /*!< TPI FIFO0: ETM_bytecount Mask */
+
+#define TPI_FIFO0_ETM2_Pos                 16                                          /*!< TPI FIFO0: ETM2 Position */
+#define TPI_FIFO0_ETM2_Msk                 (0xFFUL << TPI_FIFO0_ETM2_Pos)              /*!< TPI FIFO0: ETM2 Mask */
+
+#define TPI_FIFO0_ETM1_Pos                  8                                          /*!< TPI FIFO0: ETM1 Position */
+#define TPI_FIFO0_ETM1_Msk                 (0xFFUL << TPI_FIFO0_ETM1_Pos)              /*!< TPI FIFO0: ETM1 Mask */
+
+#define TPI_FIFO0_ETM0_Pos                  0                                          /*!< TPI FIFO0: ETM0 Position */
+#define TPI_FIFO0_ETM0_Msk                 (0xFFUL << TPI_FIFO0_ETM0_Pos)              /*!< TPI FIFO0: ETM0 Mask */
+
+/* TPI ITATBCTR2 Register Definitions */
+#define TPI_ITATBCTR2_ATREADY_Pos           0                                          /*!< TPI ITATBCTR2: ATREADY Position */
+#define TPI_ITATBCTR2_ATREADY_Msk          (0x1UL << TPI_ITATBCTR2_ATREADY_Pos)        /*!< TPI ITATBCTR2: ATREADY Mask */
+
+/* TPI Integration ITM Data Register Definitions (FIFO1) */
+#define TPI_FIFO1_ITM_ATVALID_Pos          29                                          /*!< TPI FIFO1: ITM_ATVALID Position */
+#define TPI_FIFO1_ITM_ATVALID_Msk          (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos)        /*!< TPI FIFO1: ITM_ATVALID Mask */
+
+#define TPI_FIFO1_ITM_bytecount_Pos        27                                          /*!< TPI FIFO1: ITM_bytecount Position */
+#define TPI_FIFO1_ITM_bytecount_Msk        (0x3UL << TPI_FIFO1_ITM_bytecount_Pos)      /*!< TPI FIFO1: ITM_bytecount Mask */
+
+#define TPI_FIFO1_ETM_ATVALID_Pos          26                                          /*!< TPI FIFO1: ETM_ATVALID Position */
+#define TPI_FIFO1_ETM_ATVALID_Msk          (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos)        /*!< TPI FIFO1: ETM_ATVALID Mask */
+
+#define TPI_FIFO1_ETM_bytecount_Pos        24                                          /*!< TPI FIFO1: ETM_bytecount Position */
+#define TPI_FIFO1_ETM_bytecount_Msk        (0x3UL << TPI_FIFO1_ETM_bytecount_Pos)      /*!< TPI FIFO1: ETM_bytecount Mask */
+
+#define TPI_FIFO1_ITM2_Pos                 16                                          /*!< TPI FIFO1: ITM2 Position */
+#define TPI_FIFO1_ITM2_Msk                 (0xFFUL << TPI_FIFO1_ITM2_Pos)              /*!< TPI FIFO1: ITM2 Mask */
+
+#define TPI_FIFO1_ITM1_Pos                  8                                          /*!< TPI FIFO1: ITM1 Position */
+#define TPI_FIFO1_ITM1_Msk                 (0xFFUL << TPI_FIFO1_ITM1_Pos)              /*!< TPI FIFO1: ITM1 Mask */
+
+#define TPI_FIFO1_ITM0_Pos                  0                                          /*!< TPI FIFO1: ITM0 Position */
+#define TPI_FIFO1_ITM0_Msk                 (0xFFUL << TPI_FIFO1_ITM0_Pos)              /*!< TPI FIFO1: ITM0 Mask */
+
+/* TPI ITATBCTR0 Register Definitions */
+#define TPI_ITATBCTR0_ATREADY_Pos           0                                          /*!< TPI ITATBCTR0: ATREADY Position */
+#define TPI_ITATBCTR0_ATREADY_Msk          (0x1UL << TPI_ITATBCTR0_ATREADY_Pos)        /*!< TPI ITATBCTR0: ATREADY Mask */
+
+/* TPI Integration Mode Control Register Definitions */
+#define TPI_ITCTRL_Mode_Pos                 0                                          /*!< TPI ITCTRL: Mode Position */
+#define TPI_ITCTRL_Mode_Msk                (0x1UL << TPI_ITCTRL_Mode_Pos)              /*!< TPI ITCTRL: Mode Mask */
+
+/* TPI DEVID Register Definitions */
+#define TPI_DEVID_NRZVALID_Pos             11                                          /*!< TPI DEVID: NRZVALID Position */
+#define TPI_DEVID_NRZVALID_Msk             (0x1UL << TPI_DEVID_NRZVALID_Pos)           /*!< TPI DEVID: NRZVALID Mask */
+
+#define TPI_DEVID_MANCVALID_Pos            10                                          /*!< TPI DEVID: MANCVALID Position */
+#define TPI_DEVID_MANCVALID_Msk            (0x1UL << TPI_DEVID_MANCVALID_Pos)          /*!< TPI DEVID: MANCVALID Mask */
+
+#define TPI_DEVID_PTINVALID_Pos             9                                          /*!< TPI DEVID: PTINVALID Position */
+#define TPI_DEVID_PTINVALID_Msk            (0x1UL << TPI_DEVID_PTINVALID_Pos)          /*!< TPI DEVID: PTINVALID Mask */
+
+#define TPI_DEVID_MinBufSz_Pos              6                                          /*!< TPI DEVID: MinBufSz Position */
+#define TPI_DEVID_MinBufSz_Msk             (0x7UL << TPI_DEVID_MinBufSz_Pos)           /*!< TPI DEVID: MinBufSz Mask */
+
+#define TPI_DEVID_AsynClkIn_Pos             5                                          /*!< TPI DEVID: AsynClkIn Position */
+#define TPI_DEVID_AsynClkIn_Msk            (0x1UL << TPI_DEVID_AsynClkIn_Pos)          /*!< TPI DEVID: AsynClkIn Mask */
+
+#define TPI_DEVID_NrTraceInput_Pos          0                                          /*!< TPI DEVID: NrTraceInput Position */
+#define TPI_DEVID_NrTraceInput_Msk         (0x1FUL << TPI_DEVID_NrTraceInput_Pos)      /*!< TPI DEVID: NrTraceInput Mask */
+
+/* TPI DEVTYPE Register Definitions */
+#define TPI_DEVTYPE_SubType_Pos             0                                          /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Msk            (0xFUL << TPI_DEVTYPE_SubType_Pos)          /*!< TPI DEVTYPE: SubType Mask */
+
+#define TPI_DEVTYPE_MajorType_Pos           4                                          /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk          (0xFUL << TPI_DEVTYPE_MajorType_Pos)        /*!< TPI DEVTYPE: MajorType Mask */
+
+/*@}*/ /* end of group CMSIS_TPI */
+
+
+#if (__MPU_PRESENT == 1)
+/** \ingroup  CMSIS_core_register
+    \defgroup CMSIS_MPU     Memory Protection Unit (MPU)
+    \brief      Type definitions for the Memory Protection Unit (MPU)
+  @{
+ */
+
+/** \brief  Structure type to access the Memory Protection Unit (MPU).
+ */
+typedef struct
+{
+  __I  uint32_t TYPE;                    /*!< Offset: 0x000 (R/ )  MPU Type Register                              */
+  __IO uint32_t CTRL;                    /*!< Offset: 0x004 (R/W)  MPU Control Register                           */
+  __IO uint32_t RNR;                     /*!< Offset: 0x008 (R/W)  MPU Region RNRber Register                     */
+  __IO uint32_t RBAR;                    /*!< Offset: 0x00C (R/W)  MPU Region Base Address Register               */
+  __IO uint32_t RASR;                    /*!< Offset: 0x010 (R/W)  MPU Region Attribute and Size Register         */
+  __IO uint32_t RBAR_A1;                 /*!< Offset: 0x014 (R/W)  MPU Alias 1 Region Base Address Register       */
+  __IO uint32_t RASR_A1;                 /*!< Offset: 0x018 (R/W)  MPU Alias 1 Region Attribute and Size Register */
+  __IO uint32_t RBAR_A2;                 /*!< Offset: 0x01C (R/W)  MPU Alias 2 Region Base Address Register       */
+  __IO uint32_t RASR_A2;                 /*!< Offset: 0x020 (R/W)  MPU Alias 2 Region Attribute and Size Register */
+  __IO uint32_t RBAR_A3;                 /*!< Offset: 0x024 (R/W)  MPU Alias 3 Region Base Address Register       */
+  __IO uint32_t RASR_A3;                 /*!< Offset: 0x028 (R/W)  MPU Alias 3 Region Attribute and Size Register */
+} MPU_Type;
+
+/* MPU Type Register */
+#define MPU_TYPE_IREGION_Pos               16                                             /*!< MPU TYPE: IREGION Position */
+#define MPU_TYPE_IREGION_Msk               (0xFFUL << MPU_TYPE_IREGION_Pos)               /*!< MPU TYPE: IREGION Mask */
+
+#define MPU_TYPE_DREGION_Pos                8                                             /*!< MPU TYPE: DREGION Position */
+#define MPU_TYPE_DREGION_Msk               (0xFFUL << MPU_TYPE_DREGION_Pos)               /*!< MPU TYPE: DREGION Mask */
+
+#define MPU_TYPE_SEPARATE_Pos               0                                             /*!< MPU TYPE: SEPARATE Position */
+#define MPU_TYPE_SEPARATE_Msk              (1UL << MPU_TYPE_SEPARATE_Pos)                 /*!< MPU TYPE: SEPARATE Mask */
+
+/* MPU Control Register */
+#define MPU_CTRL_PRIVDEFENA_Pos             2                                             /*!< MPU CTRL: PRIVDEFENA Position */
+#define MPU_CTRL_PRIVDEFENA_Msk            (1UL << MPU_CTRL_PRIVDEFENA_Pos)               /*!< MPU CTRL: PRIVDEFENA Mask */
+
+#define MPU_CTRL_HFNMIENA_Pos               1                                             /*!< MPU CTRL: HFNMIENA Position */
+#define MPU_CTRL_HFNMIENA_Msk              (1UL << MPU_CTRL_HFNMIENA_Pos)                 /*!< MPU CTRL: HFNMIENA Mask */
+
+#define MPU_CTRL_ENABLE_Pos                 0                                             /*!< MPU CTRL: ENABLE Position */
+#define MPU_CTRL_ENABLE_Msk                (1UL << MPU_CTRL_ENABLE_Pos)                   /*!< MPU CTRL: ENABLE Mask */
+
+/* MPU Region Number Register */
+#define MPU_RNR_REGION_Pos                  0                                             /*!< MPU RNR: REGION Position */
+#define MPU_RNR_REGION_Msk                 (0xFFUL << MPU_RNR_REGION_Pos)                 /*!< MPU RNR: REGION Mask */
+
+/* MPU Region Base Address Register */
+#define MPU_RBAR_ADDR_Pos                   5                                             /*!< MPU RBAR: ADDR Position */
+#define MPU_RBAR_ADDR_Msk                  (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos)             /*!< MPU RBAR: ADDR Mask */
+
+#define MPU_RBAR_VALID_Pos                  4                                             /*!< MPU RBAR: VALID Position */
+#define MPU_RBAR_VALID_Msk                 (1UL << MPU_RBAR_VALID_Pos)                    /*!< MPU RBAR: VALID Mask */
+
+#define MPU_RBAR_REGION_Pos                 0                                             /*!< MPU RBAR: REGION Position */
+#define MPU_RBAR_REGION_Msk                (0xFUL << MPU_RBAR_REGION_Pos)                 /*!< MPU RBAR: REGION Mask */
+
+/* MPU Region Attribute and Size Register */
+#define MPU_RASR_ATTRS_Pos                 16                                             /*!< MPU RASR: MPU Region Attribute field Position */
+#define MPU_RASR_ATTRS_Msk                 (0xFFFFUL << MPU_RASR_ATTRS_Pos)               /*!< MPU RASR: MPU Region Attribute field Mask */
+
+#define MPU_RASR_XN_Pos                    28                                             /*!< MPU RASR: ATTRS.XN Position */
+#define MPU_RASR_XN_Msk                    (1UL << MPU_RASR_XN_Pos)                       /*!< MPU RASR: ATTRS.XN Mask */
+
+#define MPU_RASR_AP_Pos                    24                                             /*!< MPU RASR: ATTRS.AP Position */
+#define MPU_RASR_AP_Msk                    (0x7UL << MPU_RASR_AP_Pos)                     /*!< MPU RASR: ATTRS.AP Mask */
+
+#define MPU_RASR_TEX_Pos                   19                                             /*!< MPU RASR: ATTRS.TEX Position */
+#define MPU_RASR_TEX_Msk                   (0x7UL << MPU_RASR_TEX_Pos)                    /*!< MPU RASR: ATTRS.TEX Mask */
+
+#define MPU_RASR_S_Pos                     18                                             /*!< MPU RASR: ATTRS.S Position */
+#define MPU_RASR_S_Msk                     (1UL << MPU_RASR_S_Pos)                        /*!< MPU RASR: ATTRS.S Mask */
+
+#define MPU_RASR_C_Pos                     17                                             /*!< MPU RASR: ATTRS.C Position */
+#define MPU_RASR_C_Msk                     (1UL << MPU_RASR_C_Pos)                        /*!< MPU RASR: ATTRS.C Mask */
+
+#define MPU_RASR_B_Pos                     16                                             /*!< MPU RASR: ATTRS.B Position */
+#define MPU_RASR_B_Msk                     (1UL << MPU_RASR_B_Pos)                        /*!< MPU RASR: ATTRS.B Mask */
+
+#define MPU_RASR_SRD_Pos                    8                                             /*!< MPU RASR: Sub-Region Disable Position */
+#define MPU_RASR_SRD_Msk                   (0xFFUL << MPU_RASR_SRD_Pos)                   /*!< MPU RASR: Sub-Region Disable Mask */
+
+#define MPU_RASR_SIZE_Pos                   1                                             /*!< MPU RASR: Region Size Field Position */
+#define MPU_RASR_SIZE_Msk                  (0x1FUL << MPU_RASR_SIZE_Pos)                  /*!< MPU RASR: Region Size Field Mask */
+
+#define MPU_RASR_ENABLE_Pos                 0                                             /*!< MPU RASR: Region enable bit Position */
+#define MPU_RASR_ENABLE_Msk                (1UL << MPU_RASR_ENABLE_Pos)                   /*!< MPU RASR: Region enable bit Disable Mask */
+
+/*@} end of group CMSIS_MPU */
+#endif
+
+
+#if (__FPU_PRESENT == 1)
+/** \ingroup  CMSIS_core_register
+    \defgroup CMSIS_FPU     Floating Point Unit (FPU)
+    \brief      Type definitions for the Floating Point Unit (FPU)
+  @{
+ */
+
+/** \brief  Structure type to access the Floating Point Unit (FPU).
+ */
+typedef struct
+{
+       uint32_t RESERVED0[1];
+  __IO uint32_t FPCCR;                   /*!< Offset: 0x004 (R/W)  Floating-Point Context Control Register               */
+  __IO uint32_t FPCAR;                   /*!< Offset: 0x008 (R/W)  Floating-Point Context Address Register               */
+  __IO uint32_t FPDSCR;                  /*!< Offset: 0x00C (R/W)  Floating-Point Default Status Control Register        */
+  __I  uint32_t MVFR0;                   /*!< Offset: 0x010 (R/ )  Media and FP Feature Register 0                       */
+  __I  uint32_t MVFR1;                   /*!< Offset: 0x014 (R/ )  Media and FP Feature Register 1                       */
+} FPU_Type;
+
+/* Floating-Point Context Control Register */
+#define FPU_FPCCR_ASPEN_Pos                31                                             /*!< FPCCR: ASPEN bit Position */
+#define FPU_FPCCR_ASPEN_Msk                (1UL << FPU_FPCCR_ASPEN_Pos)                   /*!< FPCCR: ASPEN bit Mask */
+
+#define FPU_FPCCR_LSPEN_Pos                30                                             /*!< FPCCR: LSPEN Position */
+#define FPU_FPCCR_LSPEN_Msk                (1UL << FPU_FPCCR_LSPEN_Pos)                   /*!< FPCCR: LSPEN bit Mask */
+
+#define FPU_FPCCR_MONRDY_Pos                8                                             /*!< FPCCR: MONRDY Position */
+#define FPU_FPCCR_MONRDY_Msk               (1UL << FPU_FPCCR_MONRDY_Pos)                  /*!< FPCCR: MONRDY bit Mask */
+
+#define FPU_FPCCR_BFRDY_Pos                 6                                             /*!< FPCCR: BFRDY Position */
+#define FPU_FPCCR_BFRDY_Msk                (1UL << FPU_FPCCR_BFRDY_Pos)                   /*!< FPCCR: BFRDY bit Mask */
+
+#define FPU_FPCCR_MMRDY_Pos                 5                                             /*!< FPCCR: MMRDY Position */
+#define FPU_FPCCR_MMRDY_Msk                (1UL << FPU_FPCCR_MMRDY_Pos)                   /*!< FPCCR: MMRDY bit Mask */
+
+#define FPU_FPCCR_HFRDY_Pos                 4                                             /*!< FPCCR: HFRDY Position */
+#define FPU_FPCCR_HFRDY_Msk                (1UL << FPU_FPCCR_HFRDY_Pos)                   /*!< FPCCR: HFRDY bit Mask */
+
+#define FPU_FPCCR_THREAD_Pos                3                                             /*!< FPCCR: processor mode bit Position */
+#define FPU_FPCCR_THREAD_Msk               (1UL << FPU_FPCCR_THREAD_Pos)                  /*!< FPCCR: processor mode active bit Mask */
+
+#define FPU_FPCCR_USER_Pos                  1                                             /*!< FPCCR: privilege level bit Position */
+#define FPU_FPCCR_USER_Msk                 (1UL << FPU_FPCCR_USER_Pos)                    /*!< FPCCR: privilege level bit Mask */
+
+#define FPU_FPCCR_LSPACT_Pos                0                                             /*!< FPCCR: Lazy state preservation active bit Position */
+#define FPU_FPCCR_LSPACT_Msk               (1UL << FPU_FPCCR_LSPACT_Pos)                  /*!< FPCCR: Lazy state preservation active bit Mask */
+
+/* Floating-Point Context Address Register */
+#define FPU_FPCAR_ADDRESS_Pos               3                                             /*!< FPCAR: ADDRESS bit Position */
+#define FPU_FPCAR_ADDRESS_Msk              (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos)        /*!< FPCAR: ADDRESS bit Mask */
+
+/* Floating-Point Default Status Control Register */
+#define FPU_FPDSCR_AHP_Pos                 26                                             /*!< FPDSCR: AHP bit Position */
+#define FPU_FPDSCR_AHP_Msk                 (1UL << FPU_FPDSCR_AHP_Pos)                    /*!< FPDSCR: AHP bit Mask */
+
+#define FPU_FPDSCR_DN_Pos                  25                                             /*!< FPDSCR: DN bit Position */
+#define FPU_FPDSCR_DN_Msk                  (1UL << FPU_FPDSCR_DN_Pos)                     /*!< FPDSCR: DN bit Mask */
+
+#define FPU_FPDSCR_FZ_Pos                  24                                             /*!< FPDSCR: FZ bit Position */
+#define FPU_FPDSCR_FZ_Msk                  (1UL << FPU_FPDSCR_FZ_Pos)                     /*!< FPDSCR: FZ bit Mask */
+
+#define FPU_FPDSCR_RMode_Pos               22                                             /*!< FPDSCR: RMode bit Position */
+#define FPU_FPDSCR_RMode_Msk               (3UL << FPU_FPDSCR_RMode_Pos)                  /*!< FPDSCR: RMode bit Mask */
+
+/* Media and FP Feature Register 0 */
+#define FPU_MVFR0_FP_rounding_modes_Pos    28                                             /*!< MVFR0: FP rounding modes bits Position */
+#define FPU_MVFR0_FP_rounding_modes_Msk    (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos)     /*!< MVFR0: FP rounding modes bits Mask */
+
+#define FPU_MVFR0_Short_vectors_Pos        24                                             /*!< MVFR0: Short vectors bits Position */
+#define FPU_MVFR0_Short_vectors_Msk        (0xFUL << FPU_MVFR0_Short_vectors_Pos)         /*!< MVFR0: Short vectors bits Mask */
+
+#define FPU_MVFR0_Square_root_Pos          20                                             /*!< MVFR0: Square root bits Position */
+#define FPU_MVFR0_Square_root_Msk          (0xFUL << FPU_MVFR0_Square_root_Pos)           /*!< MVFR0: Square root bits Mask */
+
+#define FPU_MVFR0_Divide_Pos               16                                             /*!< MVFR0: Divide bits Position */
+#define FPU_MVFR0_Divide_Msk               (0xFUL << FPU_MVFR0_Divide_Pos)                /*!< MVFR0: Divide bits Mask */
+
+#define FPU_MVFR0_FP_excep_trapping_Pos    12                                             /*!< MVFR0: FP exception trapping bits Position */
+#define FPU_MVFR0_FP_excep_trapping_Msk    (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos)     /*!< MVFR0: FP exception trapping bits Mask */
+
+#define FPU_MVFR0_Double_precision_Pos      8                                             /*!< MVFR0: Double-precision bits Position */
+#define FPU_MVFR0_Double_precision_Msk     (0xFUL << FPU_MVFR0_Double_precision_Pos)      /*!< MVFR0: Double-precision bits Mask */
+
+#define FPU_MVFR0_Single_precision_Pos      4                                             /*!< MVFR0: Single-precision bits Position */
+#define FPU_MVFR0_Single_precision_Msk     (0xFUL << FPU_MVFR0_Single_precision_Pos)      /*!< MVFR0: Single-precision bits Mask */
+
+#define FPU_MVFR0_A_SIMD_registers_Pos      0                                             /*!< MVFR0: A_SIMD registers bits Position */
+#define FPU_MVFR0_A_SIMD_registers_Msk     (0xFUL << FPU_MVFR0_A_SIMD_registers_Pos)      /*!< MVFR0: A_SIMD registers bits Mask */
+
+/* Media and FP Feature Register 1 */
+#define FPU_MVFR1_FP_fused_MAC_Pos         28                                             /*!< MVFR1: FP fused MAC bits Position */
+#define FPU_MVFR1_FP_fused_MAC_Msk         (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos)          /*!< MVFR1: FP fused MAC bits Mask */
+
+#define FPU_MVFR1_FP_HPFP_Pos              24                                             /*!< MVFR1: FP HPFP bits Position */
+#define FPU_MVFR1_FP_HPFP_Msk              (0xFUL << FPU_MVFR1_FP_HPFP_Pos)               /*!< MVFR1: FP HPFP bits Mask */
+
+#define FPU_MVFR1_D_NaN_mode_Pos            4                                             /*!< MVFR1: D_NaN mode bits Position */
+#define FPU_MVFR1_D_NaN_mode_Msk           (0xFUL << FPU_MVFR1_D_NaN_mode_Pos)            /*!< MVFR1: D_NaN mode bits Mask */
+
+#define FPU_MVFR1_FtZ_mode_Pos              0                                             /*!< MVFR1: FtZ mode bits Position */
+#define FPU_MVFR1_FtZ_mode_Msk             (0xFUL << FPU_MVFR1_FtZ_mode_Pos)              /*!< MVFR1: FtZ mode bits Mask */
+
+/*@} end of group CMSIS_FPU */
+#endif
+
+
+/** \ingroup  CMSIS_core_register
+    \defgroup CMSIS_CoreDebug       Core Debug Registers (CoreDebug)
+    \brief      Type definitions for the Core Debug Registers
+  @{
+ */
+
+/** \brief  Structure type to access the Core Debug Register (CoreDebug).
+ */
+typedef struct
+{
+  __IO uint32_t DHCSR;                   /*!< Offset: 0x000 (R/W)  Debug Halting Control and Status Register    */
+  __O  uint32_t DCRSR;                   /*!< Offset: 0x004 ( /W)  Debug Core Register Selector Register        */
+  __IO uint32_t DCRDR;                   /*!< Offset: 0x008 (R/W)  Debug Core Register Data Register            */
+  __IO uint32_t DEMCR;                   /*!< Offset: 0x00C (R/W)  Debug Exception and Monitor Control Register */
+} CoreDebug_Type;
+
+/* Debug Halting Control and Status Register */
+#define CoreDebug_DHCSR_DBGKEY_Pos         16                                             /*!< CoreDebug DHCSR: DBGKEY Position */
+#define CoreDebug_DHCSR_DBGKEY_Msk         (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos)       /*!< CoreDebug DHCSR: DBGKEY Mask */
+
+#define CoreDebug_DHCSR_S_RESET_ST_Pos     25                                             /*!< CoreDebug DHCSR: S_RESET_ST Position */
+#define CoreDebug_DHCSR_S_RESET_ST_Msk     (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos)        /*!< CoreDebug DHCSR: S_RESET_ST Mask */
+
+#define CoreDebug_DHCSR_S_RETIRE_ST_Pos    24                                             /*!< CoreDebug DHCSR: S_RETIRE_ST Position */
+#define CoreDebug_DHCSR_S_RETIRE_ST_Msk    (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos)       /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */
+
+#define CoreDebug_DHCSR_S_LOCKUP_Pos       19                                             /*!< CoreDebug DHCSR: S_LOCKUP Position */
+#define CoreDebug_DHCSR_S_LOCKUP_Msk       (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos)          /*!< CoreDebug DHCSR: S_LOCKUP Mask */
+
+#define CoreDebug_DHCSR_S_SLEEP_Pos        18                                             /*!< CoreDebug DHCSR: S_SLEEP Position */
+#define CoreDebug_DHCSR_S_SLEEP_Msk        (1UL << CoreDebug_DHCSR_S_SLEEP_Pos)           /*!< CoreDebug DHCSR: S_SLEEP Mask */
+
+#define CoreDebug_DHCSR_S_HALT_Pos         17                                             /*!< CoreDebug DHCSR: S_HALT Position */
+#define CoreDebug_DHCSR_S_HALT_Msk         (1UL << CoreDebug_DHCSR_S_HALT_Pos)            /*!< CoreDebug DHCSR: S_HALT Mask */
+
+#define CoreDebug_DHCSR_S_REGRDY_Pos       16                                             /*!< CoreDebug DHCSR: S_REGRDY Position */
+#define CoreDebug_DHCSR_S_REGRDY_Msk       (1UL << CoreDebug_DHCSR_S_REGRDY_Pos)          /*!< CoreDebug DHCSR: S_REGRDY Mask */
+
+#define CoreDebug_DHCSR_C_SNAPSTALL_Pos     5                                             /*!< CoreDebug DHCSR: C_SNAPSTALL Position */
+#define CoreDebug_DHCSR_C_SNAPSTALL_Msk    (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos)       /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */
+
+#define CoreDebug_DHCSR_C_MASKINTS_Pos      3                                             /*!< CoreDebug DHCSR: C_MASKINTS Position */
+#define CoreDebug_DHCSR_C_MASKINTS_Msk     (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos)        /*!< CoreDebug DHCSR: C_MASKINTS Mask */
+
+#define CoreDebug_DHCSR_C_STEP_Pos          2                                             /*!< CoreDebug DHCSR: C_STEP Position */
+#define CoreDebug_DHCSR_C_STEP_Msk         (1UL << CoreDebug_DHCSR_C_STEP_Pos)            /*!< CoreDebug DHCSR: C_STEP Mask */
+
+#define CoreDebug_DHCSR_C_HALT_Pos          1                                             /*!< CoreDebug DHCSR: C_HALT Position */
+#define CoreDebug_DHCSR_C_HALT_Msk         (1UL << CoreDebug_DHCSR_C_HALT_Pos)            /*!< CoreDebug DHCSR: C_HALT Mask */
+
+#define CoreDebug_DHCSR_C_DEBUGEN_Pos       0                                             /*!< CoreDebug DHCSR: C_DEBUGEN Position */
+#define CoreDebug_DHCSR_C_DEBUGEN_Msk      (1UL << CoreDebug_DHCSR_C_DEBUGEN_Pos)         /*!< CoreDebug DHCSR: C_DEBUGEN Mask */
+
+/* Debug Core Register Selector Register */
+#define CoreDebug_DCRSR_REGWnR_Pos         16                                             /*!< CoreDebug DCRSR: REGWnR Position */
+#define CoreDebug_DCRSR_REGWnR_Msk         (1UL << CoreDebug_DCRSR_REGWnR_Pos)            /*!< CoreDebug DCRSR: REGWnR Mask */
+
+#define CoreDebug_DCRSR_REGSEL_Pos          0                                             /*!< CoreDebug DCRSR: REGSEL Position */
+#define CoreDebug_DCRSR_REGSEL_Msk         (0x1FUL << CoreDebug_DCRSR_REGSEL_Pos)         /*!< CoreDebug DCRSR: REGSEL Mask */
+
+/* Debug Exception and Monitor Control Register */
+#define CoreDebug_DEMCR_TRCENA_Pos         24                                             /*!< CoreDebug DEMCR: TRCENA Position */
+#define CoreDebug_DEMCR_TRCENA_Msk         (1UL << CoreDebug_DEMCR_TRCENA_Pos)            /*!< CoreDebug DEMCR: TRCENA Mask */
+
+#define CoreDebug_DEMCR_MON_REQ_Pos        19                                             /*!< CoreDebug DEMCR: MON_REQ Position */
+#define CoreDebug_DEMCR_MON_REQ_Msk        (1UL << CoreDebug_DEMCR_MON_REQ_Pos)           /*!< CoreDebug DEMCR: MON_REQ Mask */
+
+#define CoreDebug_DEMCR_MON_STEP_Pos       18                                             /*!< CoreDebug DEMCR: MON_STEP Position */
+#define CoreDebug_DEMCR_MON_STEP_Msk       (1UL << CoreDebug_DEMCR_MON_STEP_Pos)          /*!< CoreDebug DEMCR: MON_STEP Mask */
+
+#define CoreDebug_DEMCR_MON_PEND_Pos       17                                             /*!< CoreDebug DEMCR: MON_PEND Position */
+#define CoreDebug_DEMCR_MON_PEND_Msk       (1UL << CoreDebug_DEMCR_MON_PEND_Pos)          /*!< CoreDebug DEMCR: MON_PEND Mask */
+
+#define CoreDebug_DEMCR_MON_EN_Pos         16                                             /*!< CoreDebug DEMCR: MON_EN Position */
+#define CoreDebug_DEMCR_MON_EN_Msk         (1UL << CoreDebug_DEMCR_MON_EN_Pos)            /*!< CoreDebug DEMCR: MON_EN Mask */
+
+#define CoreDebug_DEMCR_VC_HARDERR_Pos     10                                             /*!< CoreDebug DEMCR: VC_HARDERR Position */
+#define CoreDebug_DEMCR_VC_HARDERR_Msk     (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos)        /*!< CoreDebug DEMCR: VC_HARDERR Mask */
+
+#define CoreDebug_DEMCR_VC_INTERR_Pos       9                                             /*!< CoreDebug DEMCR: VC_INTERR Position */
+#define CoreDebug_DEMCR_VC_INTERR_Msk      (1UL << CoreDebug_DEMCR_VC_INTERR_Pos)         /*!< CoreDebug DEMCR: VC_INTERR Mask */
+
+#define CoreDebug_DEMCR_VC_BUSERR_Pos       8                                             /*!< CoreDebug DEMCR: VC_BUSERR Position */
+#define CoreDebug_DEMCR_VC_BUSERR_Msk      (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos)         /*!< CoreDebug DEMCR: VC_BUSERR Mask */
+
+#define CoreDebug_DEMCR_VC_STATERR_Pos      7                                             /*!< CoreDebug DEMCR: VC_STATERR Position */
+#define CoreDebug_DEMCR_VC_STATERR_Msk     (1UL << CoreDebug_DEMCR_VC_STATERR_Pos)        /*!< CoreDebug DEMCR: VC_STATERR Mask */
+
+#define CoreDebug_DEMCR_VC_CHKERR_Pos       6                                             /*!< CoreDebug DEMCR: VC_CHKERR Position */
+#define CoreDebug_DEMCR_VC_CHKERR_Msk      (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos)         /*!< CoreDebug DEMCR: VC_CHKERR Mask */
+
+#define CoreDebug_DEMCR_VC_NOCPERR_Pos      5                                             /*!< CoreDebug DEMCR: VC_NOCPERR Position */
+#define CoreDebug_DEMCR_VC_NOCPERR_Msk     (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos)        /*!< CoreDebug DEMCR: VC_NOCPERR Mask */
+
+#define CoreDebug_DEMCR_VC_MMERR_Pos        4                                             /*!< CoreDebug DEMCR: VC_MMERR Position */
+#define CoreDebug_DEMCR_VC_MMERR_Msk       (1UL << CoreDebug_DEMCR_VC_MMERR_Pos)          /*!< CoreDebug DEMCR: VC_MMERR Mask */
+
+#define CoreDebug_DEMCR_VC_CORERESET_Pos    0                                             /*!< CoreDebug DEMCR: VC_CORERESET Position */
+#define CoreDebug_DEMCR_VC_CORERESET_Msk   (1UL << CoreDebug_DEMCR_VC_CORERESET_Pos)      /*!< CoreDebug DEMCR: VC_CORERESET Mask */
+
+/*@} end of group CMSIS_CoreDebug */
+
+
+/** \ingroup    CMSIS_core_register
+    \defgroup   CMSIS_core_base     Core Definitions
+    \brief      Definitions for base addresses, unions, and structures.
+  @{
+ */
+
+/* Memory mapping of Cortex-M4 Hardware */
+#define SCS_BASE            (0xE000E000UL)                            /*!< System Control Space Base Address  */
+#define ITM_BASE            (0xE0000000UL)                            /*!< ITM Base Address                   */
+#define DWT_BASE            (0xE0001000UL)                            /*!< DWT Base Address                   */
+#define TPI_BASE            (0xE0040000UL)                            /*!< TPI Base Address                   */
+#define CoreDebug_BASE      (0xE000EDF0UL)                            /*!< Core Debug Base Address            */
+#define SysTick_BASE        (SCS_BASE +  0x0010UL)                    /*!< SysTick Base Address               */
+#define NVIC_BASE           (SCS_BASE +  0x0100UL)                    /*!< NVIC Base Address                  */
+#define SCB_BASE            (SCS_BASE +  0x0D00UL)                    /*!< System Control Block Base Address  */
+
+#define SCnSCB              ((SCnSCB_Type    *)     SCS_BASE      )   /*!< System control Register not in SCB */
+#define SCB                 ((SCB_Type       *)     SCB_BASE      )   /*!< SCB configuration struct           */
+#define SysTick             ((SysTick_Type   *)     SysTick_BASE  )   /*!< SysTick configuration struct       */
+#define NVIC                ((NVIC_Type      *)     NVIC_BASE     )   /*!< NVIC configuration struct          */
+#define ITM                 ((ITM_Type       *)     ITM_BASE      )   /*!< ITM configuration struct           */
+#define DWT                 ((DWT_Type       *)     DWT_BASE      )   /*!< DWT configuration struct           */
+#define TPI                 ((TPI_Type       *)     TPI_BASE      )   /*!< TPI configuration struct           */
+#define CoreDebug           ((CoreDebug_Type *)     CoreDebug_BASE)   /*!< Core Debug configuration struct    */
+
+#if (__MPU_PRESENT == 1)
+  #define MPU_BASE          (SCS_BASE +  0x0D90UL)                    /*!< Memory Protection Unit             */
+  #define MPU               ((MPU_Type       *)     MPU_BASE      )   /*!< Memory Protection Unit             */
+#endif
+
+#if (__FPU_PRESENT == 1)
+  #define FPU_BASE          (SCS_BASE +  0x0F30UL)                    /*!< Floating Point Unit                */
+  #define FPU               ((FPU_Type       *)     FPU_BASE      )   /*!< Floating Point Unit                */
+#endif
+
+/*@} */
+
+
+
+/*******************************************************************************
+ *                Hardware Abstraction Layer
+  Core Function Interface contains:
+  - Core NVIC Functions
+  - Core SysTick Functions
+  - Core Debug Functions
+  - Core Register Access Functions
+ ******************************************************************************/
+/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ##########################   NVIC functions  #################################### */
+/** \ingroup  CMSIS_Core_FunctionInterface
+    \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+    \brief      Functions that manage interrupts and exceptions via the NVIC.
+    @{
+ */
+
+/** \brief  Set Priority Grouping
+
+  The function sets the priority grouping field using the required unlock sequence.
+  The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
+  Only values from 0..7 are used.
+  In case of a conflict between priority grouping and available
+  priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+
+    \param [in]      PriorityGroup  Priority grouping field.
+ */
+__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
+{
+  uint32_t reg_value;
+  uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07);               /* only values 0..7 are used          */
+
+  reg_value  =  SCB->AIRCR;                                                   /* read old register configuration    */
+  reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk);             /* clear bits to change               */
+  reg_value  =  (reg_value                                 |
+                ((uint32_t)0x5FA << SCB_AIRCR_VECTKEY_Pos) |
+                (PriorityGroupTmp << 8));                                     /* Insert write key and priorty group */
+  SCB->AIRCR =  reg_value;
+}
+
+
+/** \brief  Get Priority Grouping
+
+  The function reads the priority grouping field from the NVIC Interrupt Controller.
+
+    \return                Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
+ */
+__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void)
+{
+  return ((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos);   /* read priority grouping field */
+}
+
+
+/** \brief  Enable External Interrupt
+
+    The function enables a device-specific interrupt in the NVIC interrupt controller.
+
+    \param [in]      IRQn  External interrupt number. Value cannot be negative.
+ */
+__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+/*  NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F));  enable interrupt */
+  NVIC->ISER[(uint32_t)((int32_t)IRQn) >> 5] = (uint32_t)(1 << ((uint32_t)((int32_t)IRQn) & (uint32_t)0x1F)); /* enable interrupt */
+}
+
+
+/** \brief  Disable External Interrupt
+
+    The function disables a device-specific interrupt in the NVIC interrupt controller.
+
+    \param [in]      IRQn  External interrupt number. Value cannot be negative.
+ */
+__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+  NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */
+}
+
+
+/** \brief  Get Pending Interrupt
+
+    The function reads the pending register in the NVIC and returns the pending bit
+    for the specified interrupt.
+
+    \param [in]      IRQn  Interrupt number.
+
+    \return             0  Interrupt status is not pending.
+    \return             1  Interrupt status is pending.
+ */
+__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+  return((uint32_t) ((NVIC->ISPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if pending else 0 */
+}
+
+
+/** \brief  Set Pending Interrupt
+
+    The function sets the pending bit of an external interrupt.
+
+    \param [in]      IRQn  Interrupt number. Value cannot be negative.
+ */
+__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+  NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */
+}
+
+
+/** \brief  Clear Pending Interrupt
+
+    The function clears the pending bit of an external interrupt.
+
+    \param [in]      IRQn  External interrupt number. Value cannot be negative.
+ */
+__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+  NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */
+}
+
+
+/** \brief  Get Active Interrupt
+
+    The function reads the active register in NVIC and returns the active bit.
+
+    \param [in]      IRQn  Interrupt number.
+
+    \return             0  Interrupt status is not active.
+    \return             1  Interrupt status is active.
+ */
+__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn)
+{
+  return((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if active else 0 */
+}
+
+
+/** \brief  Set Interrupt Priority
+
+    The function sets the priority of an interrupt.
+
+    \note The priority cannot be set for every core interrupt.
+
+    \param [in]      IRQn  Interrupt number.
+    \param [in]  priority  Priority to set.
+ */
+__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+  if(IRQn < 0) {
+    SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M  System Interrupts */
+  else {
+    NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff);    }        /* set Priority for device specific Interrupts  */
+}
+
+
+/** \brief  Get Interrupt Priority
+
+    The function reads the priority of an interrupt. The interrupt
+    number can be positive to specify an external (device specific)
+    interrupt, or negative to specify an internal (core) interrupt.
+
+
+    \param [in]   IRQn  Interrupt number.
+    \return             Interrupt Priority. Value is aligned automatically to the implemented
+                        priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+  if(IRQn < 0) {
+    return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS)));  } /* get priority for Cortex-M  system interrupts */
+  else {
+    return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)]           >> (8 - __NVIC_PRIO_BITS)));  } /* get priority for device specific interrupts  */
+}
+
+
+/** \brief  Encode Priority
+
+    The function encodes the priority for an interrupt with the given priority group,
+    preemptive priority value, and subpriority value.
+    In case of a conflict between priority grouping and available
+    priority bits (__NVIC_PRIO_BITS), the samllest possible priority group is set.
+
+    \param [in]     PriorityGroup  Used priority group.
+    \param [in]   PreemptPriority  Preemptive priority value (starting from 0).
+    \param [in]       SubPriority  Subpriority value (starting from 0).
+    \return                        Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+  uint32_t PriorityGroupTmp = (PriorityGroup & 0x07);          /* only values 0..7 are used          */
+  uint32_t PreemptPriorityBits;
+  uint32_t SubPriorityBits;
+
+  PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp;
+  SubPriorityBits     = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS;
+
+  return (
+           ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) |
+           ((SubPriority     & ((1 << (SubPriorityBits    )) - 1)))
+         );
+}
+
+
+/** \brief  Decode Priority
+
+    The function decodes an interrupt priority value with a given priority group to
+    preemptive priority value and subpriority value.
+    In case of a conflict between priority grouping and available
+    priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set.
+
+    \param [in]         Priority   Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+    \param [in]     PriorityGroup  Used priority group.
+    \param [out] pPreemptPriority  Preemptive priority value (starting from 0).
+    \param [out]     pSubPriority  Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority)
+{
+  uint32_t PriorityGroupTmp = (PriorityGroup & 0x07);          /* only values 0..7 are used          */
+  uint32_t PreemptPriorityBits;
+  uint32_t SubPriorityBits;
+
+  PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp;
+  SubPriorityBits     = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS;
+
+  *pPreemptPriority = (Priority >> SubPriorityBits) & ((1 << (PreemptPriorityBits)) - 1);
+  *pSubPriority     = (Priority                   ) & ((1 << (SubPriorityBits    )) - 1);
+}
+
+
+/** \brief  System Reset
+
+    The function initiates a system reset request to reset the MCU.
+ */
+__STATIC_INLINE void NVIC_SystemReset(void)
+{
+  __DSB();                                                     /* Ensure all outstanding memory accesses included
+                                                                  buffered write are completed before reset */
+  SCB->AIRCR  = ((0x5FA << SCB_AIRCR_VECTKEY_Pos)      |
+                 (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
+                 SCB_AIRCR_SYSRESETREQ_Msk);                   /* Keep priority group unchanged */
+  __DSB();                                                     /* Ensure completion of memory access */
+  while(1);                                                    /* wait until reset */
+}
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+
+
+/* ##################################    SysTick function  ############################################ */
+/** \ingroup  CMSIS_Core_FunctionInterface
+    \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+    \brief      Functions that configure the System.
+  @{
+ */
+
+#if (__Vendor_SysTickConfig == 0)
+
+/** \brief  System Tick Configuration
+
+    The function initializes the System Timer and its interrupt, and starts the System Tick Timer.
+    Counter is in free running mode to generate periodic interrupts.
+
+    \param [in]  ticks  Number of ticks between two interrupts.
+
+    \return          0  Function succeeded.
+    \return          1  Function failed.
+
+    \note     When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
+    function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
+    must contain a vendor-specific implementation of this function.
+
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */
+
+  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */
+  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Systick Interrupt */
+  SysTick->VAL   = 0;                                          /* Load the SysTick Counter Value */
+  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
+                   SysTick_CTRL_TICKINT_Msk   |
+                   SysTick_CTRL_ENABLE_Msk;                    /* Enable SysTick IRQ and SysTick Timer */
+  return (0);                                                  /* Function successful */
+}
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+/* ##################################### Debug In/Output function ########################################### */
+/** \ingroup  CMSIS_Core_FunctionInterface
+    \defgroup CMSIS_core_DebugFunctions ITM Functions
+    \brief   Functions that access the ITM debug interface.
+  @{
+ */
+
+extern volatile int32_t ITM_RxBuffer;                    /*!< External variable to receive characters.                         */
+#define                 ITM_RXBUFFER_EMPTY    0x5AA55AA5 /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
+
+
+/** \brief  ITM Send Character
+
+    The function transmits a character via the ITM channel 0, and
+    \li Just returns when no debugger is connected that has booked the output.
+    \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted.
+
+    \param [in]     ch  Character to transmit.
+
+    \returns            Character to transmit.
+ */
+__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch)
+{
+  if ((ITM->TCR & ITM_TCR_ITMENA_Msk)                  &&      /* ITM enabled */
+      (ITM->TER & (1UL << 0)        )                    )     /* ITM Port #0 enabled */
+  {
+    while (ITM->PORT[0].u32 == 0);
+    ITM->PORT[0].u8 = (uint8_t) ch;
+  }
+  return (ch);
+}
+
+
+/** \brief  ITM Receive Character
+
+    The function inputs a character via the external variable \ref ITM_RxBuffer.
+
+    \return             Received character.
+    \return         -1  No character pending.
+ */
+__STATIC_INLINE int32_t ITM_ReceiveChar (void) {
+  int32_t ch = -1;                           /* no character available */
+
+  if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) {
+    ch = ITM_RxBuffer;
+    ITM_RxBuffer = ITM_RXBUFFER_EMPTY;       /* ready for next character */
+  }
+
+  return (ch);
+}
+
+
+/** \brief  ITM Check Character
+
+    The function checks whether a character is pending for reading in the variable \ref ITM_RxBuffer.
+
+    \return          0  No character available.
+    \return          1  Character available.
+ */
+__STATIC_INLINE int32_t ITM_CheckChar (void) {
+
+  if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) {
+    return (0);                                 /* no character available */
+  } else {
+    return (1);                                 /*    character available */
+  }
+}
+
+/*@} end of CMSIS_core_DebugFunctions */
+
+#endif /* __CORE_CM4_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/teensy3/core_cm4_simd.h b/teensy3/core_cm4_simd.h
new file mode 100644
index 0000000000000000000000000000000000000000..66c99397d7d687742eca43fbbfc08c6eb87ef0ad
--- /dev/null
+++ b/teensy3/core_cm4_simd.h
@@ -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
diff --git a/teensy3/core_cmInstr.h b/teensy3/core_cmInstr.h
new file mode 100644
index 0000000000000000000000000000000000000000..971ae7e9bdb01efb284987c05a813e8a8ce72c9b
--- /dev/null
+++ b/teensy3/core_cmInstr.h
@@ -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 */
diff --git a/teensy3/core_id.h b/teensy3/core_id.h
new file mode 100644
index 0000000000000000000000000000000000000000..a64f940f735f0edb466f137ed321cbc6878d7145
--- /dev/null
+++ b/teensy3/core_id.h
@@ -0,0 +1,3 @@
+#ifndef CORE_TEENSY
+#define CORE_TEENSY
+#endif
diff --git a/teensy3/core_pins.h b/teensy3/core_pins.h
new file mode 100644
index 0000000000000000000000000000000000000000..8c2240fc1005b45df4df9c3094da4567dd9ef735
--- /dev/null
+++ b/teensy3/core_pins.h
@@ -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
diff --git a/teensy3/eeprom.c b/teensy3/eeprom.c
new file mode 100644
index 0000000000000000000000000000000000000000..848c7a4bb4eaa9ca6a9f34cf597e4dff59e8648d
--- /dev/null
+++ b/teensy3/eeprom.c
@@ -0,0 +1,226 @@
+/* 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;
+	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;
+	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;
+	return *(uint32_t *)(&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 (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;
+#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;
+#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 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
+*/
+
diff --git a/teensy3/elapsedMillis.h b/teensy3/elapsedMillis.h
new file mode 100644
index 0000000000000000000000000000000000000000..a014f5040a1ddf2eac567ddbb628476bb16071ba
--- /dev/null
+++ b/teensy3/elapsedMillis.h
@@ -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
diff --git a/teensy3/keylayouts.c b/teensy3/keylayouts.c
new file mode 100644
index 0000000000000000000000000000000000000000..4bf543a4abbb21df9dfdc29ba39689b03c420a0e
--- /dev/null
+++ b/teensy3/keylayouts.c
@@ -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
+
diff --git a/teensy3/keylayouts.h b/teensy3/keylayouts.h
new file mode 100644
index 0000000000000000000000000000000000000000..0956bf6eaf190de9096d36cf55107636949976ed
--- /dev/null
+++ b/teensy3/keylayouts.h
@@ -0,0 +1,5173 @@
+/* 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 KEYLAYOUTS_H__
+#define KEYLAYOUTS_H__
+
+#include <stdint.h>
+#include <avr/pgmspace.h>
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+//#define LAYOUT_US_ENGLISH
+//#define LAYOUT_CANADIAN_FRENCH
+//#define LAYOUT_CANADIAN_MULTILINGUAL
+//#define LAYOUT_DANISH
+//#define LAYOUT_FINNISH
+//#define LAYOUT_FRENCH
+//#define LAYOUT_FRENCH_BELGIAN
+//#define LAYOUT_FRENCH_SWISS
+//#define LAYOUT_GERMAN
+//#define LAYOUT_GERMAN_MAC
+//#define LAYOUT_GERMAN_SWISS
+//#define LAYOUT_ICELANDIC
+//#define LAYOUT_IRISH
+//#define LAYOUT_ITALIAN
+//#define LAYOUT_NORWEGIAN
+//#define LAYOUT_PORTUGUESE
+//#define LAYOUT_PORTUGUESE_BRAZILIAN
+//#define LAYOUT_SPANISH
+//#define LAYOUT_SPANISH_LATIN_AMERICA
+//#define LAYOUT_SWEDISH
+//#define LAYOUT_TURKISH
+//#define LAYOUT_UNITED_KINGDOM	
+//#define LAYOUT_US_INTERNATIONAL
+
+
+
+// http://en.wikipedia.org/wiki/Keyboard_layout
+
+
+#define MODIFIERKEY_CTRL        ( 0x01 | 0x8000 )
+#define MODIFIERKEY_SHIFT       ( 0x02 | 0x8000 )
+#define MODIFIERKEY_ALT         ( 0x04 | 0x8000 )
+#define MODIFIERKEY_GUI         ( 0x08 | 0x8000 )
+#define MODIFIERKEY_LEFT_CTRL   ( 0x01 | 0x8000 )
+#define MODIFIERKEY_LEFT_SHIFT  ( 0x02 | 0x8000 )
+#define MODIFIERKEY_LEFT_ALT    ( 0x04 | 0x8000 )
+#define MODIFIERKEY_LEFT_GUI    ( 0x08 | 0x8000 )
+#define MODIFIERKEY_RIGHT_CTRL  ( 0x10 | 0x8000 )
+#define MODIFIERKEY_RIGHT_SHIFT ( 0x20 | 0x8000 )
+#define MODIFIERKEY_RIGHT_ALT   ( 0x40 | 0x8000 )
+#define MODIFIERKEY_RIGHT_GUI   ( 0x80 | 0x8000 )
+
+#define KEY_MEDIA_VOLUME_INC    0x01
+#define KEY_MEDIA_VOLUME_DEC    0x02
+#define KEY_MEDIA_MUTE          0x04
+#define KEY_MEDIA_PLAY_PAUSE    0x08
+#define KEY_MEDIA_NEXT_TRACK    0x10
+#define KEY_MEDIA_PREV_TRACK    0x20
+#define KEY_MEDIA_STOP          0x40
+#define KEY_MEDIA_EJECT         0x80
+
+#define KEY_A           ( 4   | 0x4000 )
+#define KEY_B           ( 5   | 0x4000 )
+#define KEY_C           ( 6   | 0x4000 )
+#define KEY_D           ( 7   | 0x4000 )
+#define KEY_E           ( 8   | 0x4000 )
+#define KEY_F           ( 9   | 0x4000 )
+#define KEY_G           ( 10  | 0x4000 )
+#define KEY_H           ( 11  | 0x4000 )
+#define KEY_I           ( 12  | 0x4000 )
+#define KEY_J           ( 13  | 0x4000 )
+#define KEY_K           ( 14  | 0x4000 )
+#define KEY_L           ( 15  | 0x4000 )
+#define KEY_M           ( 16  | 0x4000 )
+#define KEY_N           ( 17  | 0x4000 )
+#define KEY_O           ( 18  | 0x4000 )
+#define KEY_P           ( 19  | 0x4000 )
+#define KEY_Q           ( 20  | 0x4000 )
+#define KEY_R           ( 21  | 0x4000 )
+#define KEY_S           ( 22  | 0x4000 )
+#define KEY_T           ( 23  | 0x4000 )
+#define KEY_U           ( 24  | 0x4000 )
+#define KEY_V           ( 25  | 0x4000 )
+#define KEY_W           ( 26  | 0x4000 )
+#define KEY_X           ( 27  | 0x4000 )
+#define KEY_Y           ( 28  | 0x4000 )
+#define KEY_Z           ( 29  | 0x4000 )
+#define KEY_1           ( 30  | 0x4000 )
+#define KEY_2           ( 31  | 0x4000 )
+#define KEY_3           ( 32  | 0x4000 )
+#define KEY_4           ( 33  | 0x4000 )
+#define KEY_5           ( 34  | 0x4000 )
+#define KEY_6           ( 35  | 0x4000 )
+#define KEY_7           ( 36  | 0x4000 )
+#define KEY_8           ( 37  | 0x4000 )
+#define KEY_9           ( 38  | 0x4000 )
+#define KEY_0           ( 39  | 0x4000 )
+#define KEY_ENTER       ( 40  | 0x4000 )
+#define KEY_ESC         ( 41  | 0x4000 )
+#define KEY_BACKSPACE   ( 42  | 0x4000 )
+#define KEY_TAB         ( 43  | 0x4000 )
+#define KEY_SPACE       ( 44  | 0x4000 )
+#define KEY_MINUS       ( 45  | 0x4000 )
+#define KEY_EQUAL       ( 46  | 0x4000 )
+#define KEY_LEFT_BRACE  ( 47  | 0x4000 )
+#define KEY_RIGHT_BRACE ( 48  | 0x4000 )
+#define KEY_BACKSLASH   ( 49  | 0x4000 )
+#define KEY_NON_US_NUM  ( 50  | 0x4000 )
+#define KEY_SEMICOLON   ( 51  | 0x4000 )
+#define KEY_QUOTE       ( 52  | 0x4000 )
+#define KEY_TILDE       ( 53  | 0x4000 )
+#define KEY_COMMA       ( 54  | 0x4000 )
+#define KEY_PERIOD      ( 55  | 0x4000 )
+#define KEY_SLASH       ( 56  | 0x4000 )
+#define KEY_CAPS_LOCK   ( 57  | 0x4000 )
+#define KEY_F1          ( 58  | 0x4000 )
+#define KEY_F2          ( 59  | 0x4000 )
+#define KEY_F3          ( 60  | 0x4000 )
+#define KEY_F4          ( 61  | 0x4000 )
+#define KEY_F5          ( 62  | 0x4000 )
+#define KEY_F6          ( 63  | 0x4000 )
+#define KEY_F7          ( 64  | 0x4000 )
+#define KEY_F8          ( 65  | 0x4000 )
+#define KEY_F9          ( 66  | 0x4000 )
+#define KEY_F10         ( 67  | 0x4000 )
+#define KEY_F11         ( 68  | 0x4000 )
+#define KEY_F12         ( 69  | 0x4000 )
+#define KEY_PRINTSCREEN ( 70  | 0x4000 )
+#define KEY_SCROLL_LOCK ( 71  | 0x4000 )
+#define KEY_PAUSE       ( 72  | 0x4000 )
+#define KEY_INSERT      ( 73  | 0x4000 )
+#define KEY_HOME        ( 74  | 0x4000 )
+#define KEY_PAGE_UP     ( 75  | 0x4000 )
+#define KEY_DELETE      ( 76  | 0x4000 )
+#define KEY_END         ( 77  | 0x4000 )
+#define KEY_PAGE_DOWN   ( 78  | 0x4000 )
+#define KEY_RIGHT       ( 79  | 0x4000 )
+#define KEY_LEFT        ( 80  | 0x4000 )
+#define KEY_DOWN        ( 81  | 0x4000 )
+#define KEY_UP          ( 82  | 0x4000 )
+#define KEY_NUM_LOCK    ( 83  | 0x4000 )
+#define KEYPAD_SLASH    ( 84  | 0x4000 )
+#define KEYPAD_ASTERIX  ( 85  | 0x4000 )
+#define KEYPAD_MINUS    ( 86  | 0x4000 )
+#define KEYPAD_PLUS     ( 87  | 0x4000 )
+#define KEYPAD_ENTER    ( 88  | 0x4000 )
+#define KEYPAD_1        ( 89  | 0x4000 )
+#define KEYPAD_2        ( 90  | 0x4000 )
+#define KEYPAD_3        ( 91  | 0x4000 )
+#define KEYPAD_4        ( 92  | 0x4000 )
+#define KEYPAD_5        ( 93  | 0x4000 )
+#define KEYPAD_6        ( 94  | 0x4000 )
+#define KEYPAD_7        ( 95  | 0x4000 )
+#define KEYPAD_8        ( 96  | 0x4000 )
+#define KEYPAD_9        ( 97  | 0x4000 )
+#define KEYPAD_0        ( 98  | 0x4000 )
+#define KEYPAD_PERIOD   ( 99  | 0x4000 )
+#define KEY_MENU	( 101 | 0x4000 )
+#define KEY_F13         ( 104 | 0x4000 )
+#define KEY_F14         ( 105 | 0x4000 )
+#define KEY_F15         ( 106 | 0x4000 )
+#define KEY_F16         ( 107 | 0x4000 )
+#define KEY_F17         ( 108 | 0x4000 )
+#define KEY_F18         ( 109 | 0x4000 )
+#define KEY_F19         ( 110 | 0x4000 )
+#define KEY_F20         ( 111 | 0x4000 )
+#define KEY_F21         ( 112 | 0x4000 )
+#define KEY_F22         ( 113 | 0x4000 )
+#define KEY_F23         ( 114 | 0x4000 )
+#define KEY_F24         ( 115 | 0x4000 )
+
+
+// for compatibility with Leonardo's slightly different names
+#define KEY_UP_ARROW	KEY_UP
+#define KEY_DOWN_ARROW	KEY_DOWN
+#define KEY_LEFT_ARROW	KEY_LEFT
+#define KEY_RIGHT_ARROW	KEY_RIGHT
+#define KEY_RETURN	KEY_ENTER
+#define KEY_LEFT_CTRL	MODIFIERKEY_LEFT_CTRL
+#define KEY_LEFT_SHIFT	MODIFIERKEY_LEFT_SHIFT
+#define KEY_LEFT_ALT	MODIFIERKEY_LEFT_ALT
+#define KEY_LEFT_GUI	MODIFIERKEY_LEFT_GUI
+#define KEY_RIGHT_CTRL	MODIFIERKEY_RIGHT_CTRL
+#define KEY_RIGHT_SHIFT	MODIFIERKEY_RIGHT_SHIFT
+#define KEY_RIGHT_ALT	MODIFIERKEY_RIGHT_ALT
+#define KEY_RIGHT_GUI	MODIFIERKEY_RIGHT_GUI
+
+
+// Everything below this line is not intended for use in "normal" programs.
+// These private symbols populate lookup tables, which are used to translate
+// ascii and UTF8 unicode into keystroke sequences.
+
+
+#ifdef LAYOUT_US_ENGLISH
+
+#define SHIFT_MASK		0x40
+#define KEYCODE_TYPE		uint8_t
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_1 + SHIFT_MASK			// 33 !
+#define ASCII_22	KEY_QUOTE + SHIFT_MASK			// 34 "
+#define ASCII_23	KEY_3 + SHIFT_MASK			// 35 #
+#define ASCII_24	KEY_4 + SHIFT_MASK			// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_7 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_QUOTE				// 39 '  
+#define ASCII_28	KEY_9 + SHIFT_MASK			// 40 ( 
+#define ASCII_29	KEY_0 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_8 + SHIFT_MASK			// 42 *
+#define ASCII_2B	KEY_EQUAL + SHIFT_MASK			// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_MINUS				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_SLASH				// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_SEMICOLON + SHIFT_MASK		// 58 :
+#define ASCII_3B	KEY_SEMICOLON				// 59 ;
+#define ASCII_3C	KEY_COMMA + SHIFT_MASK			// 60 <
+#define ASCII_3D	KEY_EQUAL				// 61 =
+#define ASCII_3E	KEY_PERIOD + SHIFT_MASK			// 62 >
+#define ASCII_3F	KEY_SLASH + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_2 + SHIFT_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Y + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Z + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_LEFT_BRACE				// 91 [
+#define ASCII_5C	KEY_BACKSLASH				// 92 
+#define ASCII_5D	KEY_RIGHT_BRACE				// 93 ]
+#define ASCII_5E	KEY_6 + SHIFT_MASK			// 94 ^
+#define ASCII_5F	KEY_MINUS + SHIFT_MASK			// 95 _
+#define ASCII_60	KEY_TILDE				// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Y					// 121 y
+#define ASCII_7A	KEY_Z					// 122 z
+#define ASCII_7B	KEY_LEFT_BRACE + SHIFT_MASK		// 123 {
+#define ASCII_7C	KEY_BACKSLASH + SHIFT_MASK		// 124 |
+#define ASCII_7D	KEY_RIGHT_BRACE + SHIFT_MASK		// 125 }
+#define ASCII_7E	KEY_TILDE + SHIFT_MASK			// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+
+#endif // LAYOUT_US_ENGLISH
+
+
+
+
+#ifdef LAYOUT_US_INTERNATIONAL
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define DEADKEYS_MASK		0x0700
+#define	CIRCUMFLEX_BITS		0x0100
+#define ACUTE_ACCENT_BITS	0x0200
+#define GRAVE_ACCENT_BITS	0x0300
+#define TILDE_BITS		0x0400
+#define DIAERESIS_BITS		0x0500
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_CIRCUMFLEX	KEY_6 + SHIFT_MASK
+#define DEADKEY_ACUTE_ACCENT	KEY_QUOTE
+#define DEADKEY_GRAVE_ACCENT	KEY_TILDE
+#define DEADKEY_TILDE		KEY_TILDE + SHIFT_MASK
+#define DEADKEY_DIAERESIS	KEY_QUOTE + SHIFT_MASK
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_1 + SHIFT_MASK			// 33 !
+#define ASCII_22	DIAERESIS_BITS + KEY_SPACE		// 34 "
+#define ASCII_23	KEY_3 + SHIFT_MASK			// 35 #
+#define ASCII_24	KEY_4 + SHIFT_MASK			// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_7 + SHIFT_MASK			// 38 &
+#define ASCII_27	ACUTE_ACCENT_BITS + KEY_SPACE		// 39 '  
+#define ASCII_28	KEY_9 + SHIFT_MASK			// 40 ( 
+#define ASCII_29	KEY_0 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_8 + SHIFT_MASK			// 42 *
+#define ASCII_2B	KEY_EQUAL + SHIFT_MASK			// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_MINUS				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_SLASH				// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_SEMICOLON + SHIFT_MASK		// 58 :
+#define ASCII_3B	KEY_SEMICOLON				// 59 ;
+#define ASCII_3C	KEY_COMMA + SHIFT_MASK			// 60 <
+#define ASCII_3D	KEY_EQUAL				// 61 =
+#define ASCII_3E	KEY_PERIOD + SHIFT_MASK			// 62 >
+#define ASCII_3F	KEY_SLASH + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_2 + SHIFT_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Y + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Z + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_LEFT_BRACE				// 91 [
+#define ASCII_5C	KEY_BACKSLASH				// 92 
+#define ASCII_5D	KEY_RIGHT_BRACE				// 93 ]
+#define ASCII_5E	CIRCUMFLEX_BITS + KEY_SPACE		// 94 ^
+#define ASCII_5F	KEY_MINUS + SHIFT_MASK			// 95 _
+#define ASCII_60	GRAVE_ACCENT_BITS + KEY_SPACE		// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Y					// 121 y
+#define ASCII_7A	KEY_Z					// 122 z
+#define ASCII_7B	KEY_LEFT_BRACE + SHIFT_MASK		// 123 {
+#define ASCII_7C	KEY_BACKSLASH + SHIFT_MASK		// 124 |
+#define ASCII_7D	KEY_RIGHT_BRACE + SHIFT_MASK		// 125 }
+#define ASCII_7E	TILDE_BITS + KEY_SPACE			// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	KEY_1 + ALTGR_MASK			// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	KEY_C + ALTGR_MASK + SHIFT_MASK		// 162 ¢     Cent SIGN
+#define ISO_8859_1_A3	KEY_4 + ALTGR_MASK + SHIFT_MASK		// 163 £     Pound Sign
+#define ISO_8859_1_A4	KEY_4 + ALTGR_MASK			// 164 ¤     Currency or Euro Sign
+#define ISO_8859_1_A5	KEY_MINUS + ALTGR_MASK			// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	KEY_BACKSLASH + ALTGR_MASK + SHIFT_MASK	// 166 ¦     BROKEN BAR			??
+#define ISO_8859_1_A7	KEY_S + ALTGR_MASK + SHIFT_MASK		// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	KEY_QUOTE + ALTGR_MASK + SHIFT_MASK	// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	KEY_C + ALTGR_MASK			// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	0					// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	KEY_LEFT_BRACE + ALTGR_MASK		// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	KEY_BACKSLASH + ALTGR_MASK		// 172 ¬     NOT SIGN			??
+#define ISO_8859_1_AD	0					// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	KEY_R + ALTGR_MASK			// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0					// 175 ¯     MACRON
+#define ISO_8859_1_B0	KEY_SEMICOLON + ALTGR_MASK + SHIFT_MASK	// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	0					// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	KEY_2 + ALTGR_MASK			// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	KEY_3 + ALTGR_MASK			// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	KEY_QUOTE + ALTGR_MASK			// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	KEY_M + ALTGR_MASK			// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	KEY_SEMICOLON + ALTGR_MASK		// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	0					// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	KEY_1 + ALTGR_MASK + SHIFT_MASK		// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	0					// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	KEY_RIGHT_BRACE + ALTGR_MASK		// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	KEY_6 + ALTGR_MASK			// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	KEY_7 + ALTGR_MASK			// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	KEY_8 + ALTGR_MASK			// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	KEY_SLASH + ALTGR_MASK			// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 192 À     A GRAVE
+#define ISO_8859_1_C1	KEY_A + ALTGR_MASK + SHIFT_MASK		// 193 Á     A ACUTE
+#define ISO_8859_1_C2	CIRCUMFLEX_BITS	+ KEY_A + SHIFT_MASK	// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	TILDE_BITS + KEY_A + SHIFT_MASK		// 195 Ã     A TILDE
+#define ISO_8859_1_C4	KEY_Q + ALTGR_MASK + SHIFT_MASK		// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	KEY_W + ALTGR_MASK + SHIFT_MASK		// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	KEY_Z + ALTGR_MASK + SHIFT_MASK		// 198 Æ     AE
+#define ISO_8859_1_C7	KEY_COMMA + ALTGR_MASK + SHIFT_MASK	// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 200 È     E GRAVE
+#define ISO_8859_1_C9	KEY_E + ALTGR_MASK + SHIFT_MASK		// 201 É     E ACUTE
+#define ISO_8859_1_CA	CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK	// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	DIAERESIS_BITS + KEY_E + SHIFT_MASK	// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	KEY_I + ALTGR_MASK + SHIFT_MASK		// 205 Í     I ACUTE
+#define ISO_8859_1_CE	CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK	// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	DIAERESIS_BITS + KEY_I + SHIFT_MASK	// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	KEY_D + ALTGR_MASK + SHIFT_MASK		// 208 Ð     ETH
+#define ISO_8859_1_D1	KEY_N + ALTGR_MASK + SHIFT_MASK		// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	KEY_O + ALTGR_MASK + SHIFT_MASK		// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK	// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	TILDE_BITS + KEY_O + SHIFT_MASK		// 213 Õ     O TILDE
+#define ISO_8859_1_D6	KEY_P + ALTGR_MASK + SHIFT_MASK		// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	KEY_EQUAL + ALTGR_MASK			// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	KEY_L + ALTGR_MASK + SHIFT_MASK		// 216 Ø     O STROKE
+#define ISO_8859_1_D9	GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	KEY_U + ALTGR_MASK + SHIFT_MASK		// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK	// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	KEY_Y + ALTGR_MASK + SHIFT_MASK		// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK	// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	KEY_T + ALTGR_MASK + SHIFT_MASK		// 222 Þ     THORN
+#define ISO_8859_1_DF	KEY_S + ALTGR_MASK			// 223 ß     SHARP S
+#define ISO_8859_1_E0	GRAVE_ACCENT_BITS + KEY_A		// 224 à     a GRAVE
+#define ISO_8859_1_E1	KEY_A + ALTGR_MASK			// 225 á     a ACUTE
+#define ISO_8859_1_E2	CIRCUMFLEX_BITS + KEY_A			// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	TILDE_BITS + KEY_A			// 227 ã     a TILDE
+#define ISO_8859_1_E4	DIAERESIS_BITS + KEY_A			// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	KEY_W + ALTGR_MASK			// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	KEY_Z + ALTGR_MASK			// 230 æ     ae
+#define ISO_8859_1_E7	KEY_COMMA + ALTGR_MASK			// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	GRAVE_ACCENT_BITS + KEY_E		// 232 è     e GRAVE
+#define ISO_8859_1_E9	ACUTE_ACCENT_BITS + KEY_E		// 233 é     e ACUTE
+#define ISO_8859_1_EA	CIRCUMFLEX_BITS + KEY_E			// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	DIAERESIS_BITS + KEY_E			// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	KEY_I + ALTGR_MASK			// 237 í     i ACUTE
+#define ISO_8859_1_EE	CIRCUMFLEX_BITS + KEY_I			// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	DIAERESIS_BITS + KEY_I			// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	KEY_D + ALTGR_MASK			// 240 ð     ETH
+#define ISO_8859_1_F1	KEY_N + ALTGR_MASK			// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	KEY_O + ALTGR_MASK			// 243 ó     o ACUTE
+#define ISO_8859_1_F4	CIRCUMFLEX_BITS + KEY_O			// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	TILDE_BITS + KEY_O 			// 245 õ     o TILDE
+#define ISO_8859_1_F6	KEY_P + ALTGR_MASK			// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	KEY_EQUAL + ALTGR_MASK + SHIFT_MASK	// 247 ÷     DIVISION
+#define ISO_8859_1_F8	KEY_L + ALTGR_MASK			// 248 ø     o STROKE
+#define ISO_8859_1_F9	GRAVE_ACCENT_BITS + KEY_U		// 249 ù     u GRAVE
+#define ISO_8859_1_FA	KEY_U + ALTGR_MASK			// 250 ú     u ACUTE
+#define ISO_8859_1_FB	CIRCUMFLEX_BITS + KEY_U			// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	KEY_Y + ALTGR_MASK			// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	ACUTE_ACCENT_BITS + KEY_Y		// 253 ý     y ACUTE
+#define ISO_8859_1_FE	KEY_T + ALTGR_MASK			// 254 þ     THORN
+#define ISO_8859_1_FF	DIAERESIS_BITS + KEY_Y			// 255 ÿ     y DIAERESIS
+#define UNICODE_20AC	KEY_5 + ALTGR_MASK			//     €     Euro Sign
+// not yet implemented
+#define UNICODE_EXTRA00	0x20AC
+#define KEYCODE_EXTRA00	KEY_5 + ALTGR_MASK			// 20AC €    Euro Sign
+
+#endif // LAYOUT_US_INTERNATIONAL
+
+
+
+#ifdef LAYOUT_GERMAN
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define DEADKEYS_MASK		0x0700
+#define SHIFT_MASK		0x0100
+#define ALTGR_MASK		0x0200
+#define	CIRCUMFLEX_BITS		0x0300
+#define ACUTE_ACCENT_BITS	0x0400
+#define GRAVE_ACCENT_BITS	0x0500
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_CIRCUMFLEX	KEY_TILDE
+//#define DEADKEY_CIRCUMFLEX	KEY_NON_US_100
+#define DEADKEY_ACUTE_ACCENT	KEY_EQUAL
+#define DEADKEY_GRAVE_ACCENT	KEY_EQUAL + SHIFT_MASK
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_1 + SHIFT_MASK			// 33 !
+#define ASCII_22	KEY_2 + SHIFT_MASK			// 34 "
+#define ASCII_23	KEY_BACKSLASH				// 35 #		??
+#define ASCII_24	KEY_4 + SHIFT_MASK			// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_6 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_BACKSLASH + SHIFT_MASK		// 39 '  
+#define ASCII_28	KEY_8 + SHIFT_MASK			// 40 ( 
+#define ASCII_29	KEY_9 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_RIGHT_BRACE + SHIFT_MASK		// 42 *
+#define ASCII_2B	KEY_RIGHT_BRACE				// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_SLASH				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_7 + SHIFT_MASK			// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_PERIOD + SHIFT_MASK			// 58 :
+#define ASCII_3B	KEY_COMMA + SHIFT_MASK			// 59 ;
+#define ASCII_3C	KEY_NON_US_100				// 60 <
+#define ASCII_3D	KEY_0 + SHIFT_MASK			// 61 =
+#define ASCII_3E	KEY_NON_US_100 + SHIFT_MASK		// 62 >
+#define ASCII_3F	KEY_MINUS + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_Q + ALTGR_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Z + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Y + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_8 + ALTGR_MASK			// 91 [
+#define ASCII_5C	KEY_MINUS + ALTGR_MASK			// 92 
+#define ASCII_5D	KEY_9 + ALTGR_MASK			// 93 ]
+#define ASCII_5E	CIRCUMFLEX_BITS + KEY_SPACE		// 94 ^
+#define ASCII_5F	KEY_SLASH + SHIFT_MASK			// 95 _
+#define ASCII_60	GRAVE_ACCENT_BITS + KEY_SPACE		// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Z					// 121 y
+#define ASCII_7A	KEY_Y					// 122 z
+#define ASCII_7B	KEY_7 + ALTGR_MASK			// 123 {
+#define ASCII_7C	KEY_NON_US_100 + ALTGR_MASK		// 124 |
+#define ASCII_7D	KEY_0 + ALTGR_MASK			// 125 }
+#define ASCII_7E	KEY_RIGHT_BRACE + ALTGR_MASK		// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	0					// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	0					// 162 ¢     Cent Sign
+#define ISO_8859_1_A3	0					// 163 £     Pound Sign
+#define ISO_8859_1_A4	KEY_E + ALTGR_MASK			// 164 ¤     Currency Sign
+#define ISO_8859_1_A5	0					// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	0					// 166 ¦     BROKEN BAR
+#define ISO_8859_1_A7	KEY_3 + SHIFT_MASK			// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	0					// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	0					// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	0					// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	0					// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	0					// 172 ¬     NOT SIGN
+#define ISO_8859_1_AD	0					// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	0					// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0					// 175 ¯     MACRON
+#define ISO_8859_1_B0	KEY_TILDE + SHIFT_MASK			// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	0					// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	KEY_2 + ALTGR_MASK			// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	KEY_3 + ALTGR_MASK			// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	0					// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	KEY_M + ALTGR_MASK			// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	0					// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	0					// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	0					// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	0					// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	0					// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	0					// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	0					// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	0					// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	0					// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 192 À     A GRAVE
+#define ISO_8859_1_C1	ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 193 Á     A ACUTE
+#define ISO_8859_1_C2	CIRCUMFLEX_BITS	+ KEY_A + SHIFT_MASK	// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	0					// 195 Ã     A TILDE
+#define ISO_8859_1_C4	KEY_QUOTE + SHIFT_MASK			// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	0					// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	0					// 198 Æ     AE
+#define ISO_8859_1_C7	0					// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 200 È     E GRAVE
+#define ISO_8859_1_C9	ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 201 É     E ACUTE
+#define ISO_8859_1_CA	CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK	// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	0					// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 205 Í     I ACUTE
+#define ISO_8859_1_CE	CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK	// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	0					// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	0					// 208 Ð     ETH
+#define ISO_8859_1_D1	0					// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK	// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	0					// 213 Õ     O TILDE
+#define ISO_8859_1_D6	KEY_SEMICOLON + SHIFT_MASK		// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	0					// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	0					// 216 Ø     O STROKE
+#define ISO_8859_1_D9	GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK	// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	KEY_LEFT_BRACE + SHIFT_MASK		// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	ACUTE_ACCENT_BITS + KEY_Z + SHIFT_MASK	// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	0					// 222 Þ     THORN
+#define ISO_8859_1_DF	KEY_MINUS				// 223 ß     SHARP S
+#define ISO_8859_1_E0	GRAVE_ACCENT_BITS + KEY_A		// 224 à     a GRAVE
+#define ISO_8859_1_E1	ACUTE_ACCENT_BITS + KEY_A		// 225 á     a ACUTE
+#define ISO_8859_1_E2	CIRCUMFLEX_BITS + KEY_A			// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	0					// 227 ã     a TILDE
+#define ISO_8859_1_E4	KEY_QUOTE				// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	0					// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	0					// 230 æ     ae
+#define ISO_8859_1_E7	0					// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	GRAVE_ACCENT_BITS + KEY_E		// 232 è     e GRAVE
+#define ISO_8859_1_E9	ACUTE_ACCENT_BITS + KEY_E		// 233 é     e ACUTE
+#define ISO_8859_1_EA	CIRCUMFLEX_BITS + KEY_E			// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	0					// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	ACUTE_ACCENT_BITS + KEY_I		// 237 í     i ACUTE
+#define ISO_8859_1_EE	CIRCUMFLEX_BITS + KEY_I			// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	0					// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	0					// 240 ð     ETH
+#define ISO_8859_1_F1	0					// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	ACUTE_ACCENT_BITS + KEY_O		// 243 ó     o ACUTE
+#define ISO_8859_1_F4	CIRCUMFLEX_BITS + KEY_O			// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	0					// 245 õ     o TILDE
+#define ISO_8859_1_F6	KEY_SEMICOLON				// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	0					// 248 ø     o STROKE
+#define ISO_8859_1_F9	GRAVE_ACCENT_BITS + KEY_U		// 249 ù     u GRAVE
+#define ISO_8859_1_FA	ACUTE_ACCENT_BITS + KEY_U		// 250 ú     u ACUTE
+#define ISO_8859_1_FB	CIRCUMFLEX_BITS + KEY_U			// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	KEY_LEFT_BRACE				// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	ACUTE_ACCENT_BITS + KEY_Z		// 253 ý     y ACUTE
+#define ISO_8859_1_FE	0					// 254 þ     THORN
+#define ISO_8859_1_FF	0					// 255 ÿ     y DIAERESIS
+#define UNICODE_20AC	KEY_E + ALTGR_MASK			//     €     Euro Sign
+// not yet implemented
+#define UNICODE_EXTRA00	0x20AC
+#define KEYCODE_EXTRA00	KEY_E + ALTGR_MASK			// 20AC €    Euro Sign
+
+#endif // LAYOUT_GERMAN
+
+
+
+#ifdef LAYOUT_GERMAN_MAC
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define DEADKEYS_MASK		0x0700
+#define ACUTE_ACCENT_BITS	0x0100
+#define GRAVE_ACCENT_BITS	0x0200
+#define	CIRCUMFLEX_BITS		0x0300
+#define	DIAERESIS_BITS		0x0400
+#define	TILDE_BITS		0x0500
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_ACUTE_ACCENT	KEY_EQUAL
+#define DEADKEY_GRAVE_ACCENT	KEY_EQUAL + SHIFT_MASK
+#define DEADKEY_CIRCUMFLEX	KEY_6 + SHIFT_MASK + ALTGR_MASK
+#define DEADKEY_DIAERESIS	KEY_U + ALTGR_MASK
+#define DEADKEY_TILDE		KEY_N + ALTGR_MASK
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_1 + SHIFT_MASK			// 33 !
+#define ASCII_22	KEY_2 + SHIFT_MASK			// 34 "
+#define ASCII_23	KEY_BACKSLASH				// 35 #		??
+#define ASCII_24	KEY_4 + SHIFT_MASK			// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_6 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_BACKSLASH + SHIFT_MASK		// 39 '  
+#define ASCII_28	KEY_8 + SHIFT_MASK			// 40 ( 
+#define ASCII_29	KEY_9 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_RIGHT_BRACE + SHIFT_MASK		// 42 *
+#define ASCII_2B	KEY_RIGHT_BRACE				// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_SLASH				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_7 + SHIFT_MASK			// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_PERIOD + SHIFT_MASK			// 58 :
+#define ASCII_3B	KEY_COMMA + SHIFT_MASK			// 59 ;
+#define ASCII_3C	KEY_TILDE				// 60 <
+#define ASCII_3D	KEY_0 + SHIFT_MASK			// 61 =
+#define ASCII_3E	KEY_TILDE + SHIFT_MASK			// 62 >
+#define ASCII_3F	KEY_MINUS + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_Q + ALTGR_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Z + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Y + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_5 + ALTGR_MASK			// 91 [
+#define ASCII_5C	KEY_7 + ALTGR_MASK + SHIFT_MASK		// 92 
+#define ASCII_5D	KEY_6 + ALTGR_MASK			// 93 ]
+#define ASCII_5E	CIRCUMFLEX_BITS + KEY_SPACE		// 94 ^
+#define ASCII_5F	KEY_SLASH + SHIFT_MASK			// 95 _
+#define ASCII_60	GRAVE_ACCENT_BITS + KEY_SPACE		// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Z					// 121 y
+#define ASCII_7A	KEY_Y					// 122 z
+#define ASCII_7B	KEY_8 + ALTGR_MASK			// 123 {
+#define ASCII_7C	KEY_7 + ALTGR_MASK			// 124 |
+#define ASCII_7D	KEY_9 + ALTGR_MASK			// 125 }
+#define ASCII_7E	TILDE_BITS + KEY_SPACE			// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	KEY_1 + ALTGR_MASK			// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	KEY_4 + ALTGR_MASK			// 162 ¢     Cent Sign
+#define ISO_8859_1_A3	KEY_4 + SHIFT_MASK + ALTGR_MASK		// 163 £     Pound Sign
+#define ISO_8859_1_A4	KEY_E + ALTGR_MASK			// 164 ¤     Currency Sign
+#define ISO_8859_1_A5	KEY_Z + ALTGR_MASK			// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	0					// 166 ¦     BROKEN BAR
+#define ISO_8859_1_A7	KEY_3 + SHIFT_MASK			// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	DIAERESIS_BITS + KEY_SPACE		// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	KEY_G + ALTGR_MASK			// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	KEY_H + ALTGR_MASK			// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	KEY_Q + ALTGR_MASK			// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	0					// 172 ¬     NOT SIGN
+#define ISO_8859_1_AD	0					// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	KEY_R + ALTGR_MASK			// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	KEY_0 + SHIFT_MASK + ALTGR_MASK		// 175 ¯     MACRON
+#define ISO_8859_1_B0	KEY_LEFT_BRACE + ALTGR_MASK + SHIFT_MASK// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	KEY_RIGHT_BRACE + ALTGR_MASK		// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	0					// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	0					// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	ACUTE_ACCENT_BITS + KEY_SPACE		// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	KEY_M + ALTGR_MASK			// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	KEY_3 + ALTGR_MASK			// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	KEY_9 + SHIFT_MASK + ALTGR_MASK		// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	0					// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	KEY_J + ALTGR_MASK			// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	KEY_Q + SHIFT_MASK + ALTGR_MASK		// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	0					// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	0					// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	0					// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	KEY_MINUS + ALTGR_MASK			// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 192 À     A GRAVE
+#define ISO_8859_1_C1	ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 193 Á     A ACUTE
+#define ISO_8859_1_C2	CIRCUMFLEX_BITS	+ KEY_A + SHIFT_MASK	// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	TILDE_BITS + KEY_A + SHIFT_MASK		// 195 Ã     A TILDE
+#define ISO_8859_1_C4	KEY_QUOTE + SHIFT_MASK			// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	KEY_A + ALTGR_MASK + SHIFT_MASK		// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	KEY_QUOTE + ALTGR_MASK + SHIFT_MASK	// 198 Æ     AE
+#define ISO_8859_1_C7	KEY_C + ALTGR_MASK + SHIFT_MASK		// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 200 È     E GRAVE
+#define ISO_8859_1_C9	ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 201 É     E ACUTE
+#define ISO_8859_1_CA	CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK	// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	DIAERESIS_BITS + KEY_E + SHIFT_MASK	// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 205 Í     I ACUTE
+#define ISO_8859_1_CE	CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK	// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	DIAERESIS_BITS + KEY_I + SHIFT_MASK	// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	0					// 208 Ð     ETH
+#define ISO_8859_1_D1	TILDE_BITS + KEY_N + SHIFT_MASK		// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK	// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	TILDE_BITS + KEY_O + SHIFT_MASK		// 213 Õ     O TILDE
+#define ISO_8859_1_D6	KEY_SEMICOLON + SHIFT_MASK		// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	0					// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	KEY_O + ALTGR_MASK + SHIFT_MASK		// 216 Ø     O STROKE
+#define ISO_8859_1_D9	GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK	// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	KEY_LEFT_BRACE + SHIFT_MASK		// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	ACUTE_ACCENT_BITS + KEY_Z + SHIFT_MASK	// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	0					// 222 Þ     THORN
+#define ISO_8859_1_DF	KEY_MINUS				// 223 ß     SHARP S
+#define ISO_8859_1_E0	GRAVE_ACCENT_BITS + KEY_A		// 224 à     a GRAVE
+#define ISO_8859_1_E1	ACUTE_ACCENT_BITS + KEY_A		// 225 á     a ACUTE
+#define ISO_8859_1_E2	CIRCUMFLEX_BITS + KEY_A			// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	TILDE_BITS + KEY_A			// 227 ã     a TILDE
+#define ISO_8859_1_E4	KEY_QUOTE				// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	KEY_A + ALTGR_MASK			// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	KEY_QUOTE + ALTGR_MASK			// 230 æ     ae
+#define ISO_8859_1_E7	KEY_C + ALTGR_MASK			// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	GRAVE_ACCENT_BITS + KEY_E		// 232 è     e GRAVE
+#define ISO_8859_1_E9	ACUTE_ACCENT_BITS + KEY_E		// 233 é     e ACUTE
+#define ISO_8859_1_EA	CIRCUMFLEX_BITS + KEY_E			// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	DIAERESIS_BITS + KEY_E			// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	ACUTE_ACCENT_BITS + KEY_I		// 237 í     i ACUTE
+#define ISO_8859_1_EE	CIRCUMFLEX_BITS + KEY_I			// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	DIAERESIS_BITS + KEY_I			// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	0					// 240 ð     ETH
+#define ISO_8859_1_F1	TILDE_BITS + KEY_N			// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	ACUTE_ACCENT_BITS + KEY_O		// 243 ó     o ACUTE
+#define ISO_8859_1_F4	CIRCUMFLEX_BITS + KEY_O			// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	TILDE_BITS + KEY_O			// 245 õ     o TILDE
+#define ISO_8859_1_F6	KEY_SEMICOLON				// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	KEY_O + ALTGR_MASK			// 248 ø     o STROKE
+#define ISO_8859_1_F9	GRAVE_ACCENT_BITS + KEY_U		// 249 ù     u GRAVE
+#define ISO_8859_1_FA	ACUTE_ACCENT_BITS + KEY_U		// 250 ú     u ACUTE
+#define ISO_8859_1_FB	CIRCUMFLEX_BITS + KEY_U			// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	KEY_LEFT_BRACE				// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	ACUTE_ACCENT_BITS + KEY_Z		// 253 ý     y ACUTE
+#define ISO_8859_1_FE	0					// 254 þ     THORN
+#define ISO_8859_1_FF	DIAERESIS_BITS + KEY_Z			// 255 ÿ     y DIAERESIS
+#define UNICODE_20AC	KEY_E + ALTGR_MASK			//     €     Euro Sign
+// not yet implemented
+#define UNICODE_EXTRA00	0x20AC
+#define KEYCODE_EXTRA00	KEY_E + ALTGR_MASK			// 20AC €    Euro Sign
+
+#endif // LAYOUT_GERMAN_MAC
+
+
+
+
+
+
+#ifdef LAYOUT_CANADIAN_FRENCH
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define DEADKEYS_MASK		0x0700
+#define	CIRCUMFLEX_BITS		0x0100
+#define ACUTE_ACCENT_BITS	0x0200
+#define GRAVE_ACCENT_BITS	0x0300
+#define DIAERESIS_BITS		0x0400
+#define CEDILLA_BITS		0x0500
+
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_CIRCUMFLEX	KEY_LEFT_BRACE
+#define DEADKEY_ACUTE_ACCENT	KEY_SLASH + ALTGR_MASK
+#define DEADKEY_GRAVE_ACCENT	KEY_QUOTE
+#define DEADKEY_DIAERESIS	KEY_RIGHT_BRACE + SHIFT_MASK
+#define DEADKEY_CEDILLA		KEY_RIGHT_BRACE
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_1 + SHIFT_MASK			// 33 !
+#define ASCII_22	KEY_2 + SHIFT_MASK			// 34 "
+#define ASCII_23	KEY_TILDE + SHIFT_MASK			// 35 #
+#define ASCII_24	KEY_4 + SHIFT_MASK			// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_7 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_COMMA + SHIFT_MASK			// 39 '  
+#define ASCII_27	ACUTE_ACCENT_BITS + KEY_SPACE		// 39 '  
+#define ASCII_28	KEY_9 + SHIFT_MASK			// 40 ( 
+#define ASCII_29	KEY_0 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_8 + SHIFT_MASK			// 42 *
+#define ASCII_2B	KEY_EQUAL + SHIFT_MASK			// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_MINUS				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_3 + SHIFT_MASK			// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_SEMICOLON + SHIFT_MASK		// 58 :
+#define ASCII_3B	KEY_SEMICOLON				// 59 ;
+#define ASCII_3C	KEY_BACKSLASH				// 60 <
+#define ASCII_3D	KEY_EQUAL				// 61 =
+#define ASCII_3E	KEY_BACKSLASH + SHIFT_MASK		// 62 >
+#define ASCII_3F	KEY_6 + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_2 + ALTGR_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Y + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Z + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_LEFT_BRACE + ALTGR_MASK		// 91 [
+#define ASCII_5C	KEY_TILDE + ALTGR_MASK			// 92 
+#define ASCII_5D	KEY_RIGHT_BRACE + ALTGR_MASK		// 93 ]
+#define ASCII_5E	CIRCUMFLEX_BITS + KEY_SPACE		// 94 ^
+#define ASCII_5F	KEY_MINUS + SHIFT_MASK			// 95 _
+#define ASCII_60	GRAVE_ACCENT_BITS + KEY_SPACE		// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Y					// 121 y
+#define ASCII_7A	KEY_Z					// 122 z
+#define ASCII_7B	KEY_QUOTE + ALTGR_MASK			// 123 {
+#define ASCII_7C	KEY_TILDE + SHIFT_MASK			// 124 |
+#define ASCII_7D	KEY_BACKSLASH + ALTGR_MASK		// 125 }
+#define ASCII_7E	KEY_SEMICOLON + ALTGR_MASK		// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	0					// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	KEY_4 + ALTGR_MASK			// 162 ¢     Cent SIGN
+#define ISO_8859_1_A3	KEY_3 + ALTGR_MASK			// 163 £     Pound Sign
+#define ISO_8859_1_A4	KEY_5 + ALTGR_MASK			// 164 ¤     Currency or Euro Sign
+#define ISO_8859_1_A5	0					// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	KEY_7 + ALTGR_MASK			// 166 ¦     BROKEN BAR
+#define ISO_8859_1_A7	KEY_O + ALTGR_MASK			// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	0					// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	0					// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	0					// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	KEY_NON_US_100				// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	KEY_6 + ALTGR_MASK			// 172 ¬     NOT SIGN
+#define ISO_8859_1_AD	KEY_PERIOD + ALTGR_MASK			// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	0					// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	KEY_COMMA + ALTGR_MASK			// 175 ¯     MACRON
+#define ISO_8859_1_B0	KEY_NON_US_100 + ALTGR_MASK		// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	KEY_1 + ALTGR_MASK			// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	KEY_8 + ALTGR_MASK			// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	KEY_9 + ALTGR_MASK			// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	0					// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	KEY_M + ALTGR_MASK			// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	KEY_P + ALTGR_MASK			// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	0					// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	0					// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	0					// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	KEY_NON_US_100 + SHIFT_MASK		// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	KEY_0 + ALTGR_MASK			// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	KEY_MINUS + ALTGR_MASK			// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	KEY_EQUAL + ALTGR_MASK			// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	0					// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 192 À     A GRAVE
+#define ISO_8859_1_C1	ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 193 Á     A ACUTE
+#define ISO_8859_1_C2	CIRCUMFLEX_BITS	+ KEY_A + SHIFT_MASK	// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	0					// 195 Ã     A TILDE
+#define ISO_8859_1_C4	DIAERESIS_BITS + KEY_A + SHIFT_MASK	// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	0					// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	0					// 198 Æ     AE
+#define ISO_8859_1_C7	CEDILLA_BITS + KEY_C + SHIFT_MASK	// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 200 È     E GRAVE
+#define ISO_8859_1_C9	KEY_SLASH + SHIFT_MASK			// 201 É     E ACUTE
+#define ISO_8859_1_CA	CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK	// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	DIAERESIS_BITS + KEY_E + SHIFT_MASK	// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 205 Í     I ACUTE
+#define ISO_8859_1_CE	CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK	// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	DIAERESIS_BITS + KEY_I + SHIFT_MASK	// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	0					// 208 Ð     ETH
+#define ISO_8859_1_D1	0					// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK	// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	0					// 213 Õ     O TILDE
+#define ISO_8859_1_D6	DIAERESIS_BITS + KEY_O + SHIFT_MASK	// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	0					// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	0					// 216 Ø     O STROKE
+#define ISO_8859_1_D9	GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK	// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	DIAERESIS_BITS + KEY_U			// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK	// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	0					// 222 Þ     THORN
+#define ISO_8859_1_DF	0					// 223 ß     SHARP S
+#define ISO_8859_1_E0	GRAVE_ACCENT_BITS + KEY_A		// 224 à     a GRAVE
+#define ISO_8859_1_E1	ACUTE_ACCENT_BITS + KEY_A		// 225 á     a ACUTE
+#define ISO_8859_1_E2	CIRCUMFLEX_BITS + KEY_A			// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	0					// 227 ã     a TILDE
+#define ISO_8859_1_E4	DIAERESIS_BITS + KEY_A			// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	0					// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	0					// 230 æ     ae
+#define ISO_8859_1_E7	CEDILLA_BITS + KEY_C			// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	GRAVE_ACCENT_BITS + KEY_E		// 232 è     e GRAVE
+#define ISO_8859_1_E9	KEY_SLASH				// 233 é     e ACUTE
+#define ISO_8859_1_EA	CIRCUMFLEX_BITS + KEY_E			// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	DIAERESIS_BITS + KEY_E			// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	ACUTE_ACCENT_BITS + KEY_I		// 237 í     i ACUTE
+#define ISO_8859_1_EE	CIRCUMFLEX_BITS + KEY_I			// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	DIAERESIS_BITS + KEY_I			// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	0					// 240 ð     ETH
+#define ISO_8859_1_F1	0					// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	ACUTE_ACCENT_BITS + KEY_O		// 243 ó     o ACUTE
+#define ISO_8859_1_F4	CIRCUMFLEX_BITS + KEY_O			// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	0					// 245 õ     o TILDE
+#define ISO_8859_1_F6	DIAERESIS_BITS + KEY_O			// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	0					// 248 ø     o STROKE
+#define ISO_8859_1_F9	GRAVE_ACCENT_BITS + KEY_U		// 249 ù     u GRAVE
+#define ISO_8859_1_FA	ACUTE_ACCENT_BITS + KEY_U		// 250 ú     u ACUTE
+#define ISO_8859_1_FB	CIRCUMFLEX_BITS + KEY_U			// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	DIAERESIS_BITS + KEY_U			// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	ACUTE_ACCENT_BITS + KEY_Y		// 253 ý     y ACUTE
+#define ISO_8859_1_FE	0					// 254 þ     THORN
+#define ISO_8859_1_FF	DIAERESIS_BITS + KEY_Y			// 255 ÿ     y DIAERESIS
+
+#endif // LAYOUT_CANADIAN_FRENCH
+
+
+
+#ifdef LAYOUT_CANADIAN_MULTILINGUAL
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define RCTRL_MASK		0x0800
+#define DEADKEYS_MASK		0x0700
+#define	CIRCUMFLEX_BITS		0x0100
+#define DIAERESIS_BITS		0x0200
+#define ACUTE_ACCENT_BITS	0x0300
+#define CEDILLA_BITS		0x0400
+#define GRAVE_ACCENT_BITS	0x0500
+#define TILDE_BITS		0x0600
+#define RING_ABOVE_BITS	 	0x0700
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_CIRCUMFLEX	KEY_LEFT_BRACE
+#define DEADKEY_DIAERESIS	KEY_LEFT_BRACE + SHIFT_MASK
+#define DEADKEY_ACUTE_ACCENT	KEY_SEMICOLON + RCTRL_MASK
+#define DEADKEY_CEDILLA		KEY_EQUAL + RCTRL_MASK
+#define DEADKEY_GRAVE_ACCENT	KEY_LEFT_BRACE + ALTGR_MASK
+#define DEADKEY_TILDE		KEY_RIGHT_BRACE + ALTGR_MASK
+#define DEADKEY_RING_ABOVE	KEY_LEFT_BRACE + SHIFT_MASK + RCTRL_MASK
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_1 + SHIFT_MASK			// 33 !
+#define ASCII_22	KEY_PERIOD + SHIFT_MASK			// 34 "
+#define ASCII_23	KEY_3 + SHIFT_MASK			// 35 #
+#define ASCII_24	KEY_4 + SHIFT_MASK			// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_7 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_COMMA + SHIFT_MASK			// 39 '  
+#define ASCII_28	KEY_9 + SHIFT_MASK			// 40 ( 
+#define ASCII_29	KEY_0 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_8 + SHIFT_MASK			// 42 *
+#define ASCII_2B	KEY_EQUAL + SHIFT_MASK			// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_MINUS				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_TILDE				// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_SEMICOLON + SHIFT_MASK		// 58 :
+#define ASCII_3B	KEY_SEMICOLON				// 59 ;
+#define ASCII_3C	KEY_COMMA + ALTGR_MASK			// 60 <
+#define ASCII_3D	KEY_EQUAL				// 61 =
+#define ASCII_3E	KEY_PERIOD + ALTGR_MASK			// 62 >
+#define ASCII_3F	KEY_6 + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_2 + SHIFT_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Y + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Z + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_9 + ALTGR_MASK			// 91 [
+#define ASCII_5C	KEY_TILDE + SHIFT_MASK			// 92 
+#define ASCII_5D	KEY_0 + ALTGR_MASK			// 93 ]
+#define ASCII_5E	CIRCUMFLEX_BITS + KEY_SPACE		// 94 ^
+#define ASCII_5F	KEY_MINUS + SHIFT_MASK			// 95 _
+#define ASCII_60	GRAVE_ACCENT_BITS + KEY_SPACE		// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Y					// 121 y
+#define ASCII_7A	KEY_Z					// 122 z
+#define ASCII_7B	KEY_7 + ALTGR_MASK			// 123 {
+#define ASCII_7C	KEY_TILDE + ALTGR_MASK			// 124 |
+#define ASCII_7D	KEY_8 + ALTGR_MASK			// 125 }
+#define ASCII_7E	KEY_RIGHT_BRACE + RCTRL_MASK		// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+#define ISO_8859_1_A0	KEY_SPACE + ALTGR_MASK			// 160       Nonbreakng Space
+#define ISO_8859_1_A1	KEY_1 + SHIFT_MASK + RCTRL_MASK		// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	KEY_C + RCTRL_MASK			// 162 ¢     Cent SIGN
+#define ISO_8859_1_A3	KEY_3 + SHIFT_MASK + RCTRL_MASK		// 163 £     Pound Sign
+#define ISO_8859_1_A4	KEY_4 + SHIFT_MASK + RCTRL_MASK		// 164 ¤     Currency or Euro Sign
+#define ISO_8859_1_A5	KEY_Y + SHIFT_MASK + RCTRL_MASK		// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	KEY_NON_US_100 + SHIFT_MASK + RCTRL_MASK// 166 ¦     BROKEN BAR
+#define ISO_8859_1_A7	KEY_S + SHIFT_MASK + RCTRL_MASK		// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	DIAERESIS_BITS + KEY_SPACE		// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	KEY_C + SHIFT_MASK + RCTRL_MASK		// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	KEY_F + SHIFT_MASK + RCTRL_MASK		// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	KEY_Z + ALTGR_MASK			// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	KEY_EQUAL + ALTGR_MASK			// 172 ¬     NOT SIGN
+#define ISO_8859_1_AD	KEY_TILDE + SHIFT_MASK + RCTRL_MASK	// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	KEY_R + SHIFT_MASK + RCTRL_MASK		// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0  // special dead key - no implemented	// 175 ¯     MACRON
+#define ISO_8859_1_B0	KEY_SEMICOLON + ALTGR_MASK		// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	KEY_9 + SHIFT_MASK + RCTRL_MASK		// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	KEY_2 + RCTRL_MASK			// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	KEY_3 + RCTRL_MASK			// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	ACUTE_ACCENT_BITS + KEY_SPACE		// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	KEY_M + RCTRL_MASK			// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	KEY_R + RCTRL_MASK			// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	0					// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	CEDILLA_BITS + KEY_SPACE		// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	KEY_1 + RCTRL_MASK			// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	KEY_M + SHIFT_MASK + RCTRL_MASK		// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	KEY_X + ALTGR_MASK			// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	KEY_4 + RCTRL_MASK			// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	KEY_5 + RCTRL_MASK			// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	KEY_6 + RCTRL_MASK			// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	KEY_MINUS + SHIFT_MASK + RCTRL_MASK	// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	KEY_BACKSLASH + SHIFT_MASK		// 192 À     A GRAVE
+#define ISO_8859_1_C1	ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 193 Á     A ACUTE
+#define ISO_8859_1_C2	CIRCUMFLEX_BITS	+ KEY_A + SHIFT_MASK	// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	TILDE_BITS + KEY_A + SHIFT_MASK		// 195 Ã     A TILDE
+#define ISO_8859_1_C4	DIAERESIS_BITS + KEY_A + SHIFT_MASK	// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	RING_ABOVE_BITS + KEY_A + SHIFT_MASK	// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	KEY_A + SHIFT_MASK + RCTRL_MASK		// 198 Æ     AE
+#define ISO_8859_1_C7	KEY_RIGHT_BRACE + SHIFT_MASK		// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	KEY_QUOTE + SHIFT_MASK			// 200 È     E GRAVE
+#define ISO_8859_1_C9	KEY_SLASH + SHIFT_MASK			// 201 É     E ACUTE
+#define ISO_8859_1_CA	CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK	// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	DIAERESIS_BITS + KEY_E + SHIFT_MASK	// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 205 Í     I ACUTE
+#define ISO_8859_1_CE	CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK	// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	DIAERESIS_BITS + KEY_I + SHIFT_MASK	// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	KEY_D + SHIFT_MASK + RCTRL_MASK		// 208 Ð     ETH
+#define ISO_8859_1_D1	TILDE_BITS + KEY_N + SHIFT_MASK		// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK	// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	TILDE_BITS + KEY_O + SHIFT_MASK		// 213 Õ     O TILDE
+#define ISO_8859_1_D6	DIAERESIS_BITS + KEY_O + SHIFT_MASK	// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	KEY_COMMA + SHIFT_MASK + RCTRL_MASK	// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	KEY_O + SHIFT_MASK + RCTRL_MASK		// 216 Ø     O STROKE
+#define ISO_8859_1_D9	KEY_NON_US_100 + SHIFT_MASK		// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK	// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	DIAERESIS_BITS + KEY_U			// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK	// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	KEY_P + RCTRL_MASK + SHIFT_MASK		// 222 Þ     THORN
+#define ISO_8859_1_DF	KEY_S + RCTRL_MASK			// 223 ß     SHARP S
+#define ISO_8859_1_E0	KEY_BACKSLASH				// 224 à     a GRAVE
+#define ISO_8859_1_E1	ACUTE_ACCENT_BITS + KEY_A		// 225 á     a ACUTE
+#define ISO_8859_1_E2	CIRCUMFLEX_BITS + KEY_A			// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	TILDE_BITS + KEY_A			// 227 ã     a TILDE
+#define ISO_8859_1_E4	DIAERESIS_BITS + KEY_A			// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	RING_ABOVE_BITS + KEY_A			// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	KEY_A + RCTRL_MASK			// 230 æ     ae
+#define ISO_8859_1_E7	KEY_RIGHT_BRACE				// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	KEY_QUOTE				// 232 è     e GRAVE
+#define ISO_8859_1_E9	KEY_SLASH				// 233 é     e ACUTE
+#define ISO_8859_1_EA	CIRCUMFLEX_BITS + KEY_E			// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	DIAERESIS_BITS + KEY_E			// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	ACUTE_ACCENT_BITS + KEY_I		// 237 í     i ACUTE
+#define ISO_8859_1_EE	CIRCUMFLEX_BITS + KEY_I			// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	DIAERESIS_BITS + KEY_I			// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	KEY_D + RCTRL_MASK			// 240 ð     ETH
+#define ISO_8859_1_F1	TILDE_BITS + KEY_N			// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	ACUTE_ACCENT_BITS + KEY_O		// 243 ó     o ACUTE
+#define ISO_8859_1_F4	CIRCUMFLEX_BITS + KEY_O			// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	TILDE_BITS + KEY_O			// 245 õ     o TILDE
+#define ISO_8859_1_F6	DIAERESIS_BITS + KEY_O			// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	KEY_PERIOD + SHIFT_MASK + RCTRL_MASK	// 247 ÷     DIVISION
+#define ISO_8859_1_F8	KEY_O + RCTRL_MASK			// 248 ø     o STROKE
+#define ISO_8859_1_F9	KEY_NON_US_100				// 249 ù     u GRAVE
+#define ISO_8859_1_FA	ACUTE_ACCENT_BITS + KEY_U		// 250 ú     u ACUTE
+#define ISO_8859_1_FB	CIRCUMFLEX_BITS + KEY_U			// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	DIAERESIS_BITS + KEY_U			// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	ACUTE_ACCENT_BITS + KEY_Y		// 253 ý     y ACUTE
+#define ISO_8859_1_FE	KEY_P + RCTRL_MASK			// 254 þ     THORN
+#define ISO_8859_1_FF	DIAERESIS_BITS + KEY_Y			// 255 ÿ     y DIAERESIS
+
+#endif // LAYOUT_CANADIAN_MULTILINGUAL
+
+
+
+
+
+
+#ifdef LAYOUT_UNITED_KINGDOM
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define KEYCODE_TYPE		uint8_t
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_1 + SHIFT_MASK			// 33 !
+#define ASCII_22	KEY_2 + SHIFT_MASK			// 34 "
+#define ASCII_23	KEY_BACKSPACE				// 35 #
+#define ASCII_24	KEY_4 + SHIFT_MASK			// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_7 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_QUOTE				// 39 '  
+#define ASCII_28	KEY_9 + SHIFT_MASK			// 40 ( 
+#define ASCII_29	KEY_0 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_8 + SHIFT_MASK			// 42 *
+#define ASCII_2B	KEY_EQUAL + SHIFT_MASK			// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_MINUS				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_SLASH				// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_SEMICOLON + SHIFT_MASK		// 58 :
+#define ASCII_3B	KEY_SEMICOLON				// 59 ;
+#define ASCII_3C	KEY_COMMA + SHIFT_MASK			// 60 <
+#define ASCII_3D	KEY_EQUAL				// 61 =
+#define ASCII_3E	KEY_PERIOD + SHIFT_MASK			// 62 >
+#define ASCII_3F	KEY_SLASH + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_QUOTE + SHIFT_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Y + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Z + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_LEFT_BRACE				// 91 [
+#define ASCII_5C	KEY_NON_US_100				// 92 
+#define ASCII_5D	KEY_RIGHT_BRACE				// 93 ]
+#define ASCII_5E	KEY_6 + SHIFT_MASK			// 94 ^
+#define ASCII_5F	KEY_MINUS + SHIFT_MASK			// 95 _
+#define ASCII_60	KEY_TILDE				// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Y					// 121 y
+#define ASCII_7A	KEY_Z					// 122 z
+#define ASCII_7B	KEY_LEFT_BRACE + SHIFT_MASK		// 123 {
+#define ASCII_7C	KEY_NON_US_100 + SHIFT_MASK		// 124 |
+#define ASCII_7D	KEY_RIGHT_BRACE + SHIFT_MASK		// 125 }
+#define ASCII_7E	KEY_BACKSLASH + SHIFT_MASK		// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	0					// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	0					// 162 ¢     Cent SIGN
+#define ISO_8859_1_A3	KEY_3 + SHIFT_MASK			// 163 £     Pound Sign
+#define ISO_8859_1_A4	0					// 164 ¤     Currency or Euro Sign
+#define ISO_8859_1_A5	0					// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	KEY_TILDE + ALTGR_MASK			// 166 ¦     BROKEN BAR
+#define ISO_8859_1_A7	0					// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	0					// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	0					// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	0					// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	0					// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	KEY_TILDE + SHIFT_MASK			// 172 ¬     NOT SIGN
+#define ISO_8859_1_AD	0					// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	0					// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0					// 175 ¯     MACRON
+#define ISO_8859_1_B0	0					// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	0					// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	0					// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	0					// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	0					// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	0					// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	0					// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	0					// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	0					// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	0					// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	0					// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	0					// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	0					// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	0					// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	0					// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	0					// 192 À     A GRAVE
+#define ISO_8859_1_C1	KEY_A + ALTGR_MASK + SHIFT_MASK		// 193 Á     A ACUTE
+#define ISO_8859_1_C2	0					// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	0					// 195 Ã     A TILDE
+#define ISO_8859_1_C4	0					// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	0					// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	0					// 198 Æ     AE
+#define ISO_8859_1_C7	0					// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	0					// 200 È     E GRAVE
+#define ISO_8859_1_C9	KEY_E + ALTGR_MASK + SHIFT_MASK		// 201 É     E ACUTE
+#define ISO_8859_1_CA	0					// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	0					// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	0					// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	KEY_I + ALTGR_MASK + SHIFT_MASK		// 205 Í     I ACUTE
+#define ISO_8859_1_CE	0					// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	0					// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	0					// 208 Ð     ETH
+#define ISO_8859_1_D1	0					// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	0					// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	KEY_O + ALTGR_MASK + SHIFT_MASK		// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	0					// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	0					// 213 Õ     O TILDE
+#define ISO_8859_1_D6	0					// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	0					// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	0					// 216 Ø     O STROKE
+#define ISO_8859_1_D9	0					// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	KEY_U + ALTGR_MASK + SHIFT_MASK		// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	0					// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	0					// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	0					// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	0					// 222 Þ     THORN
+#define ISO_8859_1_DF	0					// 223 ß     SHARP S
+#define ISO_8859_1_E0	0					// 224 à     a GRAVE
+#define ISO_8859_1_E1	KEY_A + ALTGR_MASK			// 225 á     a ACUTE
+#define ISO_8859_1_E2	0					// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	0					// 227 ã     a TILDE
+#define ISO_8859_1_E4	0					// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	0					// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	0					// 230 æ     ae
+#define ISO_8859_1_E7	0					// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	0					// 232 è     e GRAVE
+#define ISO_8859_1_E9	KEY_E + ALTGR_MASK			// 233 é     e ACUTE
+#define ISO_8859_1_EA	0					// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	0					// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	0					// 236 ì     i GRAVE
+#define ISO_8859_1_ED	KEY_I + ALTGR_MASK			// 237 í     i ACUTE
+#define ISO_8859_1_EE	0					// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	0					// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	0					// 240 ð     ETH
+#define ISO_8859_1_F1	0					// 241 ñ     n TILDE
+#define ISO_8859_1_F2	0					// 242 ò     o GRAVE
+#define ISO_8859_1_F3	KEY_O + ALTGR_MASK			// 243 ó     o ACUTE
+#define ISO_8859_1_F4	0					// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	0					// 245 õ     o TILDE
+#define ISO_8859_1_F6	0					// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	0					// 248 ø     o STROKE
+#define ISO_8859_1_F9	0					// 249 ù     u GRAVE
+#define ISO_8859_1_FA	KEY_U + ALTGR_MASK			// 250 ú     u ACUTE
+#define ISO_8859_1_FB	0					// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	0					// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	0					// 253 ý     y ACUTE
+#define ISO_8859_1_FE	0					// 254 þ     THORN
+#define ISO_8859_1_FF	0					// 255 ÿ     y DIAERESIS
+#define UNICODE_20AC	KEY_4 + ALTGR_MASK			//     €     Euro Sign
+// not yet implemented
+#define UNICODE_EXTRA00	0x20AC
+#define KEYCODE_EXTRA00	KEY_4 + ALTGR_MASK			// 20AC €    Euro Sign
+
+#endif // LAYOUT_UNITED_KINGDOM
+
+
+
+#ifdef LAYOUT_FINNISH
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define DEADKEYS_MASK		0x0700
+#define	CIRCUMFLEX_BITS		0x0100
+#define ACUTE_ACCENT_BITS	0x0200
+#define GRAVE_ACCENT_BITS	0x0300
+#define TILDE_BITS		0x0400
+#define DIAERESIS_BITS		0x0500
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_CIRCUMFLEX	KEY_RIGHT_BRACE + SHIFT_MASK
+#define DEADKEY_ACUTE_ACCENT	KEY_EQUAL
+#define DEADKEY_GRAVE_ACCENT	KEY_EQUAL + SHIFT_MASK
+#define DEADKEY_TILDE		KEY_RIGHT_BRACE + ALTGR_MASK
+#define DEADKEY_DIAERESIS	KEY_RIGHT_BRACE
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_1 + SHIFT_MASK			// 33 !
+#define ASCII_22	KEY_2 + SHIFT_MASK			// 34 "
+#define ASCII_23	KEY_3 + SHIFT_MASK			// 35 #
+#define ASCII_24	KEY_4 + ALTGR_MASK			// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_6 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_BACKSLASH				// 39 '  
+#define ASCII_28	KEY_8 + SHIFT_MASK			// 40 ( 
+#define ASCII_29	KEY_9 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_BACKSLASH + SHIFT_MASK		// 42 *
+#define ASCII_2B	KEY_MINUS				// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_SLASH				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_7 + SHIFT_MASK			// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_PERIOD + SHIFT_MASK			// 58 :
+#define ASCII_3B	KEY_COMMA + SHIFT_MASK			// 59 ;
+#define ASCII_3C	KEY_NON_US_100				// 60 <
+#define ASCII_3D	KEY_0 + SHIFT_MASK			// 61 =
+#define ASCII_3E	KEY_NON_US_100 + SHIFT_MASK		// 62 >
+#define ASCII_3F	KEY_MINUS + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_2 + ALTGR_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Y + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Z + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_8 + ALTGR_MASK			// 91 [
+#define ASCII_5C	KEY_MINUS + ALTGR_MASK			// 92 
+#define ASCII_5D	KEY_9 + ALTGR_MASK			// 93 ]
+#define ASCII_5E	CIRCUMFLEX_BITS + KEY_SPACE		// 94 ^
+#define ASCII_5F	KEY_SLASH + SHIFT_MASK			// 95 _
+#define ASCII_60	GRAVE_ACCENT_BITS + KEY_SPACE		// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Y					// 121 y
+#define ASCII_7A	KEY_Z					// 122 z
+#define ASCII_7B	KEY_7 + ALTGR_MASK			// 123 {
+#define ASCII_7C	KEY_NON_US_100 + ALTGR_MASK		// 124 |
+#define ASCII_7D	KEY_0 + ALTGR_MASK			// 125 }
+#define ASCII_7E	TILDE_BITS + KEY_SPACE			// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+#define ISO_8859_1_A0	KEY_SPACE + ALTGR_MASK			// 160       Nonbreakng Space
+#define ISO_8859_1_A1	KEY_1 + SHIFT_MASK + ALTGR_MASK		// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	0					// 162 ¢     Cent SIGN
+#define ISO_8859_1_A3	KEY_3 + ALTGR_MASK			// 163 £     Pound Sign
+#define ISO_8859_1_A4	KEY_4 + SHIFT_MASK			// 164 ¤     Currency or Euro Sign
+#define ISO_8859_1_A5	0					// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	0					// 166 ¦     BROKEN BAR
+#define ISO_8859_1_A7	KEY_TILDE				// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	DIAERESIS_BITS + KEY_SPACE		// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	0					// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	0					// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	KEY_4 + ALTGR_MASK + SHIFT_MASK		// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	0					// 172 ¬     NOT SIGN
+#define ISO_8859_1_AD	KEY_SLASH + ALTGR_MASK			// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	0					// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0					// 175 ¯     MACRON
+#define ISO_8859_1_B0	KEY_0 + ALTGR_MASK + SHIFT_MASK		// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	0					// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	0					// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	0					// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	ACUTE_ACCENT_BITS + KEY_SPACE		// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	KEY_M + ALTGR_MASK			// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	0					// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	KEY_X + ALTGR_MASK + SHIFT_MASK		// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	0					// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	0					// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	KEY_3 + ALTGR_MASK + SHIFT_MASK		// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	0					// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	KEY_TILDE + SHIFT_MASK			// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	0					// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	KEY_MINUS + ALTGR_MASK + SHIFT_MASK	// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 192 À     A GRAVE
+#define ISO_8859_1_C1	ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 193 Á     A ACUTE
+#define ISO_8859_1_C2	CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK	// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	TILDE_BITS + KEY_A + SHIFT_MASK		// 195 Ã     A TILDE
+#define ISO_8859_1_C4	KEY_QUOTE + SHIFT_MASK			// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	KEY_LEFT_BRACE + SHIFT_MASK		// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	KEY_QUOTE + ALTGR_MASK + SHIFT_MASK	// 198 Æ     AE
+#define ISO_8859_1_C7	0					// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 200 È     E GRAVE
+#define ISO_8859_1_C9	ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 201 É     E ACUTE
+#define ISO_8859_1_CA	CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK	// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	DIAERESIS_BITS + KEY_E + SHIFT_MASK	// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 205 Í     I ACUTE
+#define ISO_8859_1_CE	CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK	// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	DIAERESIS_BITS + KEY_I + SHIFT_MASK	// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	KEY_D + ALTGR_MASK + SHIFT_MASK		// 208 Ð     ETH
+#define ISO_8859_1_D1	TILDE_BITS + KEY_N + SHIFT_MASK		// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK	// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	TILDE_BITS + KEY_O + SHIFT_MASK		// 213 Õ     O TILDE
+#define ISO_8859_1_D6	KEY_SEMICOLON + SHIFT_MASK		// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	KEY_X + ALTGR_MASK			// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	KEY_SEMICOLON + ALTGR_MASK + SHIFT_MASK	// 216 Ø     O STROKE
+#define ISO_8859_1_D9	GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK	// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	DIAERESIS_BITS + KEY_U + SHIFT_MASK	// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK	// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	KEY_T + ALTGR_MASK + SHIFT_MASK		// 222 Þ     THORN
+#define ISO_8859_1_DF	KEY_S + ALTGR_MASK			// 223 ß     SHARP S
+#define ISO_8859_1_E0	GRAVE_ACCENT_BITS + KEY_A		// 224 à     a GRAVE
+#define ISO_8859_1_E1	ACUTE_ACCENT_BITS + KEY_A		// 225 á     a ACUTE
+#define ISO_8859_1_E2	CIRCUMFLEX_BITS + KEY_A			// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	TILDE_BITS + KEY_A			// 227 ã     a TILDE
+#define ISO_8859_1_E4	KEY_QUOTE				// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	KEY_LEFT_BRACE				// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	KEY_QUOTE + ALTGR_MASK			// 230 æ     ae
+#define ISO_8859_1_E7	0					// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	GRAVE_ACCENT_BITS + KEY_E		// 232 è     e GRAVE
+#define ISO_8859_1_E9	ACUTE_ACCENT_BITS + KEY_E		// 233 é     e ACUTE
+#define ISO_8859_1_EA	CIRCUMFLEX_BITS + KEY_E			// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	DIAERESIS_BITS + KEY_E			// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	ACUTE_ACCENT_BITS + KEY_I		// 237 í     i ACUTE
+#define ISO_8859_1_EE	CIRCUMFLEX_BITS + KEY_I			// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	DIAERESIS_BITS + KEY_I			// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	KEY_D + ALTGR_MASK			// 240 ð     ETH
+#define ISO_8859_1_F1	TILDE_BITS + KEY_N			// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	ACUTE_ACCENT_BITS + KEY_O		// 243 ó     o ACUTE
+#define ISO_8859_1_F4	CIRCUMFLEX_BITS + KEY_O			// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	TILDE_BITS + KEY_O			// 245 õ     o TILDE
+#define ISO_8859_1_F6	KEY_SEMICOLON				// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	KEY_SEMICOLON + ALTGR_MASK		// 248 ø     o STROKE
+#define ISO_8859_1_F9	GRAVE_ACCENT_BITS + KEY_U		// 249 ù     u GRAVE
+#define ISO_8859_1_FA	ACUTE_ACCENT_BITS + KEY_U		// 250 ú     u ACUTE
+#define ISO_8859_1_FB	CIRCUMFLEX_BITS + KEY_U			// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	DIAERESIS_BITS + KEY_U			// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	ACUTE_ACCENT_BITS + KEY_Y		// 253 ý     y ACUTE
+#define ISO_8859_1_FE	KEY_T + ALTGR_MASK			// 254 þ     THORN
+#define ISO_8859_1_FF	DIAERESIS_BITS + KEY_Y			// 255 ÿ     y DIAERESIS
+#define UNICODE_20AC	KEY_E + ALTGR_MASK			//     €     Euro Sign
+// not yet implemented
+#define UNICODE_EXTRA00	0x20AC
+#define KEYCODE_EXTRA00	KEY_E + ALTGR_MASK			// 20AC €    Euro Sign
+// TODO: Finnish Multilingual layout can type many more glyphs
+// but we currently don't have tables tables to store them...
+
+#endif // LAYOUT_FINNISH
+
+
+
+
+
+
+
+#ifdef LAYOUT_FRENCH
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define DEADKEYS_MASK		0x0700
+#define	CIRCUMFLEX_BITS		0x0100
+#define GRAVE_ACCENT_BITS	0x0200
+#define DIAERESIS_BITS		0x0300
+#define TILDE_BITS		0x0400
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_CIRCUMFLEX	KEY_LEFT_BRACE
+#define DEADKEY_GRAVE_ACCENT	KEY_7 + ALTGR_MASK
+#define DEADKEY_DIAERESIS	KEY_LEFT_BRACE + SHIFT_MASK
+#define DEADKEY_TILDE		KEY_2 + ALTGR_MASK
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_SLASH				// 33 !
+#define ASCII_22	KEY_3					// 34 "
+#define ASCII_23	KEY_3 + ALTGR_MASK			// 35 #
+#define ASCII_24	KEY_RIGHT_BRACE				// 36 $
+#define ASCII_25	KEY_QUOTE + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_1					// 38 &
+#define ASCII_27	KEY_4					// 39 '  
+#define ASCII_28	KEY_5					// 40 ( 
+#define ASCII_29	KEY_MINUS				// 41 )
+#define ASCII_2A	KEY_BACKSLASH				// 42 *
+#define ASCII_2B	KEY_EQUAL + SHIFT_MASK			// 43 +
+#define ASCII_2C	KEY_M					// 44 ,
+#define ASCII_2D	KEY_6					// 45 -
+#define ASCII_2E	KEY_COMMA + SHIFT_MASK			// 46 .
+#define ASCII_2F	KEY_PERIOD + SHIFT_MASK			// 47 /
+#define ASCII_30	KEY_0 + SHIFT_MASK			// 48 0
+#define ASCII_31	KEY_1 + SHIFT_MASK			// 49 1
+#define ASCII_32	KEY_2 + SHIFT_MASK			// 50 2
+#define ASCII_33	KEY_3 + SHIFT_MASK			// 51 3
+#define ASCII_34	KEY_4 + SHIFT_MASK			// 52 4
+#define ASCII_35	KEY_5 + SHIFT_MASK			// 53 5
+#define ASCII_36	KEY_6 + SHIFT_MASK			// 54 6
+#define ASCII_37	KEY_7 + SHIFT_MASK			// 55 7
+#define ASCII_38	KEY_8 + SHIFT_MASK			// 55 8
+#define ASCII_39	KEY_9 + SHIFT_MASK			// 57 9
+#define ASCII_3A	KEY_PERIOD				// 58 :
+#define ASCII_3B	KEY_COMMA				// 59 ;
+#define ASCII_3C	KEY_NON_US_100				// 60 <
+#define ASCII_3D	KEY_EQUAL				// 61 =
+#define ASCII_3E	KEY_NON_US_100 + SHIFT_MASK		// 62 >
+#define ASCII_3F	KEY_M + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_0 + ALTGR_MASK			// 64 @
+#define ASCII_41	KEY_Q + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_SEMICOLON + SHIFT_MASK		// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_A + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_Z + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Y + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_W + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_5 + ALTGR_MASK			// 91 [
+#define ASCII_5C	KEY_8 + ALTGR_MASK			// 92 
+#define ASCII_5D	KEY_MINUS + ALTGR_MASK			// 93 ]
+#define ASCII_5E	KEY_9 + ALTGR_MASK			// 94 ^
+#define ASCII_5F	KEY_8					// 95 _
+#define ASCII_60	GRAVE_ACCENT_BITS + KEY_SPACE		// 96 `
+#define ASCII_61	KEY_Q					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_SEMICOLON				// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_A					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_Z					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Y					// 121 y
+#define ASCII_7A	KEY_W					// 122 z
+#define ASCII_7B	KEY_4 + ALTGR_MASK			// 123 {
+#define ASCII_7C	KEY_6 + ALTGR_MASK			// 124 |
+#define ASCII_7D	KEY_EQUAL + ALTGR_MASK			// 125 }
+#define ASCII_7E	TILDE_BITS + KEY_SPACE			// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	0					// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	0					// 162 ¢     Cent SIGN
+#define ISO_8859_1_A3	KEY_RIGHT_BRACE + SHIFT_MASK		// 163 £     Pound Sign
+#define ISO_8859_1_A4	KEY_RIGHT_BRACE + ALTGR_MASK		// 164 ¤     Currency or Euro Sign
+#define ISO_8859_1_A5	0					// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	0					// 166 ¦     BROKEN BAR
+#define ISO_8859_1_A7	KEY_SLASH + SHIFT_MASK			// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	DIAERESIS_BITS + KEY_SPACE		// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	0					// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	0					// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	0					// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	0					// 172 ¬     NOT SIGN
+#define ISO_8859_1_AD	0					// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	0					// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0					// 175 ¯     MACRON
+#define ISO_8859_1_B0	KEY_MINUS + SHIFT_MASK			// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	0					// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	KEY_TILDE				// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	0					// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	0					// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	KEY_BACKSLASH + SHIFT_MASK		// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	0					// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	0					// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	0					// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	0					// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	0					// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	0					// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	0					// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	0					// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	0					// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	GRAVE_ACCENT_BITS + KEY_Q + SHIFT_MASK	// 192 À     A GRAVE
+#define ISO_8859_1_C1	0					// 193 Á     A ACUTE
+#define ISO_8859_1_C2	CIRCUMFLEX_BITS	+ KEY_Q + SHIFT_MASK	// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	TILDE_BITS + KEY_Q + SHIFT_MASK		// 195 Ã     A TILDE
+#define ISO_8859_1_C4	DIAERESIS_BITS + KEY_Q + SHIFT_MASK	// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	0					// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	0					// 198 Æ     AE
+#define ISO_8859_1_C7	0					// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 200 È     E GRAVE
+#define ISO_8859_1_C9	0					// 201 É     E ACUTE
+#define ISO_8859_1_CA	CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK	// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	DIAERESIS_BITS + KEY_E + SHIFT_MASK	// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	0					// 205 Í     I ACUTE
+#define ISO_8859_1_CE	CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK	// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	DIAERESIS_BITS + KEY_I + SHIFT_MASK	// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	0					// 208 Ð     ETH
+#define ISO_8859_1_D1	TILDE_BITS + KEY_N + SHIFT_MASK		// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	0					// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK	// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	TILDE_BITS + KEY_O + SHIFT_MASK		// 213 Õ     O TILDE
+#define ISO_8859_1_D6	DIAERESIS_BITS + KEY_O + SHIFT_MASK	// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	0					// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	0					// 216 Ø     O STROKE
+#define ISO_8859_1_D9	GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	0					// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK	// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	DIAERESIS_BITS + KEY_U			// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	0					// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	0					// 222 Þ     THORN
+#define ISO_8859_1_DF	0					// 223 ß     SHARP S
+#define ISO_8859_1_E0	KEY_0					// 224 à     a GRAVE
+#define ISO_8859_1_E1	0					// 225 á     a ACUTE
+#define ISO_8859_1_E2	CIRCUMFLEX_BITS + KEY_Q			// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	TILDE_BITS + KEY_Q			// 227 ã     a TILDE
+#define ISO_8859_1_E4	DIAERESIS_BITS + KEY_Q			// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	0					// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	0					// 230 æ     ae
+#define ISO_8859_1_E7	KEY_9					// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	KEY_7					// 232 è     e GRAVE
+#define ISO_8859_1_E9	KEY_2					// 233 é     e ACUTE
+#define ISO_8859_1_EA	CIRCUMFLEX_BITS + KEY_E			// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	DIAERESIS_BITS + KEY_E			// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	0					// 237 í     i ACUTE
+#define ISO_8859_1_EE	CIRCUMFLEX_BITS + KEY_I			// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	DIAERESIS_BITS + KEY_I			// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	0					// 240 ð     ETH
+#define ISO_8859_1_F1	TILDE_BITS + KEY_N			// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	0					// 243 ó     o ACUTE
+#define ISO_8859_1_F4	CIRCUMFLEX_BITS + KEY_O			// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	TILDE_BITS + KEY_O			// 245 õ     o TILDE
+#define ISO_8859_1_F6	DIAERESIS_BITS + KEY_O			// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	0					// 248 ø     o STROKE
+#define ISO_8859_1_F9	KEY_SEMICOLON				// 249 ù     u GRAVE
+#define ISO_8859_1_FA	0					// 250 ú     u ACUTE
+#define ISO_8859_1_FB	CIRCUMFLEX_BITS + KEY_U			// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	DIAERESIS_BITS + KEY_U			// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	0					// 253 ý     y ACUTE
+#define ISO_8859_1_FE	0					// 254 þ     THORN
+#define ISO_8859_1_FF	DIAERESIS_BITS + KEY_Y			// 255 ÿ     y DIAERESIS
+#define UNICODE_20AC	KEY_E + ALTGR_MASK			//     €     Euro Sign
+// not yet implemented
+#define UNICODE_EXTRA00	0x20AC
+#define KEYCODE_EXTRA00	KEY_E + ALTGR_MASK			// 20AC €    Euro Sign
+
+#endif // LAYOUT_FRENCH
+
+
+
+
+
+#ifdef LAYOUT_DANISH
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define DEADKEYS_MASK		0x0700
+#define	CIRCUMFLEX_BITS		0x0100
+#define ACUTE_ACCENT_BITS	0x0200
+#define GRAVE_ACCENT_BITS	0x0300
+#define TILDE_BITS		0x0400
+#define DIAERESIS_BITS		0x0500
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_CIRCUMFLEX	KEY_RIGHT_BRACE + SHIFT_MASK
+#define DEADKEY_ACUTE_ACCENT	KEY_EQUAL
+#define DEADKEY_GRAVE_ACCENT	KEY_EQUAL + SHIFT_MASK
+#define DEADKEY_TILDE		KEY_RIGHT_BRACE + ALTGR_MASK
+#define DEADKEY_DIAERESIS	KEY_RIGHT_BRACE
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_1 + SHIFT_MASK			// 33 !
+#define ASCII_22	KEY_2 + SHIFT_MASK			// 34 "
+#define ASCII_23	KEY_3 + SHIFT_MASK			// 35 #
+#define ASCII_24	KEY_4 + ALTGR_MASK			// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_6 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_BACKSLASH				// 39 '  
+#define ASCII_28	KEY_8 + SHIFT_MASK			// 40 ( 
+#define ASCII_29	KEY_9 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_BACKSLASH + SHIFT_MASK		// 42 *
+#define ASCII_2B	KEY_MINUS				// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_SLASH				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_7 + SHIFT_MASK			// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_PERIOD + SHIFT_MASK			// 58 :
+#define ASCII_3B	KEY_COMMA + SHIFT_MASK			// 59 ;
+#define ASCII_3C	KEY_NON_US_100				// 60 <
+#define ASCII_3D	KEY_0 + SHIFT_MASK			// 61 =
+#define ASCII_3E	KEY_NON_US_100 + SHIFT_MASK		// 62 >
+#define ASCII_3F	KEY_MINUS + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_2 + ALTGR_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Y + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Z + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_8 + ALTGR_MASK			// 91 [
+#define ASCII_5C	KEY_NON_US_100 + ALTGR_MASK		// 92 
+#define ASCII_5D	KEY_9 + ALTGR_MASK			// 93 ]
+#define ASCII_5E	CIRCUMFLEX_BITS + KEY_SPACE		// 94 ^
+#define ASCII_5F	KEY_SLASH + SHIFT_MASK			// 95 _
+#define ASCII_60	GRAVE_ACCENT_BITS + KEY_SPACE		// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Y					// 121 y
+#define ASCII_7A	KEY_Z					// 122 z
+#define ASCII_7B	KEY_7 + ALTGR_MASK			// 123 {
+#define ASCII_7C	KEY_EQUAL + ALTGR_MASK			// 124 |
+#define ASCII_7D	KEY_0 + ALTGR_MASK			// 125 }
+#define ASCII_7E	TILDE_BITS + KEY_SPACE			// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	0					// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	0					// 162 ¢     Cent SIGN
+#define ISO_8859_1_A3	KEY_3 + ALTGR_MASK			// 163 £     Pound Sign
+#define ISO_8859_1_A4	KEY_4 + SHIFT_MASK			// 164 ¤     Currency Sign
+#define ISO_8859_1_A5	0					// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	0					// 166 ¦     BROKEN BAR
+#define ISO_8859_1_A7	KEY_TILDE + SHIFT_MASK			// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	DIAERESIS_BITS + KEY_SPACE		// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	0					// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	0					// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	KEY_4					// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	0					// 172 ¬     NOT SIGN
+#define ISO_8859_1_AD	0					// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	0					// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0					// 175 ¯     MACRON
+#define ISO_8859_1_B0	0					// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	0					// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	0					// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	0					// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	ACUTE_ACCENT_BITS + KEY_SPACE		// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	KEY_M + ALTGR_MASK			// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	0					// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	0					// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	0					// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	0					// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	0					// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	0					// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	KEY_TILDE				// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	0					// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	0					// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 192 À     A GRAVE
+#define ISO_8859_1_C1	ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 193 Á     A ACUTE
+#define ISO_8859_1_C2	CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK	// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	TILDE_BITS + KEY_A + SHIFT_MASK		// 195 Ã     A TILDE
+#define ISO_8859_1_C4	DIAERESIS_BITS + KEY_A + SHIFT_MASK	// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	KEY_LEFT_BRACE + SHIFT_MASK		// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	KEY_SEMICOLON + SHIFT_MASK		// 198 Æ     AE
+#define ISO_8859_1_C7	0					// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 200 È     E GRAVE
+#define ISO_8859_1_C9	ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 201 É     E ACUTE
+#define ISO_8859_1_CA	CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK	// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	DIAERESIS_BITS + KEY_E + SHIFT_MASK	// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 205 Í     I ACUTE
+#define ISO_8859_1_CE	CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK	// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	DIAERESIS_BITS + KEY_I + SHIFT_MASK	// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	KEY_D + ALTGR_MASK + SHIFT_MASK		// 208 Ð     ETH
+#define ISO_8859_1_D1	TILDE_BITS + KEY_N + SHIFT_MASK		// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK	// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	TILDE_BITS + KEY_O + SHIFT_MASK		// 213 Õ     O TILDE
+#define ISO_8859_1_D6	DIAERESIS_BITS + KEY_O + SHIFT_MASK	// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	0					// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	KEY_QUOTE + SHIFT_MASK			// 216 Ø     O STROKE
+#define ISO_8859_1_D9	GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK	// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	DIAERESIS_BITS + KEY_U + SHIFT_MASK	// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK	// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	KEY_T + ALTGR_MASK + SHIFT_MASK		// 222 Þ     THORN
+#define ISO_8859_1_DF	KEY_S + ALTGR_MASK			// 223 ß     SHARP S
+#define ISO_8859_1_E0	GRAVE_ACCENT_BITS + KEY_A		// 224 à     a GRAVE
+#define ISO_8859_1_E1	ACUTE_ACCENT_BITS + KEY_A		// 225 á     a ACUTE
+#define ISO_8859_1_E2	CIRCUMFLEX_BITS + KEY_A			// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	TILDE_BITS + KEY_A			// 227 ã     a TILDE
+#define ISO_8859_1_E4	DIAERESIS_BITS + KEY_A			// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	KEY_LEFT_BRACE				// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	KEY_SEMICOLON				// 230 æ     ae
+#define ISO_8859_1_E7	0					// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	GRAVE_ACCENT_BITS + KEY_E		// 232 è     e GRAVE
+#define ISO_8859_1_E9	ACUTE_ACCENT_BITS + KEY_E		// 233 é     e ACUTE
+#define ISO_8859_1_EA	CIRCUMFLEX_BITS + KEY_E			// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	DIAERESIS_BITS + KEY_E			// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	ACUTE_ACCENT_BITS + KEY_I		// 237 í     i ACUTE
+#define ISO_8859_1_EE	CIRCUMFLEX_BITS + KEY_I			// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	DIAERESIS_BITS + KEY_I			// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	KEY_D + ALTGR_MASK			// 240 ð     ETH
+#define ISO_8859_1_F1	TILDE_BITS + KEY_N			// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	ACUTE_ACCENT_BITS + KEY_O		// 243 ó     o ACUTE
+#define ISO_8859_1_F4	CIRCUMFLEX_BITS + KEY_O			// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	TILDE_BITS + KEY_O			// 245 õ     o TILDE
+#define ISO_8859_1_F6	DIAERESIS_BITS + KEY_O			// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	KEY_QUOTE				// 248 ø     o STROKE
+#define ISO_8859_1_F9	GRAVE_ACCENT_BITS + KEY_U		// 249 ù     u GRAVE
+#define ISO_8859_1_FA	ACUTE_ACCENT_BITS + KEY_U		// 250 ú     u ACUTE
+#define ISO_8859_1_FB	CIRCUMFLEX_BITS + KEY_U			// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	DIAERESIS_BITS + KEY_U			// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	ACUTE_ACCENT_BITS + KEY_Y		// 253 ý     y ACUTE
+#define ISO_8859_1_FE	KEY_T + ALTGR_MASK			// 254 þ     THORN
+#define ISO_8859_1_FF	DIAERESIS_BITS + KEY_Y			// 255 ÿ     y DIAERESIS
+#define UNICODE_20AC	KEY_E + ALTGR_MASK			//     €     Euro Sign
+// not yet implemented
+#define UNICODE_EXTRA00	0x20AC
+#define KEYCODE_EXTRA00	KEY_E + ALTGR_MASK			// 20AC €    Euro Sign
+
+#endif // LAYOUT_DANISH
+
+
+
+
+
+#ifdef LAYOUT_NORWEGIAN
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define DEADKEYS_MASK		0x0700
+#define	CIRCUMFLEX_BITS		0x0100
+#define ACUTE_ACCENT_BITS	0x0200
+#define GRAVE_ACCENT_BITS	0x0300
+#define TILDE_BITS		0x0400
+#define DIAERESIS_BITS		0x0500
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_CIRCUMFLEX	KEY_RIGHT_BRACE + SHIFT_MASK
+#define DEADKEY_ACUTE_ACCENT	KEY_EQUAL + ALTGR_MASK
+#define DEADKEY_GRAVE_ACCENT	KEY_EQUAL + SHIFT_MASK
+#define DEADKEY_TILDE		KEY_RIGHT_BRACE + ALTGR_MASK
+#define DEADKEY_DIAERESIS	KEY_RIGHT_BRACE
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_1 + SHIFT_MASK			// 33 !
+#define ASCII_22	KEY_2 + SHIFT_MASK			// 34 "
+#define ASCII_23	KEY_3 + SHIFT_MASK			// 35 #
+#define ASCII_24	KEY_4 + ALTGR_MASK			// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_6 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_BACKSLASH				// 39 '  
+#define ASCII_28	KEY_8 + SHIFT_MASK			// 40 ( 
+#define ASCII_29	KEY_9 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_BACKSLASH + SHIFT_MASK		// 42 *
+#define ASCII_2B	KEY_MINUS				// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_SLASH				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_7 + SHIFT_MASK			// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_PERIOD + SHIFT_MASK			// 58 :
+#define ASCII_3B	KEY_COMMA + SHIFT_MASK			// 59 ;
+#define ASCII_3C	KEY_NON_US_100				// 60 <
+#define ASCII_3D	KEY_0 + SHIFT_MASK			// 61 =
+#define ASCII_3E	KEY_NON_US_100 + SHIFT_MASK		// 62 >
+#define ASCII_3F	KEY_MINUS + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_2 + ALTGR_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Y + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Z + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_8 + ALTGR_MASK			// 91 [
+#define ASCII_5C	KEY_EQUAL				// 92 
+#define ASCII_5D	KEY_9 + ALTGR_MASK			// 93 ]
+#define ASCII_5E	CIRCUMFLEX_BITS + KEY_SPACE		// 94 ^
+#define ASCII_5F	KEY_SLASH + SHIFT_MASK			// 95 _
+#define ASCII_60	GRAVE_ACCENT_BITS + KEY_SPACE		// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Y					// 121 y
+#define ASCII_7A	KEY_Z					// 122 z
+#define ASCII_7B	KEY_7 + ALTGR_MASK			// 123 {
+#define ASCII_7C	KEY_TILDE				// 124 |
+#define ASCII_7D	KEY_0 + ALTGR_MASK			// 125 }
+#define ASCII_7E	TILDE_BITS + KEY_SPACE			// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	0					// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	0					// 162 ¢     Cent SIGN
+#define ISO_8859_1_A3	KEY_3 + ALTGR_MASK			// 163 £     Pound Sign
+#define ISO_8859_1_A4	KEY_4 + SHIFT_MASK			// 164 ¤     Currency Sign
+#define ISO_8859_1_A5	0					// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	0					// 166 ¦     BROKEN BAR
+#define ISO_8859_1_A7	KEY_TILDE + SHIFT_MASK			// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	DIAERESIS_BITS + KEY_SPACE		// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	0					// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	0					// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	KEY_4					// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	0					// 172 ¬     NOT SIGN
+#define ISO_8859_1_AD	0					// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	0					// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0					// 175 ¯     MACRON
+#define ISO_8859_1_B0	0					// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	0					// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	0					// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	0					// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	ACUTE_ACCENT_BITS + KEY_SPACE		// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	KEY_M + ALTGR_MASK			// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	0					// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	0					// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	0					// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	0					// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	0					// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	0					// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	KEY_TILDE				// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	0					// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	0					// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 192 À     A GRAVE
+#define ISO_8859_1_C1	ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 193 Á     A ACUTE
+#define ISO_8859_1_C2	CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK	// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	TILDE_BITS + KEY_A + SHIFT_MASK		// 195 Ã     A TILDE
+#define ISO_8859_1_C4	DIAERESIS_BITS + KEY_A + SHIFT_MASK	// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	KEY_LEFT_BRACE + SHIFT_MASK		// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	KEY_QUOTE + SHIFT_MASK			// 198 Æ     AE
+#define ISO_8859_1_C7	0					// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 200 È     E GRAVE
+#define ISO_8859_1_C9	ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 201 É     E ACUTE
+#define ISO_8859_1_CA	CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK	// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	DIAERESIS_BITS + KEY_E + SHIFT_MASK	// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 205 Í     I ACUTE
+#define ISO_8859_1_CE	CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK	// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	DIAERESIS_BITS + KEY_I + SHIFT_MASK	// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	KEY_D + ALTGR_MASK + SHIFT_MASK		// 208 Ð     ETH
+#define ISO_8859_1_D1	TILDE_BITS + KEY_N + SHIFT_MASK		// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK	// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	TILDE_BITS + KEY_O + SHIFT_MASK		// 213 Õ     O TILDE
+#define ISO_8859_1_D6	DIAERESIS_BITS + KEY_O + SHIFT_MASK	// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	0					// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	KEY_SEMICOLON + SHIFT_MASK		// 216 Ø     O STROKE
+#define ISO_8859_1_D9	GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK	// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	DIAERESIS_BITS + KEY_U + SHIFT_MASK	// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK	// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	KEY_T + ALTGR_MASK + SHIFT_MASK		// 222 Þ     THORN
+#define ISO_8859_1_DF	KEY_S + ALTGR_MASK			// 223 ß     SHARP S
+#define ISO_8859_1_E0	GRAVE_ACCENT_BITS + KEY_A		// 224 à     a GRAVE
+#define ISO_8859_1_E1	ACUTE_ACCENT_BITS + KEY_A		// 225 á     a ACUTE
+#define ISO_8859_1_E2	CIRCUMFLEX_BITS + KEY_A			// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	TILDE_BITS + KEY_A			// 227 ã     a TILDE
+#define ISO_8859_1_E4	DIAERESIS_BITS + KEY_A			// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	KEY_LEFT_BRACE				// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	KEY_QUOTE				// 230 æ     ae
+#define ISO_8859_1_E7	0					// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	GRAVE_ACCENT_BITS + KEY_E		// 232 è     e GRAVE
+#define ISO_8859_1_E9	ACUTE_ACCENT_BITS + KEY_E		// 233 é     e ACUTE
+#define ISO_8859_1_EA	CIRCUMFLEX_BITS + KEY_E			// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	DIAERESIS_BITS + KEY_E			// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	ACUTE_ACCENT_BITS + KEY_I		// 237 í     i ACUTE
+#define ISO_8859_1_EE	CIRCUMFLEX_BITS + KEY_I			// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	DIAERESIS_BITS + KEY_I			// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	KEY_D + ALTGR_MASK			// 240 ð     ETH
+#define ISO_8859_1_F1	TILDE_BITS + KEY_N			// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	ACUTE_ACCENT_BITS + KEY_O		// 243 ó     o ACUTE
+#define ISO_8859_1_F4	CIRCUMFLEX_BITS + KEY_O			// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	TILDE_BITS + KEY_O			// 245 õ     o TILDE
+#define ISO_8859_1_F6	DIAERESIS_BITS + KEY_O			// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	KEY_SEMICOLON				// 248 ø     o STROKE
+#define ISO_8859_1_F9	GRAVE_ACCENT_BITS + KEY_U		// 249 ù     u GRAVE
+#define ISO_8859_1_FA	ACUTE_ACCENT_BITS + KEY_U		// 250 ú     u ACUTE
+#define ISO_8859_1_FB	CIRCUMFLEX_BITS + KEY_U			// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	DIAERESIS_BITS + KEY_U			// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	ACUTE_ACCENT_BITS + KEY_Y		// 253 ý     y ACUTE
+#define ISO_8859_1_FE	KEY_T + ALTGR_MASK			// 254 þ     THORN
+#define ISO_8859_1_FF	DIAERESIS_BITS + KEY_Y			// 255 ÿ     y DIAERESIS
+#define UNICODE_20AC	KEY_E + ALTGR_MASK			//     €     Euro Sign
+// not yet implemented
+#define UNICODE_EXTRA00	0x20AC
+#define KEYCODE_EXTRA00	KEY_E + ALTGR_MASK			// 20AC €    Euro Sign
+
+#endif // LAYOUT_NORWEGIAN
+
+
+
+
+
+
+#ifdef LAYOUT_SWEDISH
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define DEADKEYS_MASK		0x0700
+#define	CIRCUMFLEX_BITS		0x0100
+#define ACUTE_ACCENT_BITS	0x0200
+#define GRAVE_ACCENT_BITS	0x0300
+#define TILDE_BITS		0x0400
+#define DIAERESIS_BITS		0x0500
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_CIRCUMFLEX	KEY_RIGHT_BRACE + SHIFT_MASK
+#define DEADKEY_ACUTE_ACCENT	KEY_EQUAL
+#define DEADKEY_GRAVE_ACCENT	KEY_EQUAL + SHIFT_MASK
+#define DEADKEY_TILDE		KEY_RIGHT_BRACE + ALTGR_MASK
+#define DEADKEY_DIAERESIS	KEY_RIGHT_BRACE
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_1 + SHIFT_MASK			// 33 !
+#define ASCII_22	KEY_2 + SHIFT_MASK			// 34 "
+#define ASCII_23	KEY_3 + SHIFT_MASK			// 35 #
+#define ASCII_24	KEY_4 + ALTGR_MASK			// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_6 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_BACKSLASH				// 39 '  
+#define ASCII_28	KEY_8 + SHIFT_MASK			// 40 ( 
+#define ASCII_29	KEY_9 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_BACKSLASH + SHIFT_MASK		// 42 *
+#define ASCII_2B	KEY_MINUS				// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_SLASH				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_7 + SHIFT_MASK			// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_PERIOD + SHIFT_MASK			// 58 :
+#define ASCII_3B	KEY_COMMA + SHIFT_MASK			// 59 ;
+#define ASCII_3C	KEY_NON_US_100				// 60 <
+#define ASCII_3D	KEY_0 + SHIFT_MASK			// 61 =
+#define ASCII_3E	KEY_NON_US_100 + SHIFT_MASK		// 62 >
+#define ASCII_3F	KEY_MINUS + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_2 + ALTGR_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Y + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Z + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_8 + ALTGR_MASK			// 91 [
+#define ASCII_5C	KEY_MINUS + ALTGR_MASK			// 92 
+#define ASCII_5D	KEY_9 + ALTGR_MASK			// 93 ]
+#define ASCII_5E	CIRCUMFLEX_BITS + KEY_SPACE		// 94 ^
+#define ASCII_5F	KEY_SLASH + SHIFT_MASK			// 95 _
+#define ASCII_60	GRAVE_ACCENT_BITS + KEY_SPACE		// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Y					// 121 y
+#define ASCII_7A	KEY_Z					// 122 z
+#define ASCII_7B	KEY_7 + ALTGR_MASK			// 123 {
+#define ASCII_7C	KEY_NON_US_100 + ALTGR_MASK		// 124 |
+#define ASCII_7D	KEY_0 + ALTGR_MASK			// 125 }
+#define ASCII_7E	TILDE_BITS + KEY_SPACE			// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	0					// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	0					// 162 ¢     Cent SIGN
+#define ISO_8859_1_A3	KEY_3 + ALTGR_MASK			// 163 £     Pound Sign
+#define ISO_8859_1_A4	KEY_4 + SHIFT_MASK			// 164 ¤     Currency Sign
+#define ISO_8859_1_A5	0					// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	0					// 166 ¦     BROKEN BAR
+#define ISO_8859_1_A7	KEY_TILDE				// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	DIAERESIS_BITS + KEY_SPACE		// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	0					// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	0					// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	KEY_4					// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	0					// 172 ¬     NOT SIGN
+#define ISO_8859_1_AD	0					// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	0					// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0					// 175 ¯     MACRON
+#define ISO_8859_1_B0	0					// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	0					// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	0					// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	0					// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	ACUTE_ACCENT_BITS + KEY_SPACE		// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	KEY_M + ALTGR_MASK			// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	0					// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	0					// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	0					// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	0					// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	0					// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	0					// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	KEY_TILDE + SHIFT_MASK			// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	0					// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	0					// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 192 À     A GRAVE
+#define ISO_8859_1_C1	ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 193 Á     A ACUTE
+#define ISO_8859_1_C2	CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK	// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	TILDE_BITS + KEY_A + SHIFT_MASK		// 195 Ã     A TILDE
+#define ISO_8859_1_C4	KEY_QUOTE + SHIFT_MASK			// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	KEY_LEFT_BRACE + SHIFT_MASK		// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	0					// 198 Æ     AE
+#define ISO_8859_1_C7	0					// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 200 È     E GRAVE
+#define ISO_8859_1_C9	ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 201 É     E ACUTE
+#define ISO_8859_1_CA	CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK	// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	DIAERESIS_BITS + KEY_E + SHIFT_MASK	// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 205 Í     I ACUTE
+#define ISO_8859_1_CE	CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK	// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	DIAERESIS_BITS + KEY_I + SHIFT_MASK	// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	KEY_D + ALTGR_MASK + SHIFT_MASK		// 208 Ð     ETH
+#define ISO_8859_1_D1	TILDE_BITS + KEY_N + SHIFT_MASK		// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK	// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	TILDE_BITS + KEY_O + SHIFT_MASK		// 213 Õ     O TILDE
+#define ISO_8859_1_D6	KEY_SEMICOLON + SHIFT_MASK		// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	0					// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	0					// 216 Ø     O STROKE
+#define ISO_8859_1_D9	GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK	// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	DIAERESIS_BITS + KEY_U + SHIFT_MASK	// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK	// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	KEY_T + ALTGR_MASK + SHIFT_MASK		// 222 Þ     THORN
+#define ISO_8859_1_DF	KEY_S + ALTGR_MASK			// 223 ß     SHARP S
+#define ISO_8859_1_E0	GRAVE_ACCENT_BITS + KEY_A		// 224 à     a GRAVE
+#define ISO_8859_1_E1	ACUTE_ACCENT_BITS + KEY_A		// 225 á     a ACUTE
+#define ISO_8859_1_E2	CIRCUMFLEX_BITS + KEY_A			// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	TILDE_BITS + KEY_A			// 227 ã     a TILDE
+#define ISO_8859_1_E4	KEY_QUOTE				// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	KEY_LEFT_BRACE				// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	0					// 230 æ     ae
+#define ISO_8859_1_E7	0					// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	GRAVE_ACCENT_BITS + KEY_E		// 232 è     e GRAVE
+#define ISO_8859_1_E9	ACUTE_ACCENT_BITS + KEY_E		// 233 é     e ACUTE
+#define ISO_8859_1_EA	CIRCUMFLEX_BITS + KEY_E			// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	DIAERESIS_BITS + KEY_E			// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	ACUTE_ACCENT_BITS + KEY_I		// 237 í     i ACUTE
+#define ISO_8859_1_EE	CIRCUMFLEX_BITS + KEY_I			// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	DIAERESIS_BITS + KEY_I			// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	KEY_D + ALTGR_MASK			// 240 ð     ETH
+#define ISO_8859_1_F1	TILDE_BITS + KEY_N			// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	ACUTE_ACCENT_BITS + KEY_O		// 243 ó     o ACUTE
+#define ISO_8859_1_F4	CIRCUMFLEX_BITS + KEY_O			// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	TILDE_BITS + KEY_O			// 245 õ     o TILDE
+#define ISO_8859_1_F6	KEY_SEMICOLON				// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	0					// 248 ø     o STROKE
+#define ISO_8859_1_F9	GRAVE_ACCENT_BITS + KEY_U		// 249 ù     u GRAVE
+#define ISO_8859_1_FA	ACUTE_ACCENT_BITS + KEY_U		// 250 ú     u ACUTE
+#define ISO_8859_1_FB	CIRCUMFLEX_BITS + KEY_U			// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	DIAERESIS_BITS + KEY_U			// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	ACUTE_ACCENT_BITS + KEY_Y		// 253 ý     y ACUTE
+#define ISO_8859_1_FE	KEY_T + ALTGR_MASK			// 254 þ     THORN
+#define ISO_8859_1_FF	DIAERESIS_BITS + KEY_Y			// 255 ÿ     y DIAERESIS
+#define UNICODE_20AC	KEY_E + ALTGR_MASK			//     €     Euro Sign
+// not yet implemented
+#define UNICODE_EXTRA00	0x20AC
+#define KEYCODE_EXTRA00	KEY_E + ALTGR_MASK			// 20AC €    Euro Sign
+
+#endif // LAYOUT_SWEDISH
+
+
+
+
+
+
+#ifdef LAYOUT_SPANISH
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define DEADKEYS_MASK		0x0700
+#define	CIRCUMFLEX_BITS		0x0100
+#define ACUTE_ACCENT_BITS	0x0200
+#define GRAVE_ACCENT_BITS	0x0300
+#define TILDE_BITS		0x0400
+#define DIAERESIS_BITS		0x0500
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_CIRCUMFLEX	KEY_LEFT_BRACE + SHIFT_MASK
+#define DEADKEY_ACUTE_ACCENT	KEY_QUOTE
+#define DEADKEY_GRAVE_ACCENT	KEY_LEFT_BRACE
+#define DEADKEY_TILDE		KEY_4 + ALTGR_MASK
+#define DEADKEY_DIAERESIS	KEY_QUOTE + SHIFT_MASK
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_1 + SHIFT_MASK			// 33 !
+#define ASCII_22	KEY_2 + SHIFT_MASK			// 34 "
+#define ASCII_23	KEY_3 + ALTGR_MASK			// 35 #
+#define ASCII_24	KEY_4 + SHIFT_MASK			// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_6 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_MINUS				// 39 '  
+#define ASCII_28	KEY_8 + SHIFT_MASK			// 40 ( 
+#define ASCII_29	KEY_9 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_RIGHT_BRACE + SHIFT_MASK		// 42 *
+#define ASCII_2B	KEY_RIGHT_BRACE				// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_SLASH				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_7 + SHIFT_MASK			// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_PERIOD + SHIFT_MASK			// 58 :
+#define ASCII_3B	KEY_COMMA + SHIFT_MASK			// 59 ;
+#define ASCII_3C	KEY_NON_US_100				// 60 <
+#define ASCII_3D	KEY_0 + SHIFT_MASK			// 61 =
+#define ASCII_3E	KEY_NON_US_100 + SHIFT_MASK		// 62 >
+#define ASCII_3F	KEY_MINUS + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_2 + ALTGR_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Y + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Z + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_LEFT_BRACE + ALTGR_MASK		// 91 [
+#define ASCII_5C	KEY_TILDE + ALTGR_MASK			// 92 
+#define ASCII_5D	KEY_RIGHT_BRACE + ALTGR_MASK		// 93 ]
+#define ASCII_5E	CIRCUMFLEX_BITS + KEY_SPACE		// 94 ^
+#define ASCII_5F	KEY_SLASH + SHIFT_MASK			// 95 _
+#define ASCII_60	GRAVE_ACCENT_BITS + KEY_SPACE		// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Y					// 121 y
+#define ASCII_7A	KEY_Z					// 122 z
+#define ASCII_7B	KEY_QUOTE + ALTGR_MASK			// 123 {
+#define ASCII_7C	KEY_1 + ALTGR_MASK			// 124 |
+#define ASCII_7D	KEY_BACKSLASH + ALTGR_MASK		// 125 }
+#define ASCII_7E	TILDE_BITS + KEY_SPACE			// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	KEY_EQUAL				// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	0					// 162 ¢     Cent SIGN
+#define ISO_8859_1_A3	0					// 163 £     Pound Sign
+#define ISO_8859_1_A4	0					// 164 ¤     Currency Sign
+#define ISO_8859_1_A5	0					// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	0					// 166 ¦     BROKEN BAR
+#define ISO_8859_1_A7	0					// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	DIAERESIS_BITS + KEY_SPACE		// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	0					// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	KEY_TILDE + SHIFT_MASK			// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	0					// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	KEY_6 + ALTGR_MASK			// 172 ¬     NOT SIGN
+#define ISO_8859_1_AD	0					// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	0					// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0					// 175 ¯     MACRON
+#define ISO_8859_1_B0	0					// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	0					// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	0					// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	0					// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	ACUTE_ACCENT_BITS + KEY_SPACE		// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	0					// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	0					// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	KEY_3 + SHIFT_MASK			// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	0					// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	KEY_TILDE				// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	0					// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	0					// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	0					// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	0					// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	KEY_EQUAL				// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 192 À     A GRAVE
+#define ISO_8859_1_C1	ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 193 Á     A ACUTE
+#define ISO_8859_1_C2	CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK	// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	TILDE_BITS + KEY_A + SHIFT_MASK		// 195 Ã     A TILDE
+#define ISO_8859_1_C4	DIAERESIS_BITS + KEY_A + SHIFT_MASK	// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	0					// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	0					// 198 Æ     AE
+#define ISO_8859_1_C7	KEY_BACKSLASH + SHIFT_MASK		// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 200 È     E GRAVE
+#define ISO_8859_1_C9	ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 201 É     E ACUTE
+#define ISO_8859_1_CA	CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK	// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	DIAERESIS_BITS + KEY_E + SHIFT_MASK	// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 205 Í     I ACUTE
+#define ISO_8859_1_CE	CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK	// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	DIAERESIS_BITS + KEY_I + SHIFT_MASK	// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	0					// 208 Ð     ETH
+#define ISO_8859_1_D1	KEY_SEMICOLON + SHIFT_MASK		// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK	// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	TILDE_BITS + KEY_O + SHIFT_MASK		// 213 Õ     O TILDE
+#define ISO_8859_1_D6	DIAERESIS_BITS + KEY_O + SHIFT_MASK	// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	0					// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	0					// 216 Ø     O STROKE
+#define ISO_8859_1_D9	GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK	// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	DIAERESIS_BITS + KEY_U + SHIFT_MASK	// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK	// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	0					// 222 Þ     THORN
+#define ISO_8859_1_DF	0					// 223 ß     SHARP S
+#define ISO_8859_1_E0	GRAVE_ACCENT_BITS + KEY_A		// 224 à     a GRAVE
+#define ISO_8859_1_E1	ACUTE_ACCENT_BITS + KEY_A		// 225 á     a ACUTE
+#define ISO_8859_1_E2	CIRCUMFLEX_BITS + KEY_A			// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	TILDE_BITS + KEY_A			// 227 ã     a TILDE
+#define ISO_8859_1_E4	DIAERESIS_BITS + KEY_A			// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	0					// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	0					// 230 æ     ae
+#define ISO_8859_1_E7	KEY_BACKSLASH				// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	GRAVE_ACCENT_BITS + KEY_E		// 232 è     e GRAVE
+#define ISO_8859_1_E9	ACUTE_ACCENT_BITS + KEY_E		// 233 é     e ACUTE
+#define ISO_8859_1_EA	CIRCUMFLEX_BITS + KEY_E			// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	DIAERESIS_BITS + KEY_E			// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	ACUTE_ACCENT_BITS + KEY_I		// 237 í     i ACUTE
+#define ISO_8859_1_EE	CIRCUMFLEX_BITS + KEY_I			// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	DIAERESIS_BITS + KEY_I			// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	0					// 240 ð     ETH
+#define ISO_8859_1_F1	KEY_SEMICOLON				// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	ACUTE_ACCENT_BITS + KEY_O		// 243 ó     o ACUTE
+#define ISO_8859_1_F4	CIRCUMFLEX_BITS + KEY_O			// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	TILDE_BITS + KEY_O			// 245 õ     o TILDE
+#define ISO_8859_1_F6	DIAERESIS_BITS + KEY_O			// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	0					// 248 ø     o STROKE
+#define ISO_8859_1_F9	GRAVE_ACCENT_BITS + KEY_U		// 249 ù     u GRAVE
+#define ISO_8859_1_FA	ACUTE_ACCENT_BITS + KEY_U		// 250 ú     u ACUTE
+#define ISO_8859_1_FB	CIRCUMFLEX_BITS + KEY_U			// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	DIAERESIS_BITS + KEY_U			// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	ACUTE_ACCENT_BITS + KEY_Y		// 253 ý     y ACUTE
+#define ISO_8859_1_FE	0					// 254 þ     THORN
+#define ISO_8859_1_FF	DIAERESIS_BITS + KEY_Y			// 255 ÿ     y DIAERESIS
+#define UNICODE_20AC	KEY_5 + ALTGR_MASK			//     €     Euro Sign
+// not yet implemented
+#define UNICODE_EXTRA00	0x20AC
+#define KEYCODE_EXTRA00	KEY_5 + ALTGR_MASK			// 20AC €    Euro Sign
+
+#endif // LAYOUT_SPANISH
+
+
+
+
+#ifdef LAYOUT_PORTUGUESE
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define DEADKEYS_MASK		0x0700
+#define	CIRCUMFLEX_BITS		0x0100
+#define ACUTE_ACCENT_BITS	0x0200
+#define GRAVE_ACCENT_BITS	0x0300
+#define TILDE_BITS		0x0400
+#define DIAERESIS_BITS		0x0500
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_CIRCUMFLEX	KEY_BACKSLASH
+#define DEADKEY_ACUTE_ACCENT	KEY_RIGHT_BRACE + SHIFT_MASK
+#define DEADKEY_GRAVE_ACCENT	KEY_RIGHT_BRACE + SHIFT_MASK
+#define DEADKEY_TILDE		KEY_BACKSLASH
+#define DEADKEY_DIAERESIS	KEY_LEFT_BRACE + SHIFT_MASK
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_1 + SHIFT_MASK			// 33 !
+#define ASCII_22	KEY_2 + SHIFT_MASK			// 34 "
+#define ASCII_23	KEY_3 + ALTGR_MASK			// 35 #
+#define ASCII_24	KEY_4 + SHIFT_MASK			// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_6 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_MINUS				// 39 '
+#define ASCII_28	KEY_8 + SHIFT_MASK			// 40 (
+#define ASCII_29	KEY_9 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_LEFT_BRACE + SHIFT_MASK		// 42 *
+#define ASCII_2B	KEY_LEFT_BRACE				// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_SLASH				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_7 + SHIFT_MASK			// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_PERIOD + SHIFT_MASK			// 58 :
+#define ASCII_3B	KEY_COMMA + SHIFT_MASK			// 59 ;
+#define ASCII_3C	KEY_NON_US_100				// 60 <
+#define ASCII_3D	KEY_0 + SHIFT_MASK			// 61 =
+#define ASCII_3E	KEY_NON_US_100 + SHIFT_MASK		// 62 >
+#define ASCII_3F	KEY_MINUS + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_2 + ALTGR_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Y + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Z + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_8 + ALTGR_MASK			// 91 [
+#define ASCII_5C	KEY_TILDE + ALTGR_MASK			// 92 
+#define ASCII_5D	KEY_9 + ALTGR_MASK			// 93 ]
+#define ASCII_5E	CIRCUMFLEX_BITS + KEY_SPACE		// 94 ^
+#define ASCII_5F	KEY_SLASH + SHIFT_MASK			// 95 _
+#define ASCII_60	GRAVE_ACCENT_BITS + KEY_SPACE		// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Y					// 121 y
+#define ASCII_7A	KEY_Z					// 122 z
+#define ASCII_7B	KEY_7 + ALTGR_MASK			// 123 {
+#define ASCII_7C	KEY_TILDE + SHIFT_MASK			// 124 |
+#define ASCII_7D	KEY_0 + ALTGR_MASK			// 125 }
+#define ASCII_7E	TILDE_BITS + KEY_SPACE			// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	0					// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	0					// 162 ¢     Cent SIGN
+#define ISO_8859_1_A3	KEY_3 + ALTGR_MASK			// 163 £     Pound Sign
+#define ISO_8859_1_A4	0					// 164 ¤     Currency Sign
+#define ISO_8859_1_A5	0					// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	0					// 166 ¦     BROKEN BAR
+#define ISO_8859_1_A7	KEY_4 + ALTGR_MASK			// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	DIAERESIS_BITS + KEY_SPACE		// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	0					// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	KEY_QUOTE + SHIFT_MASK			// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	KEY_EQUAL				// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	0					// 172 ¬     NOT SIGN
+#define ISO_8859_1_AD	0					// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	0					// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0					// 175 ¯     MACRON
+#define ISO_8859_1_B0	0					// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	0					// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	0					// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	0					// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	ACUTE_ACCENT_BITS + KEY_SPACE		// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	0					// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	0					// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	0					// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	0					// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	KEY_QUOTE				// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	KEY_EQUAL + SHIFT_MASK			// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	0					// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	0					// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	0					// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	0					// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 192 À     A GRAVE
+#define ISO_8859_1_C1	ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 193 Á     A ACUTE
+#define ISO_8859_1_C2	CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK	// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	TILDE_BITS + KEY_A + SHIFT_MASK		// 195 Ã     A TILDE
+#define ISO_8859_1_C4	DIAERESIS_BITS + KEY_A + SHIFT_MASK	// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	0					// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	0					// 198 Æ     AE
+#define ISO_8859_1_C7	KEY_SEMICOLON + SHIFT_MASK		// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 200 È     E GRAVE
+#define ISO_8859_1_C9	ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 201 É     E ACUTE
+#define ISO_8859_1_CA	CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK	// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	DIAERESIS_BITS + KEY_E + SHIFT_MASK	// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 205 Í     I ACUTE
+#define ISO_8859_1_CE	CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK	// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	DIAERESIS_BITS + KEY_I + SHIFT_MASK	// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	0					// 208 Ð     ETH
+#define ISO_8859_1_D1	TILDE_BITS + KEY_N + SHIFT_MASK		// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK	// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	TILDE_BITS + KEY_O + SHIFT_MASK		// 213 Õ     O TILDE
+#define ISO_8859_1_D6	DIAERESIS_BITS + KEY_O + SHIFT_MASK	// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	0					// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	0					// 216 Ø     O STROKE
+#define ISO_8859_1_D9	GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK	// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	DIAERESIS_BITS + KEY_U + SHIFT_MASK	// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK	// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	0					// 222 Þ     THORN
+#define ISO_8859_1_DF	0					// 223 ß     SHARP S
+#define ISO_8859_1_E0	GRAVE_ACCENT_BITS + KEY_A		// 224 à     a GRAVE
+#define ISO_8859_1_E1	ACUTE_ACCENT_BITS + KEY_A		// 225 á     a ACUTE
+#define ISO_8859_1_E2	CIRCUMFLEX_BITS + KEY_A			// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	TILDE_BITS + KEY_A			// 227 ã     a TILDE
+#define ISO_8859_1_E4	DIAERESIS_BITS + KEY_A			// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	0					// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	0					// 230 æ     ae
+#define ISO_8859_1_E7	KEY_SEMICOLON				// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	GRAVE_ACCENT_BITS + KEY_E		// 232 è     e GRAVE
+#define ISO_8859_1_E9	ACUTE_ACCENT_BITS + KEY_E		// 233 é     e ACUTE
+#define ISO_8859_1_EA	CIRCUMFLEX_BITS + KEY_E			// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	DIAERESIS_BITS + KEY_E			// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	ACUTE_ACCENT_BITS + KEY_I		// 237 í     i ACUTE
+#define ISO_8859_1_EE	CIRCUMFLEX_BITS + KEY_I			// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	DIAERESIS_BITS + KEY_I			// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	0					// 240 ð     ETH
+#define ISO_8859_1_F1	TILDE_BITS + KEY_N			// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	ACUTE_ACCENT_BITS + KEY_O		// 243 ó     o ACUTE
+#define ISO_8859_1_F4	CIRCUMFLEX_BITS + KEY_O			// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	TILDE_BITS + KEY_O			// 245 õ     o TILDE
+#define ISO_8859_1_F6	DIAERESIS_BITS + KEY_O			// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	0					// 248 ø     o STROKE
+#define ISO_8859_1_F9	GRAVE_ACCENT_BITS + KEY_U		// 249 ù     u GRAVE
+#define ISO_8859_1_FA	ACUTE_ACCENT_BITS + KEY_U		// 250 ú     u ACUTE
+#define ISO_8859_1_FB	CIRCUMFLEX_BITS + KEY_U			// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	DIAERESIS_BITS + KEY_U			// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	ACUTE_ACCENT_BITS + KEY_Y		// 253 ý     y ACUTE
+#define ISO_8859_1_FE	0					// 254 þ     THORN
+#define ISO_8859_1_FF	DIAERESIS_BITS + KEY_Y			// 255 ÿ     y DIAERESIS
+#define UNICODE_20AC	KEY_E + ALTGR_MASK			//     €     Euro Sign
+// not yet implemented
+#define UNICODE_EXTRA00	0x20AC
+#define KEYCODE_EXTRA00	KEY_E + ALTGR_MASK			// 20AC €    Euro Sign
+
+#endif // LAYOUT_PORTUGUESE
+
+
+
+
+
+
+
+#ifdef LAYOUT_ITALIAN
+
+#define SHIFT_MASK		0x40
+#define ALTGR_MASK		0x80
+#define KEYCODE_TYPE		uint8_t
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_1 + SHIFT_MASK			// 33 !
+#define ASCII_22	KEY_2 + SHIFT_MASK			// 34 "
+#define ASCII_23	KEY_QUOTE + ALTGR_MASK			// 35 #
+#define ASCII_24	KEY_4 + SHIFT_MASK			// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_6 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_MINUS				// 39 '  
+#define ASCII_28	KEY_8 + SHIFT_MASK			// 40 ( 
+#define ASCII_29	KEY_9 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_RIGHT_BRACE + SHIFT_MASK		// 42 *
+#define ASCII_2B	KEY_RIGHT_BRACE				// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_SLASH				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_7 + SHIFT_MASK			// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_PERIOD + SHIFT_MASK			// 58 :
+#define ASCII_3B	KEY_COMMA + SHIFT_MASK			// 59 ;
+#define ASCII_3C	KEY_NON_US_100				// 60 <
+#define ASCII_3D	KEY_0 + SHIFT_MASK			// 61 =
+#define ASCII_3E	KEY_NON_US_100 + SHIFT_MASK		// 62 >
+#define ASCII_3F	KEY_MINUS + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_SEMICOLON + ALTGR_MASK		// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Y + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Z + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_LEFT_BRACE + ALTGR_MASK		// 91 [
+#define ASCII_5C	KEY_TILDE				// 92 
+#define ASCII_5D	KEY_RIGHT_BRACE + ALTGR_MASK		// 93 ]
+#define ASCII_5E	KEY_EQUAL + SHIFT_MASK			// 94 ^
+#define ASCII_5F	KEY_SLASH + SHIFT_MASK			// 95 _
+#define ASCII_60	0					// 96 `  (how to type this on Italian?)
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Y					// 121 y
+#define ASCII_7A	KEY_Z					// 122 z
+#define ASCII_7B	KEY_LEFT_BRACE + SHIFT_MASK + ALTGR_MASK // 123 {
+#define ASCII_7C	KEY_TILDE + SHIFT_MASK			// 124 |
+#define ASCII_7D	KEY_RIGHT_BRACE + SHIFT_MASK + ALTGR_MASK // 125 }
+#define ASCII_7E	0					// 126 ~   (how to type this on Italian?)
+#define ASCII_7F	KEY_BACKSPACE				// 127
+
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	0					// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	0					// 162 ¢     Cent Sign
+#define ISO_8859_1_A3	KEY_3 + SHIFT_MASK			// 163 £     Pound Sign
+#define ISO_8859_1_A4	0					// 164 ¤     Currency Sign
+#define ISO_8859_1_A5	0					// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	0					// 166 ¦     BROKEN BAR
+#define ISO_8859_1_A7	KEY_BACKSLASH + SHIFT_MASK		// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	0					// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	0					// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	0					// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	0					// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	0					// 172 ¬     NOT SIGN
+#define ISO_8859_1_AD	0					// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	0					// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0					// 175 ¯     MACRON
+#define ISO_8859_1_B0	KEY_QUOTE + SHIFT_MASK			// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	0					// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	0					// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	0					// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	0					// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	0					// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	0					// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	0					// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	0					// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	0					// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	0					// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	0					// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	0					// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	0					// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	0					// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	0					// 192 À     A GRAVE
+#define ISO_8859_1_C1	0					// 193 Á     A ACUTE
+#define ISO_8859_1_C2	0					// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	0					// 195 Ã     A TILDE
+#define ISO_8859_1_C4	0					// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	0					// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	0					// 198 Æ     AE
+#define ISO_8859_1_C7	0					// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	0					// 200 È     E GRAVE
+#define ISO_8859_1_C9	0					// 201 É     E ACUTE
+#define ISO_8859_1_CA	0					// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	0					// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	0					// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	0					// 205 Í     I ACUTE
+#define ISO_8859_1_CE	0					// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	0					// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	0					// 208 Ð     ETH
+#define ISO_8859_1_D1	0					// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	0					// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	0					// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	0					// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	0					// 213 Õ     O TILDE
+#define ISO_8859_1_D6	0					// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	0					// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	0					// 216 Ø     O STROKE
+#define ISO_8859_1_D9	0					// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	0					// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	0					// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	0					// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	0					// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	0					// 222 Þ     THORN
+#define ISO_8859_1_DF	0					// 223 ß     SHARP S
+#define ISO_8859_1_E0	KEY_QUOTE				// 224 à     a GRAVE
+#define ISO_8859_1_E1	0					// 225 á     a ACUTE
+#define ISO_8859_1_E2	0					// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	0					// 227 ã     a TILDE
+#define ISO_8859_1_E4	0					// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	0					// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	0					// 230 æ     ae
+#define ISO_8859_1_E7	KEY_SEMICOLON + SHIFT_MASK		// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	KEY_LEFT_BRACE				// 232 è     e GRAVE
+#define ISO_8859_1_E9	KEY_LEFT_BRACE + SHIFT_MASK		// 233 é     e ACUTE
+#define ISO_8859_1_EA	0					// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	0					// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	KEY_EQUAL				// 236 ì     i GRAVE
+#define ISO_8859_1_ED	0					// 237 í     i ACUTE
+#define ISO_8859_1_EE	0					// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	0					// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	0					// 240 ð     ETH
+#define ISO_8859_1_F1	0					// 241 ñ     n TILDE
+#define ISO_8859_1_F2	KEY_SEMICOLON				// 242 ò     o GRAVE
+#define ISO_8859_1_F3	0					// 243 ó     o ACUTE
+#define ISO_8859_1_F4	0					// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	0					// 245 õ     o TILDE
+#define ISO_8859_1_F6	0					// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	0					// 248 ø     o STROKE
+#define ISO_8859_1_F9	KEY_BACKSLASH				// 249 ù     u GRAVE
+#define ISO_8859_1_FA	0					// 250 ú     u ACUTE
+#define ISO_8859_1_FB	0					// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	0					// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	0					// 253 ý     y ACUTE
+#define ISO_8859_1_FE	0					// 254 þ     THORN
+#define ISO_8859_1_FF	0					// 255 ÿ     y DIAERESIS
+
+#endif // LAYOUT_ITALIAN
+
+
+
+
+#ifdef LAYOUT_PORTUGUESE_BRAZILIAN
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define DEADKEYS_MASK		0x0700
+#define	CIRCUMFLEX_BITS		0x0100
+#define ACUTE_ACCENT_BITS	0x0200
+#define GRAVE_ACCENT_BITS	0x0300
+#define TILDE_BITS		0x0400
+#define DIAERESIS_BITS		0x0500
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_CIRCUMFLEX	KEY_QUOTE + SHIFT_MASK
+#define DEADKEY_ACUTE_ACCENT	KEY_LEFT_BRACE
+#define DEADKEY_GRAVE_ACCENT	KEY_LEFT_BRACE + SHIFT_MASK
+#define DEADKEY_TILDE		KEY_QUOTE
+#define DEADKEY_DIAERESIS	KEY_6 + SHIFT_MASK
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_1 + SHIFT_MASK			// 33 !
+#define ASCII_22	KEY_TILDE + SHIFT_MASK			// 34 "
+#define ASCII_23	KEY_3 + ALTGR_MASK			// 35 #
+#define ASCII_24	KEY_4 + SHIFT_MASK			// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_7 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_TILDE				// 39 '
+#define ASCII_28	KEY_9 + SHIFT_MASK			// 40 (
+#define ASCII_29	KEY_0 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_7 + SHIFT_MASK			// 42 *
+#define ASCII_2B	KEY_EQUAL + SHIFT_MASK			// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_MINUS				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_Q + ALTGR_MASK			// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_SLASH + SHIFT_MASK			// 58 :
+#define ASCII_3B	KEY_SLASH				// 59 ;
+#define ASCII_3C	KEY_COMMA + SHIFT_MASK			// 60 <
+#define ASCII_3D	KEY_EQUAL				// 61 =
+#define ASCII_3E	KEY_PERIOD + SHIFT_MASK			// 62 >
+#define ASCII_3F	KEY_W + ALTGR_MASK			// 63 ?
+#define ASCII_40	KEY_2 + SHIFT_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Y + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Z + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_RIGHT_BRACE				// 91 [
+#define ASCII_5C	KEY_NON_US_100				// 92
+#define ASCII_5D	KEY_BACKSLASH				// 93 ]
+#define ASCII_5E	CIRCUMFLEX_BITS + KEY_SPACE		// 94 ^
+#define ASCII_5F	KEY_MINUS + SHIFT_MASK			// 95 _
+#define ASCII_60	GRAVE_ACCENT_BITS + KEY_SPACE		// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Y					// 121 y
+#define ASCII_7A	KEY_Z					// 122 z
+#define ASCII_7B	KEY_RIGHT_BRACE + SHIFT_MASK		// 123 {
+#define ASCII_7C	KEY_NON_US_100 + SHIFT_MASK		// 124 |
+#define ASCII_7D	KEY_BACKSLASH + SHIFT_MASK		// 125 }
+#define ASCII_7E	TILDE_BITS + KEY_SPACE			// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	0					// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	KEY_5 + ALTGR_MASK			// 162 ¢     Cent SIGN
+#define ISO_8859_1_A3	KEY_4 + ALTGR_MASK			// 163 £     Pound Sign
+#define ISO_8859_1_A4	0					// 164 ¤     Currency Sign
+#define ISO_8859_1_A5	0					// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	0					// 166 ¦     BROKEN BAR
+#define ISO_8859_1_A7	KEY_EQUAL + ALTGR_MASK			// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	DIAERESIS_BITS + KEY_SPACE		// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	0					// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	KEY_RIGHT_BRACE + ALTGR_MASK		// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	0					// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	KEY_6 + ALTGR_MASK			// 172 ¬     NOT SIGN
+#define ISO_8859_1_AD	0					// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	0					// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0					// 175 ¯     MACRON
+#define ISO_8859_1_B0	KEY_E + ALTGR_MASK			// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	0					// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	KEY_2 + ALTGR_MASK			// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	KEY_2 + ALTGR_MASK			// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	ACUTE_ACCENT_BITS + KEY_SPACE		// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	0					// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	0					// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	0					// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	KEY_1 + ALTGR_MASK			// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	KEY_BACKSLASH + ALTGR_MASK		// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	0					// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	0					// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	0					// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	0					// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	0					// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 192 À     A GRAVE
+#define ISO_8859_1_C1	ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 193 Á     A ACUTE
+#define ISO_8859_1_C2	CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK	// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	TILDE_BITS + KEY_A + SHIFT_MASK		// 195 Ã     A TILDE
+#define ISO_8859_1_C4	DIAERESIS_BITS + KEY_A + SHIFT_MASK	// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	0					// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	0					// 198 Æ     AE
+#define ISO_8859_1_C7	0					// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 200 È     E GRAVE
+#define ISO_8859_1_C9	ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 201 É     E ACUTE
+#define ISO_8859_1_CA	CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK	// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	DIAERESIS_BITS + KEY_E + SHIFT_MASK	// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 205 Í     I ACUTE
+#define ISO_8859_1_CE	CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK	// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	DIAERESIS_BITS + KEY_I + SHIFT_MASK	// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	0					// 208 Ð     ETH
+#define ISO_8859_1_D1	TILDE_BITS + KEY_N + SHIFT_MASK		// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK	// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	TILDE_BITS + KEY_O + SHIFT_MASK		// 213 Õ     O TILDE
+#define ISO_8859_1_D6	DIAERESIS_BITS + KEY_O + SHIFT_MASK	// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	0					// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	0					// 216 Ø     O STROKE
+#define ISO_8859_1_D9	GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK	// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	DIAERESIS_BITS + KEY_U + SHIFT_MASK	// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK	// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	0					// 222 Þ     THORN
+#define ISO_8859_1_DF	0					// 223 ß     SHARP S
+#define ISO_8859_1_E0	GRAVE_ACCENT_BITS + KEY_A		// 224 à     a GRAVE
+#define ISO_8859_1_E1	ACUTE_ACCENT_BITS + KEY_A		// 225 á     a ACUTE
+#define ISO_8859_1_E2	CIRCUMFLEX_BITS + KEY_A			// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	TILDE_BITS + KEY_A			// 227 ã     a TILDE
+#define ISO_8859_1_E4	DIAERESIS_BITS + KEY_A			// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	0					// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	0					// 230 æ     ae
+#define ISO_8859_1_E7	0					// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	GRAVE_ACCENT_BITS + KEY_E		// 232 è     e GRAVE
+#define ISO_8859_1_E9	ACUTE_ACCENT_BITS + KEY_E		// 233 é     e ACUTE
+#define ISO_8859_1_EA	CIRCUMFLEX_BITS + KEY_E			// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	DIAERESIS_BITS + KEY_E			// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	ACUTE_ACCENT_BITS + KEY_I		// 237 í     i ACUTE
+#define ISO_8859_1_EE	CIRCUMFLEX_BITS + KEY_I			// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	DIAERESIS_BITS + KEY_I			// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	0					// 240 ð     ETH
+#define ISO_8859_1_F1	TILDE_BITS + KEY_N			// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	ACUTE_ACCENT_BITS + KEY_O		// 243 ó     o ACUTE
+#define ISO_8859_1_F4	CIRCUMFLEX_BITS + KEY_O			// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	TILDE_BITS + KEY_O			// 245 õ     o TILDE
+#define ISO_8859_1_F6	DIAERESIS_BITS + KEY_O			// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	0					// 248 ø     o STROKE
+#define ISO_8859_1_F9	GRAVE_ACCENT_BITS + KEY_U		// 249 ù     u GRAVE
+#define ISO_8859_1_FA	ACUTE_ACCENT_BITS + KEY_U		// 250 ú     u ACUTE
+#define ISO_8859_1_FB	CIRCUMFLEX_BITS + KEY_U			// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	DIAERESIS_BITS + KEY_U			// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	ACUTE_ACCENT_BITS + KEY_Y		// 253 ý     y ACUTE
+#define ISO_8859_1_FE	0					// 254 þ     THORN
+#define ISO_8859_1_FF	DIAERESIS_BITS + KEY_Y			// 255 ÿ     y DIAERESIS
+
+#endif // LAYOUT_PORTUGUESE_BRAZILIAN
+
+
+
+#ifdef LAYOUT_FRENCH_BELGIAN
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define DEADKEYS_MASK		0x0700
+#define	CIRCUMFLEX_BITS		0x0100
+#define GRAVE_ACCENT_BITS	0x0200
+#define DIAERESIS_BITS		0x0300
+#define TILDE_BITS		0x0400
+#define ACUTE_ACCENT_BITS	0x0500
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_CIRCUMFLEX	KEY_LEFT_BRACE
+#define DEADKEY_ACUTE_ACCENT	KEY_QUOTE + ALTGR_MASK
+#define DEADKEY_GRAVE_ACCENT	KEY_BACKSLASH + ALTGR_MASK
+#define DEADKEY_DIAERESIS	KEY_LEFT_BRACE + SHIFT_MASK
+#define DEADKEY_TILDE		KEY_SLASH + ALTGR_MASK
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_8					// 33 !
+#define ASCII_22	KEY_3					// 34 "
+#define ASCII_23	KEY_3 + ALTGR_MASK			// 35 #
+#define ASCII_24	KEY_RIGHT_BRACE				// 36 $
+#define ASCII_25	KEY_QUOTE + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_1					// 38 &
+#define ASCII_27	KEY_4					// 39 '  
+#define ASCII_28	KEY_5					// 40 ( 
+#define ASCII_29	KEY_MINUS				// 41 )
+#define ASCII_2A	KEY_RIGHT_BRACE + SHIFT_MASK		// 42 *
+#define ASCII_2B	KEY_SLASH + SHIFT_MASK			// 43 +
+#define ASCII_2C	KEY_M					// 44 ,
+#define ASCII_2D	KEY_EQUAL				// 45 -
+#define ASCII_2E	KEY_COMMA + SHIFT_MASK			// 46 .
+#define ASCII_2F	KEY_PERIOD + SHIFT_MASK			// 47 /
+#define ASCII_30	KEY_0 + SHIFT_MASK			// 48 0
+#define ASCII_31	KEY_1 + SHIFT_MASK			// 49 1
+#define ASCII_32	KEY_2 + SHIFT_MASK			// 50 2
+#define ASCII_33	KEY_3 + SHIFT_MASK			// 51 3
+#define ASCII_34	KEY_4 + SHIFT_MASK			// 52 4
+#define ASCII_35	KEY_5 + SHIFT_MASK			// 53 5
+#define ASCII_36	KEY_6 + SHIFT_MASK			// 54 6
+#define ASCII_37	KEY_7 + SHIFT_MASK			// 55 7
+#define ASCII_38	KEY_8 + SHIFT_MASK			// 55 8
+#define ASCII_39	KEY_9 + SHIFT_MASK			// 57 9
+#define ASCII_3A	KEY_PERIOD				// 58 :
+#define ASCII_3B	KEY_COMMA				// 59 ;
+#define ASCII_3C	KEY_NON_US_100				// 60 <
+#define ASCII_3D	KEY_SLASH				// 61 =
+#define ASCII_3E	KEY_NON_US_100 + SHIFT_MASK		// 62 >
+#define ASCII_3F	KEY_M + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_2 + ALTGR_MASK			// 64 @
+#define ASCII_41	KEY_Q + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_SEMICOLON + SHIFT_MASK		// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_A + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_Z + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Y + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_W + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_RIGHT_BRACE + ALTGR_MASK		// 91 [
+#define ASCII_5C	KEY_NON_US_100 + ALTGR_MASK		// 92 
+#define ASCII_5D	KEY_LEFT_BRACE + ALTGR_MASK		// 93 ]
+#define ASCII_5E	KEY_6 + ALTGR_MASK			// 94 ^
+#define ASCII_5F	KEY_EQUAL + SHIFT_MASK			// 95 _
+#define ASCII_60	GRAVE_ACCENT_BITS + KEY_SPACE		// 96 `
+#define ASCII_61	KEY_Q					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_SEMICOLON				// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_A					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_Z					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Y					// 121 y
+#define ASCII_7A	KEY_W					// 122 z
+#define ASCII_7B	KEY_9 + ALTGR_MASK			// 123 {
+#define ASCII_7C	KEY_1 + ALTGR_MASK			// 124 |
+#define ASCII_7D	KEY_0 + ALTGR_MASK			// 125 }
+#define ASCII_7E	TILDE_BITS + KEY_SPACE			// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	0					// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	0					// 162 ¢     Cent SIGN
+#define ISO_8859_1_A3	KEY_BACKSLASH + SHIFT_MASK		// 163 £     Pound Sign
+#define ISO_8859_1_A4	0					// 164 ¤     Currency or Euro Sign
+#define ISO_8859_1_A5	0					// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	0					// 166 ¦     BROKEN BAR
+#define ISO_8859_1_A7	KEY_6					// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	DIAERESIS_BITS + KEY_SPACE		// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	0					// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	0					// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	0					// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	0					// 172 ¬     NOT SIGN
+#define ISO_8859_1_AD	0					// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	0					// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0					// 175 ¯     MACRON
+#define ISO_8859_1_B0	KEY_MINUS + SHIFT_MASK			// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	0					// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	KEY_TILDE				// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	KEY_TILDE + SHIFT_MASK			// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	ACUTE_ACCENT_BITS + KEY_SPACE		// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	KEY_BACKSLASH				// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	0					// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	0					// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	0					// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	0					// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	0					// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	0					// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	0					// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	0					// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	0					// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	GRAVE_ACCENT_BITS + KEY_Q + SHIFT_MASK	// 192 À     A GRAVE
+#define ISO_8859_1_C1	ACUTE_ACCENT_BITS + KEY_Q + SHIFT_MASK	// 193 Á     A ACUTE
+#define ISO_8859_1_C2	CIRCUMFLEX_BITS	+ KEY_Q + SHIFT_MASK	// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	TILDE_BITS + KEY_Q + SHIFT_MASK		// 195 Ã     A TILDE
+#define ISO_8859_1_C4	DIAERESIS_BITS + KEY_Q + SHIFT_MASK	// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	0					// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	0					// 198 Æ     AE
+#define ISO_8859_1_C7	0					// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 200 È     E GRAVE
+#define ISO_8859_1_C9	ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 201 É     E ACUTE
+#define ISO_8859_1_CA	CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK	// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	DIAERESIS_BITS + KEY_E + SHIFT_MASK	// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 205 Í     I ACUTE
+#define ISO_8859_1_CE	CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK	// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	DIAERESIS_BITS + KEY_I + SHIFT_MASK	// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	0					// 208 Ð     ETH
+#define ISO_8859_1_D1	TILDE_BITS + KEY_N + SHIFT_MASK		// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK	// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	TILDE_BITS + KEY_O + SHIFT_MASK		// 213 Õ     O TILDE
+#define ISO_8859_1_D6	DIAERESIS_BITS + KEY_O + SHIFT_MASK	// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	0					// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	0					// 216 Ø     O STROKE
+#define ISO_8859_1_D9	GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK	// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	DIAERESIS_BITS + KEY_U			// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK	// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	0					// 222 Þ     THORN
+#define ISO_8859_1_DF	0					// 223 ß     SHARP S
+#define ISO_8859_1_E0	KEY_0					// 224 à     a GRAVE
+#define ISO_8859_1_E1	ACUTE_ACCENT_BITS + KEY_Q		// 225 á     a ACUTE
+#define ISO_8859_1_E2	CIRCUMFLEX_BITS + KEY_Q			// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	TILDE_BITS + KEY_Q			// 227 ã     a TILDE
+#define ISO_8859_1_E4	DIAERESIS_BITS + KEY_Q			// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	0					// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	0					// 230 æ     ae
+#define ISO_8859_1_E7	KEY_9					// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	KEY_7					// 232 è     e GRAVE
+#define ISO_8859_1_E9	KEY_2					// 233 é     e ACUTE
+#define ISO_8859_1_EA	CIRCUMFLEX_BITS + KEY_E			// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	DIAERESIS_BITS + KEY_E			// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	ACUTE_ACCENT_BITS + KEY_I		// 237 í     i ACUTE
+#define ISO_8859_1_EE	CIRCUMFLEX_BITS + KEY_I			// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	DIAERESIS_BITS + KEY_I			// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	0					// 240 ð     ETH
+#define ISO_8859_1_F1	TILDE_BITS + KEY_N			// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	ACUTE_ACCENT_BITS + KEY_O		// 243 ó     o ACUTE
+#define ISO_8859_1_F4	CIRCUMFLEX_BITS + KEY_O			// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	TILDE_BITS + KEY_O			// 245 õ     o TILDE
+#define ISO_8859_1_F6	DIAERESIS_BITS + KEY_O			// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	0					// 248 ø     o STROKE
+#define ISO_8859_1_F9	KEY_QUOTE				// 249 ù     u GRAVE - TODO; check FRENCH
+#define ISO_8859_1_FA	ACUTE_ACCENT_BITS + KEY_U		// 250 ú     u ACUTE
+#define ISO_8859_1_FB	CIRCUMFLEX_BITS + KEY_U			// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	DIAERESIS_BITS + KEY_U			// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	ACUTE_ACCENT_BITS + KEY_Y		// 253 ý     y ACUTE
+#define ISO_8859_1_FE	0					// 254 þ     THORN
+#define ISO_8859_1_FF	DIAERESIS_BITS + KEY_Y			// 255 ÿ     y DIAERESIS
+#define UNICODE_20AC	KEY_E + ALTGR_MASK			//     €     Euro Sign
+// not yet implemented
+#define UNICODE_EXTRA00	0x20AC
+#define KEYCODE_EXTRA00	KEY_E + ALTGR_MASK			// 20AC €    Euro Sign
+
+#endif // LAYOUT_FRENCH_BELGIAN
+
+
+
+
+#ifdef LAYOUT_GERMAN_SWISS
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define DEADKEYS_MASK		0x0700
+#define	CIRCUMFLEX_BITS		0x0100
+#define GRAVE_ACCENT_BITS	0x0200
+#define DIAERESIS_BITS		0x0300
+#define TILDE_BITS		0x0400
+#define ACUTE_ACCENT_BITS	0x0500
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_CIRCUMFLEX	KEY_EQUAL
+#define DEADKEY_ACUTE_ACCENT	KEY_MINUS + ALTGR_MASK
+#define DEADKEY_GRAVE_ACCENT	KEY_EQUAL + SHIFT_MASK
+#define DEADKEY_DIAERESIS	KEY_RIGHT_BRACE
+#define DEADKEY_TILDE		KEY_EQUAL + ALTGR_MASK
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_RIGHT_BRACE + SHIFT_MASK		// 33 !
+#define ASCII_22	KEY_2 + SHIFT_MASK			// 34 "
+#define ASCII_23	KEY_3 + ALTGR_MASK			// 35 #
+#define ASCII_24	KEY_BACKSLASH				// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_6 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_MINUS				// 39 '  
+#define ASCII_28	KEY_8 + SHIFT_MASK			// 40 ( 
+#define ASCII_29	KEY_9 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_3 + SHIFT_MASK			// 42 *
+#define ASCII_2B	KEY_1 + SHIFT_MASK			// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_SLASH				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_7 + SHIFT_MASK			// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_PERIOD + SHIFT_MASK			// 58 :
+#define ASCII_3B	KEY_COMMA + SHIFT_MASK			// 59 ;
+#define ASCII_3C	KEY_NON_US_100				// 60 <
+#define ASCII_3D	KEY_0 + SHIFT_MASK			// 61 =
+#define ASCII_3E	KEY_NON_US_100 + SHIFT_MASK		// 62 >
+#define ASCII_3F	KEY_MINUS + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_2 + ALTGR_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Z + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Y + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_LEFT_BRACE + ALTGR_MASK		// 91 [
+#define ASCII_5C	KEY_NON_US_100 + ALTGR_MASK		// 92 
+#define ASCII_5D	KEY_RIGHT_BRACE + ALTGR_MASK		// 93 ]
+#define ASCII_5E	CIRCUMFLEX_BITS + KEY_SPACE		// 94 ^
+#define ASCII_5F	KEY_SLASH + SHIFT_MASK			// 95 _
+#define ASCII_60	GRAVE_ACCENT_BITS + KEY_SPACE		// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Z					// 121 y
+#define ASCII_7A	KEY_Y					// 122 z
+#define ASCII_7B	KEY_QUOTE + ALTGR_MASK			// 123 {
+#define ASCII_7C	KEY_7 + ALTGR_MASK			// 124 |
+#define ASCII_7D	KEY_BACKSLASH + ALTGR_MASK		// 125 }
+#define ASCII_7E	TILDE_BITS + KEY_SPACE			// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	0					// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	KEY_8 + ALTGR_MASK			// 162 ¢     Cent Sign
+#define ISO_8859_1_A3	KEY_BACKSLASH + SHIFT_MASK		// 163 £     Pound Sign
+#define ISO_8859_1_A4	0					// 164 ¤     Currency Sign
+#define ISO_8859_1_A5	0					// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	KEY_1 + ALTGR_MASK			// 166 ¦     BROKEN BAR
+#define ISO_8859_1_A7	KEY_5 + ALTGR_MASK			// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	DIAERESIS_BITS + KEY_SPACE		// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	0					// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	0					// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	0					// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	KEY_6 + ALTGR_MASK			// 172 ¬     NOT SIGN
+#define ISO_8859_1_AD	0					// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	0					// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0					// 175 ¯     MACRON
+#define ISO_8859_1_B0	KEY_4 + ALTGR_MASK			// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	0					// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	0					// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	0					// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	ACUTE_ACCENT_BITS + KEY_SPACE		// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	0					// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	0					// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	0					// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	0					// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	0					// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	0					// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	0					// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	0					// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	0					// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	0					// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 192 À     A GRAVE
+#define ISO_8859_1_C1	ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 193 Á     A ACUTE
+#define ISO_8859_1_C2	CIRCUMFLEX_BITS	+ KEY_A + SHIFT_MASK	// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	TILDE_BITS + KEY_A + SHIFT_MASK		// 195 Ã     A TILDE
+#define ISO_8859_1_C4	DIAERESIS_BITS + KEY_A + SHIFT_MASK	// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	0					// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	0					// 198 Æ     AE
+#define ISO_8859_1_C7	0					// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 200 È     E GRAVE
+#define ISO_8859_1_C9	ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 201 É     E ACUTE
+#define ISO_8859_1_CA	CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK	// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	DIAERESIS_BITS + KEY_E + SHIFT_MASK	// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 205 Í     I ACUTE
+#define ISO_8859_1_CE	CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK	// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	DIAERESIS_BITS + KEY_I + SHIFT_MASK	// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	0					// 208 Ð     ETH
+#define ISO_8859_1_D1	TILDE_BITS + KEY_N + SHIFT_MASK		// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK	// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	TILDE_BITS + KEY_O + SHIFT_MASK		// 213 Õ     O TILDE
+#define ISO_8859_1_D6	DIAERESIS_BITS + KEY_O + SHIFT_MASK	// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	0					// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	0					// 216 Ø     O STROKE
+#define ISO_8859_1_D9	GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK	// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	DIAERESIS_BITS + KEY_U + SHIFT_MASK	// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK	// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	0					// 222 Þ     THORN
+#define ISO_8859_1_DF	0					// 223 ß     SHARP S
+#define ISO_8859_1_E0	KEY_QUOTE + SHIFT_MASK			// 224 à     a GRAVE
+#define ISO_8859_1_E1	ACUTE_ACCENT_BITS + KEY_A		// 225 á     a ACUTE
+#define ISO_8859_1_E2	CIRCUMFLEX_BITS + KEY_A			// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	TILDE_BITS + KEY_A			// 227 ã     a TILDE
+#define ISO_8859_1_E4	KEY_QUOTE				// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	0					// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	0					// 230 æ     ae
+#define ISO_8859_1_E7	KEY_4 + SHIFT_MASK			// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	KEY_LEFT_BRACE + SHIFT_MASK		// 232 è     e GRAVE
+#define ISO_8859_1_E9	KEY_SEMICOLON + SHIFT_MASK		// 233 é     e ACUTE
+#define ISO_8859_1_EA	CIRCUMFLEX_BITS + KEY_E			// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	DIAERESIS_BITS + KEY_E			// 235 ë     e DIAERESIS  TODO: check this
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	ACUTE_ACCENT_BITS + KEY_I		// 237 í     i ACUTE
+#define ISO_8859_1_EE	CIRCUMFLEX_BITS + KEY_I			// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	DIAERESIS_BITS + KEY_I			// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	0					// 240 ð     ETH
+#define ISO_8859_1_F1	TILDE_BITS + KEY_N			// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	ACUTE_ACCENT_BITS + KEY_O		// 243 ó     o ACUTE
+#define ISO_8859_1_F4	CIRCUMFLEX_BITS + KEY_O			// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	TILDE_BITS + KEY_O			// 245 õ     o TILDE
+#define ISO_8859_1_F6	KEY_SEMICOLON				// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	0					// 248 ø     o STROKE
+#define ISO_8859_1_F9	GRAVE_ACCENT_BITS + KEY_U		// 249 ù     u GRAVE
+#define ISO_8859_1_FA	ACUTE_ACCENT_BITS + KEY_U		// 250 ú     u ACUTE
+#define ISO_8859_1_FB	CIRCUMFLEX_BITS + KEY_U			// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	KEY_LEFT_BRACE				// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	ACUTE_ACCENT_BITS + KEY_Y		// 253 ý     y ACUTE
+#define ISO_8859_1_FE	0					// 254 þ     THORN
+#define ISO_8859_1_FF	DIAERESIS_BITS + KEY_Y			// 255 ÿ     y DIAERESIS
+#define UNICODE_20AC	KEY_E + ALTGR_MASK			//     €     Euro Sign
+// not yet implemented
+#define UNICODE_EXTRA00	0x20AC
+#define KEYCODE_EXTRA00	KEY_E + ALTGR_MASK			// 20AC €    Euro Sign
+
+#endif // LAYOUT_GERMAN_SWISS
+
+
+
+
+#ifdef LAYOUT_FRENCH_SWISS
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define DEADKEYS_MASK		0x0700
+#define	CIRCUMFLEX_BITS		0x0100
+#define GRAVE_ACCENT_BITS	0x0200
+#define DIAERESIS_BITS		0x0300
+#define TILDE_BITS		0x0400
+#define ACUTE_ACCENT_BITS	0x0500
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_CIRCUMFLEX	KEY_EQUAL
+#define DEADKEY_ACUTE_ACCENT	KEY_MINUS + ALTGR_MASK
+#define DEADKEY_GRAVE_ACCENT	KEY_EQUAL + SHIFT_MASK
+#define DEADKEY_DIAERESIS	KEY_RIGHT_BRACE
+#define DEADKEY_TILDE		KEY_EQUAL + ALTGR_MASK
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_RIGHT_BRACE + SHIFT_MASK		// 33 !
+#define ASCII_22	KEY_2 + SHIFT_MASK			// 34 "
+#define ASCII_23	KEY_3 + ALTGR_MASK			// 35 #
+#define ASCII_24	KEY_BACKSLASH				// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_6 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_MINUS				// 39 '  
+#define ASCII_28	KEY_8 + SHIFT_MASK			// 40 ( 
+#define ASCII_29	KEY_9 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_3 + SHIFT_MASK			// 42 *
+#define ASCII_2B	KEY_1 + SHIFT_MASK			// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_SLASH				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_7 + SHIFT_MASK			// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_PERIOD + SHIFT_MASK			// 58 :
+#define ASCII_3B	KEY_COMMA + SHIFT_MASK			// 59 ;
+#define ASCII_3C	KEY_NON_US_100				// 60 <
+#define ASCII_3D	KEY_0 + SHIFT_MASK			// 61 =
+#define ASCII_3E	KEY_NON_US_100 + SHIFT_MASK		// 62 >
+#define ASCII_3F	KEY_MINUS + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_2 + ALTGR_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Z + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Y + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_LEFT_BRACE + ALTGR_MASK		// 91 [
+#define ASCII_5C	KEY_NON_US_100 + ALTGR_MASK		// 92 
+#define ASCII_5D	KEY_RIGHT_BRACE + ALTGR_MASK		// 93 ]
+#define ASCII_5E	CIRCUMFLEX_BITS + KEY_SPACE		// 94 ^
+#define ASCII_5F	KEY_SLASH + SHIFT_MASK			// 95 _
+#define ASCII_60	GRAVE_ACCENT_BITS + KEY_SPACE		// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Z					// 121 y
+#define ASCII_7A	KEY_Y					// 122 z
+#define ASCII_7B	KEY_QUOTE + ALTGR_MASK			// 123 {
+#define ASCII_7C	KEY_7 + ALTGR_MASK			// 124 |
+#define ASCII_7D	KEY_BACKSLASH + ALTGR_MASK		// 125 }
+#define ASCII_7E	TILDE_BITS + KEY_SPACE			// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	0					// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	KEY_8 + ALTGR_MASK			// 162 ¢     Cent Sign
+#define ISO_8859_1_A3	KEY_BACKSLASH + SHIFT_MASK		// 163 £     Pound Sign
+#define ISO_8859_1_A4	0					// 164 ¤     Currency Sign
+#define ISO_8859_1_A5	0					// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	KEY_1 + ALTGR_MASK			// 166 ¦     BROKEN BAR
+#define ISO_8859_1_A7	KEY_5 + ALTGR_MASK			// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	DIAERESIS_BITS + KEY_SPACE		// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	0					// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	0					// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	0					// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	KEY_6 + ALTGR_MASK			// 172 ¬     NOT SIGN
+#define ISO_8859_1_AD	0					// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	0					// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0					// 175 ¯     MACRON
+#define ISO_8859_1_B0	KEY_4 + ALTGR_MASK			// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	0					// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	0					// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	0					// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	ACUTE_ACCENT_BITS + KEY_SPACE		// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	0					// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	0					// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	0					// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	0					// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	0					// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	0					// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	0					// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	0					// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	0					// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	0					// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 192 À     A GRAVE
+#define ISO_8859_1_C1	ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 193 Á     A ACUTE
+#define ISO_8859_1_C2	CIRCUMFLEX_BITS	+ KEY_A + SHIFT_MASK	// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	TILDE_BITS + KEY_A + SHIFT_MASK		// 195 Ã     A TILDE
+#define ISO_8859_1_C4	DIAERESIS_BITS + KEY_A + SHIFT_MASK	// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	0					// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	0					// 198 Æ     AE
+#define ISO_8859_1_C7	0					// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 200 È     E GRAVE
+#define ISO_8859_1_C9	ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 201 É     E ACUTE
+#define ISO_8859_1_CA	CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK	// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	DIAERESIS_BITS + KEY_E + SHIFT_MASK	// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 205 Í     I ACUTE
+#define ISO_8859_1_CE	CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK	// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	DIAERESIS_BITS + KEY_I + SHIFT_MASK	// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	0					// 208 Ð     ETH
+#define ISO_8859_1_D1	TILDE_BITS + KEY_N + SHIFT_MASK		// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK	// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	TILDE_BITS + KEY_O + SHIFT_MASK		// 213 Õ     O TILDE
+#define ISO_8859_1_D6	DIAERESIS_BITS + KEY_O + SHIFT_MASK	// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	0					// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	0					// 216 Ø     O STROKE
+#define ISO_8859_1_D9	GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK	// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	DIAERESIS_BITS + KEY_U + SHIFT_MASK	// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK	// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	0					// 222 Þ     THORN
+#define ISO_8859_1_DF	0					// 223 ß     SHARP S
+#define ISO_8859_1_E0	KEY_QUOTE				// 224 à     a GRAVE
+#define ISO_8859_1_E1	ACUTE_ACCENT_BITS + KEY_A		// 225 á     a ACUTE
+#define ISO_8859_1_E2	CIRCUMFLEX_BITS + KEY_A			// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	TILDE_BITS + KEY_A			// 227 ã     a TILDE
+#define ISO_8859_1_E4	KEY_QUOTE + SHIFT_MASK			// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	0					// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	0					// 230 æ     ae
+#define ISO_8859_1_E7	KEY_4 + SHIFT_MASK			// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	KEY_LEFT_BRACE				// 232 è     e GRAVE
+#define ISO_8859_1_E9	KEY_SEMICOLON				// 233 é     e ACUTE
+#define ISO_8859_1_EA	CIRCUMFLEX_BITS + KEY_E			// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	DIAERESIS_BITS + KEY_E			// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	ACUTE_ACCENT_BITS + KEY_I		// 237 í     i ACUTE
+#define ISO_8859_1_EE	CIRCUMFLEX_BITS + KEY_I			// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	DIAERESIS_BITS + KEY_I			// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	0					// 240 ð     ETH
+#define ISO_8859_1_F1	TILDE_BITS + KEY_N			// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	ACUTE_ACCENT_BITS + KEY_O		// 243 ó     o ACUTE
+#define ISO_8859_1_F4	CIRCUMFLEX_BITS + KEY_O			// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	TILDE_BITS + KEY_O			// 245 õ     o TILDE
+#define ISO_8859_1_F6	KEY_SEMICOLON + SHIFT_MASK		// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	0					// 248 ø     o STROKE
+#define ISO_8859_1_F9	GRAVE_ACCENT_BITS + KEY_U		// 249 ù     u GRAVE
+#define ISO_8859_1_FA	ACUTE_ACCENT_BITS + KEY_U		// 250 ú     u ACUTE
+#define ISO_8859_1_FB	CIRCUMFLEX_BITS + KEY_U			// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	KEY_LEFT_BRACE + SHIFT_MASK		// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	ACUTE_ACCENT_BITS + KEY_Y		// 253 ý     y ACUTE
+#define ISO_8859_1_FE	0					// 254 þ     THORN
+#define ISO_8859_1_FF	DIAERESIS_BITS + KEY_Y			// 255 ÿ     y DIAERESIS
+#define UNICODE_20AC	KEY_E + ALTGR_MASK			//     €     Euro Sign
+// not yet implemented
+#define UNICODE_EXTRA00	0x20AC
+#define KEYCODE_EXTRA00	KEY_E + ALTGR_MASK			// 20AC €    Euro Sign
+
+#endif // LAYOUT_FRENCH_SWISS
+
+
+
+
+
+#ifdef LAYOUT_SPANISH_LATIN_AMERICA
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define DEADKEYS_MASK		0x0700
+#define	CIRCUMFLEX_BITS		0x0100
+#define ACUTE_ACCENT_BITS	0x0200
+#define GRAVE_ACCENT_BITS	0x0300
+#define DIAERESIS_BITS		0x0400
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_CIRCUMFLEX	KEY_QUOTE + ALTGR_MASK
+#define DEADKEY_ACUTE_ACCENT	KEY_LEFT_BRACE
+#define DEADKEY_GRAVE_ACCENT	KEY_BACKSLASH + ALTGR_MASK
+#define DEADKEY_DIAERESIS	KEY_LEFT_BRACE + SHIFT_MASK
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_1 + SHIFT_MASK			// 33 !
+#define ASCII_22	KEY_2 + SHIFT_MASK			// 34 "
+#define ASCII_23	KEY_3 + ALTGR_MASK			// 35 #
+#define ASCII_24	KEY_4 + SHIFT_MASK			// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_6 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_MINUS				// 39 '  
+#define ASCII_28	KEY_8 + SHIFT_MASK			// 40 ( 
+#define ASCII_29	KEY_9 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_RIGHT_BRACE + SHIFT_MASK		// 42 *
+#define ASCII_2B	KEY_RIGHT_BRACE				// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_SLASH				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_7 + SHIFT_MASK			// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_PERIOD + SHIFT_MASK			// 58 :
+#define ASCII_3B	KEY_COMMA + SHIFT_MASK			// 59 ;
+#define ASCII_3C	KEY_NON_US_100				// 60 <
+#define ASCII_3D	KEY_0 + SHIFT_MASK			// 61 =
+#define ASCII_3E	KEY_NON_US_100 + SHIFT_MASK		// 62 >
+#define ASCII_3F	KEY_MINUS + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_Q + ALTGR_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Y + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Z + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_QUOTE + SHIFT_MASK			// 91 [
+#define ASCII_5C	KEY_MINUS + ALTGR_MASK			// 92 
+#define ASCII_5D	KEY_BACKSLASH + SHIFT_MASK		// 93 ]
+#define ASCII_5E	CIRCUMFLEX_BITS + KEY_SPACE		// 94 ^
+#define ASCII_5F	KEY_SLASH + SHIFT_MASK			// 95 _
+#define ASCII_60	GRAVE_ACCENT_BITS + KEY_SPACE		// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Y					// 121 y
+#define ASCII_7A	KEY_Z					// 122 z
+#define ASCII_7B	KEY_QUOTE				// 123 {
+#define ASCII_7C	KEY_TILDE				// 124 |
+#define ASCII_7D	KEY_BACKSLASH				// 125 }
+#define ASCII_7E	KEY_RIGHT_BRACE + ALTGR_MASK		// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	KEY_EQUAL + SHIFT_MASK			// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	0					// 162 ¢     Cent SIGN
+#define ISO_8859_1_A3	0					// 163 £     Pound Sign
+#define ISO_8859_1_A4	0					// 164 ¤     Currency Sign
+#define ISO_8859_1_A5	0					// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	0					// 166 ¦     BROKEN BAR
+#define ISO_8859_1_A7	0					// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	DIAERESIS_BITS + KEY_SPACE		// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	0					// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	0					// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	0					// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	KEY_TILDE + ALTGR_MASK			// 172 ¬     NOT SIGN
+#define ISO_8859_1_AD	0					// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	0					// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0					// 175 ¯     MACRON
+#define ISO_8859_1_B0	KEY_TILDE + SHIFT_MASK			// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	0					// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	0					// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	0					// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	ACUTE_ACCENT_BITS + KEY_SPACE		// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	0					// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	0					// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	0					// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	0					// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	0					// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	0					// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	0					// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	0					// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	0					// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	KEY_EQUAL				// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 192 À     A GRAVE
+#define ISO_8859_1_C1	ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 193 Á     A ACUTE
+#define ISO_8859_1_C2	CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK	// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	0					// 195 Ã     A TILDE
+#define ISO_8859_1_C4	DIAERESIS_BITS + KEY_A + SHIFT_MASK	// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	0					// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	0					// 198 Æ     AE
+#define ISO_8859_1_C7	0					// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 200 È     E GRAVE
+#define ISO_8859_1_C9	ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 201 É     E ACUTE
+#define ISO_8859_1_CA	CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK	// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	DIAERESIS_BITS + KEY_E + SHIFT_MASK	// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 205 Í     I ACUTE
+#define ISO_8859_1_CE	CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK	// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	DIAERESIS_BITS + KEY_I + SHIFT_MASK	// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	0					// 208 Ð     ETH
+#define ISO_8859_1_D1	KEY_SEMICOLON + SHIFT_MASK		// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK	// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	0					// 213 Õ     O TILDE
+#define ISO_8859_1_D6	DIAERESIS_BITS + KEY_O + SHIFT_MASK	// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	0					// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	0					// 216 Ø     O STROKE
+#define ISO_8859_1_D9	GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK	// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	DIAERESIS_BITS + KEY_U + SHIFT_MASK	// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK	// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	0					// 222 Þ     THORN
+#define ISO_8859_1_DF	0					// 223 ß     SHARP S
+#define ISO_8859_1_E0	GRAVE_ACCENT_BITS + KEY_A		// 224 à     a GRAVE
+#define ISO_8859_1_E1	ACUTE_ACCENT_BITS + KEY_A		// 225 á     a ACUTE
+#define ISO_8859_1_E2	CIRCUMFLEX_BITS + KEY_A			// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	0					// 227 ã     a TILDE
+#define ISO_8859_1_E4	DIAERESIS_BITS + KEY_A			// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	0					// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	0					// 230 æ     ae
+#define ISO_8859_1_E7	0					// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	GRAVE_ACCENT_BITS + KEY_E		// 232 è     e GRAVE
+#define ISO_8859_1_E9	ACUTE_ACCENT_BITS + KEY_E		// 233 é     e ACUTE
+#define ISO_8859_1_EA	CIRCUMFLEX_BITS + KEY_E			// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	DIAERESIS_BITS + KEY_E			// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	ACUTE_ACCENT_BITS + KEY_I		// 237 í     i ACUTE
+#define ISO_8859_1_EE	CIRCUMFLEX_BITS + KEY_I			// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	DIAERESIS_BITS + KEY_I			// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	0					// 240 ð     ETH
+#define ISO_8859_1_F1	KEY_SEMICOLON				// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	ACUTE_ACCENT_BITS + KEY_O		// 243 ó     o ACUTE
+#define ISO_8859_1_F4	CIRCUMFLEX_BITS + KEY_O			// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	0					// 245 õ     o TILDE
+#define ISO_8859_1_F6	DIAERESIS_BITS + KEY_O			// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	0					// 248 ø     o STROKE
+#define ISO_8859_1_F9	GRAVE_ACCENT_BITS + KEY_U		// 249 ù     u GRAVE
+#define ISO_8859_1_FA	ACUTE_ACCENT_BITS + KEY_U		// 250 ú     u ACUTE
+#define ISO_8859_1_FB	CIRCUMFLEX_BITS + KEY_U			// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	DIAERESIS_BITS + KEY_U			// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	ACUTE_ACCENT_BITS + KEY_Y		// 253 ý     y ACUTE
+#define ISO_8859_1_FE	0					// 254 þ     THORN
+#define ISO_8859_1_FF	DIAERESIS_BITS + KEY_Y			// 255 ÿ     y DIAERESIS
+
+#endif // LAYOUT_SPANISH_LATIN_AMERICA
+
+
+
+#ifdef LAYOUT_IRISH
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define DEADKEYS_MASK		0x0300
+#define GRAVE_ACCENT_BITS	0x0100
+#define ACUTE_ACCENT_BITS	0x0200
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_ACUTE_ACCENT	KEY_QUOTE + ALTGR_MASK
+#define DEADKEY_GRAVE_ACCENT	KEY_TILDE
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_1 + SHIFT_MASK			// 33 !
+#define ASCII_22	KEY_2 + SHIFT_MASK			// 34 "
+#define ASCII_23	KEY_BACKSPACE				// 35 #
+#define ASCII_24	KEY_4 + SHIFT_MASK			// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_7 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_QUOTE				// 39 '  
+#define ASCII_28	KEY_9 + SHIFT_MASK			// 40 ( 
+#define ASCII_29	KEY_0 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_8 + SHIFT_MASK			// 42 *
+#define ASCII_2B	KEY_EQUAL + SHIFT_MASK			// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_MINUS				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_SLASH				// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_SEMICOLON + SHIFT_MASK		// 58 :
+#define ASCII_3B	KEY_SEMICOLON				// 59 ;
+#define ASCII_3C	KEY_COMMA + SHIFT_MASK			// 60 <
+#define ASCII_3D	KEY_EQUAL				// 61 =
+#define ASCII_3E	KEY_PERIOD + SHIFT_MASK			// 62 >
+#define ASCII_3F	KEY_SLASH + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_QUOTE + SHIFT_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Y + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Z + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_LEFT_BRACE				// 91 [
+#define ASCII_5C	KEY_NON_US_100				// 92 
+#define ASCII_5D	KEY_RIGHT_BRACE				// 93 ]
+#define ASCII_5E	KEY_6 + SHIFT_MASK			// 94 ^
+#define ASCII_5F	KEY_MINUS + SHIFT_MASK			// 95 _
+#define ASCII_60	KEY_QUOTE + SHIFT_MASK + ALTGR_MASK	// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Y					// 121 y
+#define ASCII_7A	KEY_Z					// 122 z
+#define ASCII_7B	KEY_LEFT_BRACE + SHIFT_MASK		// 123 {
+#define ASCII_7C	KEY_NON_US_100 + SHIFT_MASK		// 124 |
+#define ASCII_7D	KEY_RIGHT_BRACE + SHIFT_MASK		// 125 }
+#define ASCII_7E	KEY_BACKSLASH + SHIFT_MASK		// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	0					// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	0					// 162 ¢     Cent SIGN
+#define ISO_8859_1_A3	KEY_3 + SHIFT_MASK			// 163 £     Pound Sign
+#define ISO_8859_1_A4	0					// 164 ¤     Currency or Euro Sign
+#define ISO_8859_1_A5	0					// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	KEY_TILDE + ALTGR_MASK			// 166 ¦     BROKEN BAR
+#define ISO_8859_1_A7	0					// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	0					// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	0					// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	0					// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	0					// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	KEY_TILDE + SHIFT_MASK			// 172 ¬     NOT SIGN
+#define ISO_8859_1_AD	0					// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	0					// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0					// 175 ¯     MACRON
+#define ISO_8859_1_B0	0					// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	0					// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	0					// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	0					// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	0					// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	0					// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	0					// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	0					// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	0					// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	0					// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	0					// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	0					// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	0					// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	0					// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	0					// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	GRAVE_ACCENT_BITS + KEY_A		// 192 À     A GRAVE
+#define ISO_8859_1_C1	KEY_A + ALTGR_MASK + SHIFT_MASK		// 193 Á     A ACUTE
+#define ISO_8859_1_C2	0					// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	0					// 195 Ã     A TILDE
+#define ISO_8859_1_C4	0					// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	0					// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	0					// 198 Æ     AE
+#define ISO_8859_1_C7	0					// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	GRAVE_ACCENT_BITS + KEY_E		// 200 È     E GRAVE
+#define ISO_8859_1_C9	KEY_E + ALTGR_MASK + SHIFT_MASK		// 201 É     E ACUTE
+#define ISO_8859_1_CA	0					// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	0					// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I		// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	KEY_I + ALTGR_MASK + SHIFT_MASK		// 205 Í     I ACUTE
+#define ISO_8859_1_CE	0					// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	0					// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	0					// 208 Ð     ETH
+#define ISO_8859_1_D1	0					// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O		// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	KEY_O + ALTGR_MASK + SHIFT_MASK		// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	0					// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	0					// 213 Õ     O TILDE
+#define ISO_8859_1_D6	0					// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	0					// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	0					// 216 Ø     O STROKE
+#define ISO_8859_1_D9	GRAVE_ACCENT_BITS + KEY_U		// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	KEY_U + ALTGR_MASK + SHIFT_MASK		// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	0					// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	0					// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK	// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	0					// 222 Þ     THORN
+#define ISO_8859_1_DF	0					// 223 ß     SHARP S
+#define ISO_8859_1_E0	GRAVE_ACCENT_BITS + KEY_A		// 224 à     a GRAVE
+#define ISO_8859_1_E1	KEY_A + ALTGR_MASK			// 225 á     a ACUTE
+#define ISO_8859_1_E2	0					// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	0					// 227 ã     a TILDE
+#define ISO_8859_1_E4	0					// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	0					// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	0					// 230 æ     ae
+#define ISO_8859_1_E7	0					// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	GRAVE_ACCENT_BITS + KEY_E		// 232 è     e GRAVE
+#define ISO_8859_1_E9	KEY_E + ALTGR_MASK			// 233 é     e ACUTE
+#define ISO_8859_1_EA	0					// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	0					// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	KEY_I + ALTGR_MASK			// 237 í     i ACUTE
+#define ISO_8859_1_EE	0					// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	0					// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	0					// 240 ð     ETH
+#define ISO_8859_1_F1	0					// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	KEY_O + ALTGR_MASK			// 243 ó     o ACUTE
+#define ISO_8859_1_F4	0					// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	0					// 245 õ     o TILDE
+#define ISO_8859_1_F6	0					// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	0					// 248 ø     o STROKE
+#define ISO_8859_1_F9	GRAVE_ACCENT_BITS + KEY_U		// 249 ù     u GRAVE
+#define ISO_8859_1_FA	KEY_U + ALTGR_MASK			// 250 ú     u ACUTE
+#define ISO_8859_1_FB	0					// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	0					// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	ACUTE_ACCENT_BITS + KEY_Y		// 253 ý     y ACUTE
+#define ISO_8859_1_FE	0					// 254 þ     THORN
+#define ISO_8859_1_FF	0					// 255 ÿ     y DIAERESIS
+#define UNICODE_20AC	KEY_4 + ALTGR_MASK			//     €     Euro Sign
+// not yet implemented
+#define UNICODE_EXTRA00	0x20AC
+#define KEYCODE_EXTRA00	KEY_4 + ALTGR_MASK			// 20AC €    Euro Sign
+
+#endif // LAYOUT_IRISH
+
+
+
+
+#ifdef LAYOUT_ICELANDIC
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define DEADKEYS_MASK		0x0700
+#define	CIRCUMFLEX_BITS		0x0100
+#define ACUTE_ACCENT_BITS	0x0200
+#define GRAVE_ACCENT_BITS	0x0300
+#define DIAERESIS_BITS		0x0400
+#define RING_ABOVE_BITS		0x0500
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_CIRCUMFLEX	KEY_QUOTE + ALTGR_MASK
+#define DEADKEY_ACUTE_ACCENT	KEY_QUOTE
+#define DEADKEY_GRAVE_ACCENT	KEY_BACKSLASH + ALTGR_MASK
+#define DEADKEY_DIAERESIS	KEY_TILDE + SHIFT_MASK
+#define DEADKEY_RING_ABOVE	KEY_TILDE
+#define KEY_NON_US_100		63
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_1 + SHIFT_MASK			// 33 !
+#define ASCII_22	KEY_2 + SHIFT_MASK			// 34 "
+#define ASCII_23	KEY_3 + SHIFT_MASK			// 35 #
+#define ASCII_24	KEY_4 + SHIFT_MASK			// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_6 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_QUOTE + SHIFT_MASK			// 39 '  
+#define ASCII_28	KEY_8 + SHIFT_MASK			// 40 ( 
+#define ASCII_29	KEY_9 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_BACKSLASH + SHIFT_MASK		// 42 *
+#define ASCII_2B	KEY_BACKSLASH				// 43 +
+#define ASCII_2C	KEY_COMMA				// 44 ,
+#define ASCII_2D	KEY_EQUAL				// 45 -
+#define ASCII_2E	KEY_PERIOD				// 46 .
+#define ASCII_2F	KEY_7 + SHIFT_MASK			// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_PERIOD + SHIFT_MASK			// 58 :
+#define ASCII_3B	KEY_COMMA + SHIFT_MASK			// 59 ;
+#define ASCII_3C	KEY_NON_US_100				// 60 <
+#define ASCII_3D	KEY_0 + SHIFT_MASK			// 61 =
+#define ASCII_3E	KEY_NON_US_100 + SHIFT_MASK		// 62 >
+#define ASCII_3F	KEY_RIGHT_BRACE + SHIFT_MASK		// 63 ?
+#define ASCII_40	KEY_Q + ALTGR_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Y + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Z + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_8 + ALTGR_MASK			// 91 [
+#define ASCII_5C	KEY_MINUS + ALTGR_MASK			// 92 
+#define ASCII_5D	KEY_9 + ALTGR_MASK			// 93 ]
+#define ASCII_5E	CIRCUMFLEX_BITS + KEY_SPACE		// 94 ^
+#define ASCII_5F	KEY_EQUAL + SHIFT_MASK			// 95 _
+#define ASCII_60	GRAVE_ACCENT_BITS + KEY_SPACE		// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_I					// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Y					// 121 y
+#define ASCII_7A	KEY_Z					// 122 z
+#define ASCII_7B	KEY_7 + ALTGR_MASK			// 123 {
+#define ASCII_7C	KEY_NON_US_100 + ALTGR_MASK		// 124 |
+#define ASCII_7D	KEY_0 + ALTGR_MASK			// 125 }
+#define ASCII_7E	KEY_RIGHT_BRACE + ALTGR_MASK		// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	0					// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	0					// 162 ¢     Cent SIGN
+#define ISO_8859_1_A3	0					// 163 £     Pound Sign
+#define ISO_8859_1_A4	0					// 164 ¤     Currency or Euro Sign
+#define ISO_8859_1_A5	0					// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	0					// 166 ¦     BROKEN BAR			??
+#define ISO_8859_1_A7	0					// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	DIAERESIS_BITS + KEY_SPACE		// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	0					// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	0					// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	0					// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	0					// 172 ¬     NOT SIGN			??
+#define ISO_8859_1_AD	0					// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	0					// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0					// 175 ¯     MACRON
+#define ISO_8859_1_B0	KEY_TILDE + ALTGR_MASK			// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	0					// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	0					// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	0					// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	ACUTE_ACCENT_BITS + KEY_SPACE		// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	KEY_M + ALTGR_MASK			// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	0					// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	0					// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	0					// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	0					// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	0					// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	0					// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	0					// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	0					// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	0					// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 192 À     A GRAVE
+#define ISO_8859_1_C1	ACUTE_ACCENT_BITS + KEY_A + ALTGR_MASK	// 193 Á     A ACUTE
+#define ISO_8859_1_C2	CIRCUMFLEX_BITS	+ KEY_A + SHIFT_MASK	// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	0					// 195 Ã     A TILDE
+#define ISO_8859_1_C4	DIAERESIS_BITS + KEY_A + SHIFT_MASK	// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	RING_ABOVE_BITS + KEY_A + SHIFT_MASK	// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	KEY_SEMICOLON + SHIFT_MASK		// 198 Æ     AE
+#define ISO_8859_1_C7	0					// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 200 È     E GRAVE
+#define ISO_8859_1_C9	ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 201 É     E ACUTE
+#define ISO_8859_1_CA	CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK	// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	DIAERESIS_BITS + KEY_E + SHIFT_MASK	// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 205 Í     I ACUTE
+#define ISO_8859_1_CE	CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK	// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	DIAERESIS_BITS + KEY_I + SHIFT_MASK	// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	KEY_LEFT_BRACE + SHIFT_MASK		// 208 Ð     ETH
+#define ISO_8859_1_D1	0					// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK	// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	0					// 213 Õ     O TILDE
+#define ISO_8859_1_D6	DIAERESIS_BITS + KEY_O + SHIFT_MASK	// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	0					// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	0					// 216 Ø     O STROKE
+#define ISO_8859_1_D9	GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK	// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	DIAERESIS_BITS + KEY_U + SHIFT_MASK	// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK	// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	KEY_SLASH + SHIFT_MASK			// 222 Þ     THORN
+#define ISO_8859_1_DF	0					// 223 ß     SHARP S
+#define ISO_8859_1_E0	GRAVE_ACCENT_BITS + KEY_A		// 224 à     a GRAVE
+#define ISO_8859_1_E1	ACUTE_ACCENT_BITS + KEY_A		// 225 á     a ACUTE
+#define ISO_8859_1_E2	CIRCUMFLEX_BITS + KEY_A			// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	0					// 227 ã     a TILDE
+#define ISO_8859_1_E4	DIAERESIS_BITS + KEY_A			// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	RING_ABOVE_BITS + KEY_A			// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	KEY_SEMICOLON				// 230 æ     ae
+#define ISO_8859_1_E7	0					// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	GRAVE_ACCENT_BITS + KEY_E		// 232 è     e GRAVE
+#define ISO_8859_1_E9	ACUTE_ACCENT_BITS + KEY_E		// 233 é     e ACUTE
+#define ISO_8859_1_EA	CIRCUMFLEX_BITS + KEY_E			// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	DIAERESIS_BITS + KEY_E			// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	ACUTE_ACCENT_BITS + KEY_I		// 237 í     i ACUTE
+#define ISO_8859_1_EE	CIRCUMFLEX_BITS + KEY_I			// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	DIAERESIS_BITS + KEY_I			// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	KEY_LEFT_BRACE				// 240 ð     ETH
+#define ISO_8859_1_F1	0					// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	ACUTE_ACCENT_BITS + KEY_O		// 243 ó     o ACUTE
+#define ISO_8859_1_F4	CIRCUMFLEX_BITS + KEY_O			// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	0					// 245 õ     o TILDE
+#define ISO_8859_1_F6	DIAERESIS_BITS + KEY_O			// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	0					// 248 ø     o STROKE
+#define ISO_8859_1_F9	GRAVE_ACCENT_BITS + KEY_U		// 249 ù     u GRAVE
+#define ISO_8859_1_FA	ACUTE_ACCENT_BITS + KEY_U		// 250 ú     u ACUTE
+#define ISO_8859_1_FB	CIRCUMFLEX_BITS + KEY_U			// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	DIAERESIS_BITS + KEY_U			// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	ACUTE_ACCENT_BITS + KEY_Y		// 253 ý     y ACUTE
+#define ISO_8859_1_FE	KEY_SLASH				// 254 þ     THORN
+#define ISO_8859_1_FF	DIAERESIS_BITS + KEY_Y			// 255 ÿ     y DIAERESIS
+#define UNICODE_20AC	KEY_5 + ALTGR_MASK			//     €     Euro Sign
+// not yet implemented
+#define UNICODE_EXTRA00	0x20AC
+#define KEYCODE_EXTRA00	KEY_5 + ALTGR_MASK			// 20AC €    Euro Sign
+
+#endif // LAYOUT_ICELANDIC
+
+
+
+#ifdef LAYOUT_TURKISH
+// http://forum.pjrc.com/threads/18781-Turkish-Language-Support
+
+#define SHIFT_MASK		0x0040
+#define ALTGR_MASK		0x0080
+#define DEADKEYS_MASK		0x0700
+#define	CIRCUMFLEX_BITS		0x0100
+#define ACUTE_ACCENT_BITS	0x0200
+#define GRAVE_ACCENT_BITS	0x0300
+#define TILDE_BITS		0x0400
+#define DIAERESIS_BITS		0x0500
+#define KEYCODE_TYPE		uint16_t
+#define DEADKEY_CIRCUMFLEX	KEY_3 + SHIFT_MASK
+#define DEADKEY_ACUTE_ACCENT	KEY_SEMICOLON + ALTGR_MASK
+#define DEADKEY_GRAVE_ACCENT	KEY_BACKSLASH + ALTGR_MASK
+#define DEADKEY_TILDE		KEY_RIGHT_BRACE + ALTGR_MASK
+#define DEADKEY_DIAERESIS	KEY_LEFT_BRACE + ALTGR_MASK
+
+#define ASCII_20	KEY_SPACE				// 32  
+#define ASCII_21	KEY_1 + SHIFT_MASK			// 33 !
+#define ASCII_22	KEY_TILDE				// 34 "
+#define ASCII_23	KEY_3 + ALTGR_MASK			// 35 #
+#define ASCII_24	KEY_4 + ALTGR_MASK			// 36 $
+#define ASCII_25	KEY_5 + SHIFT_MASK			// 37 %
+#define ASCII_26	KEY_6 + SHIFT_MASK			// 38 &
+#define ASCII_27	KEY_2 + SHIFT_MASK			// 39 '  
+#define ASCII_28	KEY_8 + SHIFT_MASK			// 40 ( 
+#define ASCII_29	KEY_9 + SHIFT_MASK			// 41 )
+#define ASCII_2A	KEY_MINUS				// 42 *
+#define ASCII_2B	KEY_4 + SHIFT_MASK			// 43 +
+#define ASCII_2C	KEY_BACKSLASH				// 44 ,
+#define ASCII_2D	KEY_EQUAL				// 45 -
+#define ASCII_2E	KEY_SLASH				// 46 .
+#define ASCII_2F	KEY_7 + SHIFT_MASK			// 47 /
+#define ASCII_30	KEY_0					// 48 0
+#define ASCII_31	KEY_1					// 49 1
+#define ASCII_32	KEY_2					// 50 2
+#define ASCII_33	KEY_3					// 51 3
+#define ASCII_34	KEY_4					// 52 4
+#define ASCII_35	KEY_5					// 53 5
+#define ASCII_36	KEY_6					// 54 6
+#define ASCII_37	KEY_7					// 55 7
+#define ASCII_38	KEY_8					// 55 8
+#define ASCII_39	KEY_9					// 57 9
+#define ASCII_3A	KEY_SLASH + SHIFT_MASK			// 58 :
+#define ASCII_3B	KEY_BACKSLASH + SHIFT_MASK		// 59 ;
+#define ASCII_3C	KEY_TILDE + ALTGR_MASK			// 60 <
+#define ASCII_3D	KEY_0 + SHIFT_MASK			// 61 =
+#define ASCII_3E	KEY_1 + ALTGR_MASK			// 62 >
+#define ASCII_3F	KEY_MINUS + SHIFT_MASK			// 63 ?
+#define ASCII_40	KEY_Q + ALTGR_MASK			// 64 @
+#define ASCII_41	KEY_A + SHIFT_MASK			// 65 A
+#define ASCII_42	KEY_B + SHIFT_MASK			// 66 B
+#define ASCII_43	KEY_C + SHIFT_MASK			// 67 C
+#define ASCII_44	KEY_D + SHIFT_MASK			// 68 D
+#define ASCII_45	KEY_E + SHIFT_MASK			// 69 E
+#define ASCII_46	KEY_F + SHIFT_MASK			// 70 F
+#define ASCII_47	KEY_G + SHIFT_MASK			// 71 G
+#define ASCII_48	KEY_H + SHIFT_MASK			// 72 H
+#define ASCII_49	KEY_I + SHIFT_MASK			// 73 I
+#define ASCII_4A	KEY_J + SHIFT_MASK			// 74 J
+#define ASCII_4B	KEY_K + SHIFT_MASK			// 75 K
+#define ASCII_4C	KEY_L + SHIFT_MASK			// 76 L
+#define ASCII_4D	KEY_M + SHIFT_MASK			// 77 M
+#define ASCII_4E	KEY_N + SHIFT_MASK			// 78 N
+#define ASCII_4F	KEY_O + SHIFT_MASK			// 79 O
+#define ASCII_50	KEY_P + SHIFT_MASK			// 80 P
+#define ASCII_51	KEY_Q + SHIFT_MASK			// 81 Q
+#define ASCII_52	KEY_R + SHIFT_MASK			// 82 R
+#define ASCII_53	KEY_S + SHIFT_MASK			// 83 S
+#define ASCII_54	KEY_T + SHIFT_MASK			// 84 T
+#define ASCII_55	KEY_U + SHIFT_MASK			// 85 U
+#define ASCII_56	KEY_V + SHIFT_MASK			// 86 V
+#define ASCII_57	KEY_W + SHIFT_MASK			// 87 W
+#define ASCII_58	KEY_X + SHIFT_MASK			// 88 X
+#define ASCII_59	KEY_Y + SHIFT_MASK			// 89 Y
+#define ASCII_5A	KEY_Z + SHIFT_MASK			// 90 Z
+#define ASCII_5B	KEY_8 + ALTGR_MASK			// 91 [
+#define ASCII_5C	KEY_MINUS + ALTGR_MASK			// 92 
+#define ASCII_5D	KEY_9 + ALTGR_MASK			// 93 ]
+#define ASCII_5E	CIRCUMFLEX_BITS + KEY_SPACE		// 94 ^
+#define ASCII_5F	KEY_EQUAL + SHIFT_MASK			// 95 _
+#define ASCII_60	GRAVE_ACCENT_BITS + KEY_SPACE		// 96 `
+#define ASCII_61	KEY_A					// 97 a
+#define ASCII_62	KEY_B					// 98 b
+#define ASCII_63	KEY_C					// 99 c
+#define ASCII_64	KEY_D					// 100 d
+#define ASCII_65	KEY_E					// 101 e
+#define ASCII_66	KEY_F					// 102 f
+#define ASCII_67	KEY_G					// 103 g
+#define ASCII_68	KEY_H					// 104 h
+#define ASCII_69	KEY_QUOTE				// 105 i
+#define ASCII_6A	KEY_J					// 106 j
+#define ASCII_6B	KEY_K					// 107 k
+#define ASCII_6C	KEY_L					// 108 l
+#define ASCII_6D	KEY_M					// 109 m
+#define ASCII_6E	KEY_N					// 110 n
+#define ASCII_6F	KEY_O					// 111 o
+#define ASCII_70	KEY_P					// 112 p
+#define ASCII_71	KEY_Q					// 113 q
+#define ASCII_72	KEY_R					// 114 r
+#define ASCII_73	KEY_S					// 115 s
+#define ASCII_74	KEY_T					// 116 t
+#define ASCII_75	KEY_U					// 117 u
+#define ASCII_76	KEY_V					// 118 v
+#define ASCII_77	KEY_W					// 119 w
+#define ASCII_78	KEY_X					// 120 x
+#define ASCII_79	KEY_Y					// 121 y
+#define ASCII_7A	KEY_Z					// 122 z
+#define ASCII_7B	KEY_7 + ALTGR_MASK			// 123 {
+#define ASCII_7C	KEY_EQUAL + ALTGR_MASK			// 124 |
+#define ASCII_7D	KEY_0 + ALTGR_MASK			// 125 }
+#define ASCII_7E	TILDE_BITS + KEY_SPACE			// 126 ~
+#define ASCII_7F	KEY_BACKSPACE				// 127
+
+#define ISO_8859_1_A0	KEY_SPACE				// 160       Nonbreakng Space
+#define ISO_8859_1_A1	0					// 161 ¡     Inverted Exclamation
+#define ISO_8859_1_A2	0					// 162 ¢     Cent SIGN
+#define ISO_8859_1_A3	KEY_2 + ALTGR_MASK			// 163 £     Pound Sign
+#define ISO_8859_1_A4	0					// 164 ¤     Currency or Euro Sign
+#define ISO_8859_1_A5	0					// 165 ¥     YEN SIGN
+#define ISO_8859_1_A6	0					// 166 ¦     BROKEN BAR			??
+#define ISO_8859_1_A7	0					// 167 §     SECTION SIGN
+#define ISO_8859_1_A8	DIAERESIS_BITS + KEY_SPACE		// 168 ¨     DIAERESIS
+#define ISO_8859_1_A9	0					// 169 ©     COPYRIGHT SIGN
+#define ISO_8859_1_AA	0					// 170 ª     FEMININE ORDINAL
+#define ISO_8859_1_AB	0					// 171 «     LEFT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_AC	0					// 172 ¬     NOT SIGN			??
+#define ISO_8859_1_AD	0					// 173       SOFT HYPHEN
+#define ISO_8859_1_AE	0					// 174 ®     REGISTERED SIGN
+#define ISO_8859_1_AF	0					// 175 ¯     MACRON
+#define ISO_8859_1_B0	0					// 176 °     DEGREE SIGN
+#define ISO_8859_1_B1	0					// 177 ±     PLUS-MINUS SIGN
+#define ISO_8859_1_B2	0					// 178 ²     SUPERSCRIPT TWO
+#define ISO_8859_1_B3	0					// 179 ³     SUPERSCRIPT THREE
+#define ISO_8859_1_B4	ACUTE_ACCENT_BITS + KEY_SPACE		// 180 ´     ACUTE ACCENT
+#define ISO_8859_1_B5	0					// 181 µ     MICRO SIGN
+#define ISO_8859_1_B6	0					// 182 ¶     PILCROW SIGN
+#define ISO_8859_1_B7	0					// 183 ·     MIDDLE DOT
+#define ISO_8859_1_B8	0					// 184 ¸     CEDILLA
+#define ISO_8859_1_B9	0					// 185 ¹     SUPERSCRIPT ONE
+#define ISO_8859_1_BA	0					// 186 º     MASCULINE ORDINAL
+#define ISO_8859_1_BB	0					// 187 »     RIGHT DOUBLE ANGLE QUOTE
+#define ISO_8859_1_BC	0					// 188 ¼     FRACTION ONE QUARTER
+#define ISO_8859_1_BD	KEY_5 + ALTGR_MASK			// 189 ½     FRACTION ONE HALF
+#define ISO_8859_1_BE	0					// 190 ¾     FRACTION THREE QUARTERS
+#define ISO_8859_1_BF	0					// 191 ¿     INVERTED QUESTION MARK
+#define ISO_8859_1_C0	GRAVE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 192 À     A GRAVE
+#define ISO_8859_1_C1	ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK	// 193 Á     A ACUTE
+#define ISO_8859_1_C2	CIRCUMFLEX_BITS	+ KEY_A + SHIFT_MASK	// 194 Â     A CIRCUMFLEX
+#define ISO_8859_1_C3	TILDE_BITS + KEY_A + SHIFT_MASK		// 195 Ã     A TILDE
+#define ISO_8859_1_C4	DIAERESIS_BITS + KEY_A + SHIFT_MASK	// 196 Ä     A DIAERESIS
+#define ISO_8859_1_C5	0					// 197 Ã…     A RING ABOVE
+#define ISO_8859_1_C6	KEY_A + ALTGR_MASK			// 198 Æ     AE
+#define ISO_8859_1_C7	KEY_PERIOD + SHIFT_MASK			// 199 Ç     C CEDILLA
+#define ISO_8859_1_C8	GRAVE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 200 È     E GRAVE
+#define ISO_8859_1_C9	ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK	// 201 É     E ACUTE
+#define ISO_8859_1_CA	CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK	// 202 Ê     E CIRCUMFLEX
+#define ISO_8859_1_CB	DIAERESIS_BITS + KEY_E + SHIFT_MASK	// 203 Ë     E DIAERESIS
+#define ISO_8859_1_CC	GRAVE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 204 Ì     I GRAVE
+#define ISO_8859_1_CD	ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK	// 205 Í     I ACUTE
+#define ISO_8859_1_CE	CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK	// 206 ÃŽ     I CIRCUMFLEX
+#define ISO_8859_1_CF	DIAERESIS_BITS + KEY_I + SHIFT_MASK	// 207 Ï     I DIAERESIS
+#define ISO_8859_1_D0	0					// 208 Ð     ETH
+#define ISO_8859_1_D1	TILDE_BITS + KEY_N + SHIFT_MASK		// 209 Ñ     N TILDE
+#define ISO_8859_1_D2	GRAVE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 210 Ã’     O GRAVE
+#define ISO_8859_1_D3	ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK	// 211 Ó     O ACUTE
+#define ISO_8859_1_D4	CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK	// 212 Ô     O CIRCUMFLEX
+#define ISO_8859_1_D5	TILDE_BITS + KEY_O + SHIFT_MASK		// 213 Õ     O TILDE
+#define ISO_8859_1_D6	KEY_COMMA + SHIFT_MASK			// 214 Ö     O DIAERESIS
+#define ISO_8859_1_D7	0					// 215 ×     MULTIPLICATION
+#define ISO_8859_1_D8	0					// 216 Ø     O STROKE
+#define ISO_8859_1_D9	GRAVE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 217 Ù     U GRAVE
+#define ISO_8859_1_DA	ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK	// 218 Ú     U ACUTE
+#define ISO_8859_1_DB	CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK	// 219 Û     U CIRCUMFLEX
+#define ISO_8859_1_DC	KEY_RIGHT_BRACE + SHIFT_MASK		// 220 Ü     U DIAERESIS
+#define ISO_8859_1_DD	ACUTE_ACCENT_BITS + KEY_Y + SHIFT_MASK	// 221 Ý     Y ACUTE
+#define ISO_8859_1_DE	0					// 222 Þ     THORN
+#define ISO_8859_1_DF	KEY_S + ALTGR_MASK			// 223 ß     SHARP S
+#define ISO_8859_1_E0	GRAVE_ACCENT_BITS + KEY_A		// 224 à     a GRAVE
+#define ISO_8859_1_E1	ACUTE_ACCENT_BITS + KEY_A		// 225 á     a ACUTE
+#define ISO_8859_1_E2	CIRCUMFLEX_BITS + KEY_A			// 226 â     a CIRCUMFLEX
+#define ISO_8859_1_E3	TILDE_BITS + KEY_A			// 227 ã     a TILDE
+#define ISO_8859_1_E4	DIAERESIS_BITS + KEY_A			// 228 ä     a DIAERESIS
+#define ISO_8859_1_E5	0					// 229 å     a RING ABOVE
+#define ISO_8859_1_E6	0					// 230 æ     ae
+#define ISO_8859_1_E7	KEY_PERIOD				// 231 ç     c CEDILLA
+#define ISO_8859_1_E8	GRAVE_ACCENT_BITS + KEY_E		// 232 è     e GRAVE
+#define ISO_8859_1_E9	KEY_TILDE + SHIFT_MASK			// 233 é     e ACUTE
+#define ISO_8859_1_EA	CIRCUMFLEX_BITS + KEY_E			// 234 ê     e CIRCUMFLEX
+#define ISO_8859_1_EB	DIAERESIS_BITS + KEY_E			// 235 ë     e DIAERESIS
+#define ISO_8859_1_EC	GRAVE_ACCENT_BITS + KEY_I		// 236 ì     i GRAVE
+#define ISO_8859_1_ED	ACUTE_ACCENT_BITS + KEY_I		// 237 í     i ACUTE
+#define ISO_8859_1_EE	CIRCUMFLEX_BITS + KEY_I			// 238 î     i CIRCUMFLEX
+#define ISO_8859_1_EF	DIAERESIS_BITS + KEY_I			// 239 ï     i DIAERESIS
+#define ISO_8859_1_F0	0					// 240 ð     ETH
+#define ISO_8859_1_F1	TILDE_BITS + KEY_N			// 241 ñ     n TILDE
+#define ISO_8859_1_F2	GRAVE_ACCENT_BITS + KEY_O		// 242 ò     o GRAVE
+#define ISO_8859_1_F3	ACUTE_ACCENT_BITS + KEY_O		// 243 ó     o ACUTE
+#define ISO_8859_1_F4	CIRCUMFLEX_BITS + KEY_O			// 244 ô     o CIRCUMFLEX
+#define ISO_8859_1_F5	TILDE_BITS + KEY_O 			// 245 õ     o TILDE
+#define ISO_8859_1_F6	KEY_COMMA				// 246 ö     o DIAERESIS
+#define ISO_8859_1_F7	0					// 247 ÷     DIVISION
+#define ISO_8859_1_F8	0					// 248 ø     o STROKE
+#define ISO_8859_1_F9	GRAVE_ACCENT_BITS + KEY_U		// 249 ù     u GRAVE
+#define ISO_8859_1_FA	ACUTE_ACCENT_BITS + KEY_U		// 250 ú     u ACUTE
+#define ISO_8859_1_FB	CIRCUMFLEX_BITS + KEY_U			// 251 û     u CIRCUMFLEX
+#define ISO_8859_1_FC	KEY_RIGHT_BRACE				// 252 ü     u DIAERESIS
+#define ISO_8859_1_FD	ACUTE_ACCENT_BITS + KEY_Y		// 253 ý     y ACUTE
+#define ISO_8859_1_FE	0					// 254 þ     THORN
+#define ISO_8859_1_FF	DIAERESIS_BITS + KEY_Y			// 255 ÿ     y DIAERESIS
+#define UNICODE_20AC	KEY_E + ALTGR_MASK			//     €     Euro Sign
+
+// not yet implemented
+#define UNICODE_EXTRA00	0x20AC
+#define KEYCODE_EXTRA00	KEY_E + ALTGR_MASK			// 20AC €    Euro Sign
+#define UNICODE_EXTRA01	0x011E
+#define KEYCODE_EXTRA01	KEY_LEFT_BRACE + SHIFT_MASK		// 011E Äž    Latin capital letter G with breve
+#define UNICODE_EXTRA02	0x011F
+#define KEYCODE_EXTRA02 KEY_LEFT_BRACE				// 011F ÄŸ    Latin small letter g with breve
+#define UNICODE_EXTRA03	0x0130
+#define KEYCODE_EXTRA03 KEY_QUOTE + SHIFT_MASK			// 0130 Ä°    Latin captial letter I with dot above
+#define UNICODE_EXTRA04	0x0131
+#define KEYCODE_EXTRA04 KEY_I					// 0131 ı    Latin small letter dotless i
+#define UNICODE_EXTRA05	0x015E
+#define KEYCODE_EXTRA05 KEY_SEMICOLON + SHIFT_MASK		// 015E Åž    Latin capital letter S with cedilla
+#define UNICODE_EXTRA06	0x0151
+#define KEYCODE_EXTRA06 KEY_SEMICOLON				// 0151 ÅŸ    Latin small letter s with cedilla
+
+#endif // LAYOUT_TURKISH
+
+
+
+
+
+
+
+
+
+extern const KEYCODE_TYPE keycodes_ascii[];
+extern const KEYCODE_TYPE keycodes_iso_8859_1[];
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif
diff --git a/teensy3/main.cpp b/teensy3/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a67502a4c70cd189132adf693b9541c1f212fc0e
--- /dev/null
+++ b/teensy3/main.cpp
@@ -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
+}
+
diff --git a/teensy3/math_helper.c b/teensy3/math_helper.c
new file mode 100644
index 0000000000000000000000000000000000000000..976ca2d3fa5b097b26af88890afc4f9ff7c1ba56
--- /dev/null
+++ b/teensy3/math_helper.c
@@ -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;
+	  }
+	       
+    }
+}
+
+
+
+
diff --git a/teensy3/math_helper.h b/teensy3/math_helper.h
new file mode 100644
index 0000000000000000000000000000000000000000..934a75d45cfdcc40a4996073147f07f76200c09b
--- /dev/null
+++ b/teensy3/math_helper.h
@@ -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
+
diff --git a/teensy3/mk20dx128.c b/teensy3/mk20dx128.c
new file mode 100644
index 0000000000000000000000000000000000000000..348050ccbca3eb536d5f4bf5534f594e9ef34c72
--- /dev/null
+++ b/teensy3/mk20dx128.c
@@ -0,0 +1,371 @@
+/* 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); // die
+}
+
+void unused_isr(void)
+{
+        while (1); // die
+}
+
+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;
+
+	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
+
+        // 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)
+{
+}
+
diff --git a/teensy3/mk20dx128.h b/teensy3/mk20dx128.h
new file mode 100644
index 0000000000000000000000000000000000000000..95af88e7d9c59e0227ca34e46df71359d4352746
--- /dev/null
+++ b/teensy3/mk20dx128.h
@@ -0,0 +1,1613 @@
+/* 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 _mk20dx128_h_
+#define _mk20dx128_h_
+
+//#define F_CPU 96000000
+//#define F_CPU 48000000
+//#define F_CPU 24000000
+//#define F_BUS 48000000
+//#define F_BUS 24000000
+//#define F_MEM 24000000
+
+#if (F_CPU == 96000000)
+ #define F_BUS 48000000
+ #define F_MEM 24000000
+#elif (F_CPU == 48000000)
+ #define F_BUS 48000000
+ #define F_MEM 24000000
+#elif (F_CPU == 24000000)
+ #define F_BUS 24000000
+ #define F_MEM 24000000
+#endif
+
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#include <stdint.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// chapter 11: Port control and interrupts (PORT)
+#define PORTA_PCR0              *(volatile uint32_t *)0x40049000 // Pin Control Register n
+#define PORT_PCR_ISF			(uint32_t)0x01000000		// Interrupt Status Flag
+#define PORT_PCR_IRQC(n)		(uint32_t)(((n) & 15) << 16)	// Interrupt Configuration
+#define PORT_PCR_IRQC_MASK		(uint32_t)0x000F0000
+#define PORT_PCR_LK			(uint32_t)0x00008000		// Lock Register
+#define PORT_PCR_MUX(n)			(uint32_t)(((n) & 7) << 8)	// Pin Mux Control
+#define PORT_PCR_MUX_MASK		(uint32_t)0x00000700
+#define PORT_PCR_DSE			(uint32_t)0x00000040		// Drive Strength Enable
+#define PORT_PCR_ODE			(uint32_t)0x00000020		// Open Drain Enable
+#define PORT_PCR_PFE			(uint32_t)0x00000010		// Passive Filter Enable
+#define PORT_PCR_SRE			(uint32_t)0x00000004		// Slew Rate Enable
+#define PORT_PCR_PE			(uint32_t)0x00000002		// Pull Enable
+#define PORT_PCR_PS			(uint32_t)0x00000001		// Pull Select
+#define PORTA_PCR1              *(volatile uint32_t *)0x40049004 // Pin Control Register n
+#define PORTA_PCR2              *(volatile uint32_t *)0x40049008 // Pin Control Register n
+#define PORTA_PCR3              *(volatile uint32_t *)0x4004900C // Pin Control Register n
+#define PORTA_PCR4              *(volatile uint32_t *)0x40049010 // Pin Control Register n
+#define PORTA_PCR5              *(volatile uint32_t *)0x40049014 // Pin Control Register n
+#define PORTA_PCR6              *(volatile uint32_t *)0x40049018 // Pin Control Register n
+#define PORTA_PCR7              *(volatile uint32_t *)0x4004901C // Pin Control Register n
+#define PORTA_PCR8              *(volatile uint32_t *)0x40049020 // Pin Control Register n
+#define PORTA_PCR9              *(volatile uint32_t *)0x40049024 // Pin Control Register n
+#define PORTA_PCR10             *(volatile uint32_t *)0x40049028 // Pin Control Register n
+#define PORTA_PCR11             *(volatile uint32_t *)0x4004902C // Pin Control Register n
+#define PORTA_PCR12             *(volatile uint32_t *)0x40049030 // Pin Control Register n
+#define PORTA_PCR13             *(volatile uint32_t *)0x40049034 // Pin Control Register n
+#define PORTA_PCR14             *(volatile uint32_t *)0x40049038 // Pin Control Register n
+#define PORTA_PCR15             *(volatile uint32_t *)0x4004903C // Pin Control Register n
+#define PORTA_PCR16             *(volatile uint32_t *)0x40049040 // Pin Control Register n
+#define PORTA_PCR17             *(volatile uint32_t *)0x40049044 // Pin Control Register n
+#define PORTA_PCR18             *(volatile uint32_t *)0x40049048 // Pin Control Register n
+#define PORTA_PCR19             *(volatile uint32_t *)0x4004904C // Pin Control Register n
+#define PORTA_PCR20             *(volatile uint32_t *)0x40049050 // Pin Control Register n
+#define PORTA_PCR21             *(volatile uint32_t *)0x40049054 // Pin Control Register n
+#define PORTA_PCR22             *(volatile uint32_t *)0x40049058 // Pin Control Register n
+#define PORTA_PCR23             *(volatile uint32_t *)0x4004905C // Pin Control Register n
+#define PORTA_PCR24             *(volatile uint32_t *)0x40049060 // Pin Control Register n
+#define PORTA_PCR25             *(volatile uint32_t *)0x40049064 // Pin Control Register n
+#define PORTA_PCR26             *(volatile uint32_t *)0x40049068 // Pin Control Register n
+#define PORTA_PCR27             *(volatile uint32_t *)0x4004906C // Pin Control Register n
+#define PORTA_PCR28             *(volatile uint32_t *)0x40049070 // Pin Control Register n
+#define PORTA_PCR29             *(volatile uint32_t *)0x40049074 // Pin Control Register n
+#define PORTA_PCR30             *(volatile uint32_t *)0x40049078 // Pin Control Register n
+#define PORTA_PCR31             *(volatile uint32_t *)0x4004907C // Pin Control Register n
+#define PORTA_GPCLR             *(volatile uint32_t *)0x40049080 // Global Pin Control Low Register
+#define PORTA_GPCHR             *(volatile uint32_t *)0x40049084 // Global Pin Control High Register
+#define PORTA_ISFR              *(volatile uint32_t *)0x400490A0 // Interrupt Status Flag Register
+#define PORTB_PCR0              *(volatile uint32_t *)0x4004A000 // Pin Control Register n
+#define PORTB_PCR1              *(volatile uint32_t *)0x4004A004 // Pin Control Register n
+#define PORTB_PCR2              *(volatile uint32_t *)0x4004A008 // Pin Control Register n
+#define PORTB_PCR3              *(volatile uint32_t *)0x4004A00C // Pin Control Register n
+#define PORTB_PCR4              *(volatile uint32_t *)0x4004A010 // Pin Control Register n
+#define PORTB_PCR5              *(volatile uint32_t *)0x4004A014 // Pin Control Register n
+#define PORTB_PCR6              *(volatile uint32_t *)0x4004A018 // Pin Control Register n
+#define PORTB_PCR7              *(volatile uint32_t *)0x4004A01C // Pin Control Register n
+#define PORTB_PCR8              *(volatile uint32_t *)0x4004A020 // Pin Control Register n
+#define PORTB_PCR9              *(volatile uint32_t *)0x4004A024 // Pin Control Register n
+#define PORTB_PCR10             *(volatile uint32_t *)0x4004A028 // Pin Control Register n
+#define PORTB_PCR11             *(volatile uint32_t *)0x4004A02C // Pin Control Register n
+#define PORTB_PCR12             *(volatile uint32_t *)0x4004A030 // Pin Control Register n
+#define PORTB_PCR13             *(volatile uint32_t *)0x4004A034 // Pin Control Register n
+#define PORTB_PCR14             *(volatile uint32_t *)0x4004A038 // Pin Control Register n
+#define PORTB_PCR15             *(volatile uint32_t *)0x4004A03C // Pin Control Register n
+#define PORTB_PCR16             *(volatile uint32_t *)0x4004A040 // Pin Control Register n
+#define PORTB_PCR17             *(volatile uint32_t *)0x4004A044 // Pin Control Register n
+#define PORTB_PCR18             *(volatile uint32_t *)0x4004A048 // Pin Control Register n
+#define PORTB_PCR19             *(volatile uint32_t *)0x4004A04C // Pin Control Register n
+#define PORTB_PCR20             *(volatile uint32_t *)0x4004A050 // Pin Control Register n
+#define PORTB_PCR21             *(volatile uint32_t *)0x4004A054 // Pin Control Register n
+#define PORTB_PCR22             *(volatile uint32_t *)0x4004A058 // Pin Control Register n
+#define PORTB_PCR23             *(volatile uint32_t *)0x4004A05C // Pin Control Register n
+#define PORTB_PCR24             *(volatile uint32_t *)0x4004A060 // Pin Control Register n
+#define PORTB_PCR25             *(volatile uint32_t *)0x4004A064 // Pin Control Register n
+#define PORTB_PCR26             *(volatile uint32_t *)0x4004A068 // Pin Control Register n
+#define PORTB_PCR27             *(volatile uint32_t *)0x4004A06C // Pin Control Register n
+#define PORTB_PCR28             *(volatile uint32_t *)0x4004A070 // Pin Control Register n
+#define PORTB_PCR29             *(volatile uint32_t *)0x4004A074 // Pin Control Register n
+#define PORTB_PCR30             *(volatile uint32_t *)0x4004A078 // Pin Control Register n
+#define PORTB_PCR31             *(volatile uint32_t *)0x4004A07C // Pin Control Register n
+#define PORTB_GPCLR             *(volatile uint32_t *)0x4004A080 // Global Pin Control Low Register
+#define PORTB_GPCHR             *(volatile uint32_t *)0x4004A084 // Global Pin Control High Register
+#define PORTB_ISFR              *(volatile uint32_t *)0x4004A0A0 // Interrupt Status Flag Register
+#define PORTC_PCR0              *(volatile uint32_t *)0x4004B000 // Pin Control Register n
+#define PORTC_PCR1              *(volatile uint32_t *)0x4004B004 // Pin Control Register n
+#define PORTC_PCR2              *(volatile uint32_t *)0x4004B008 // Pin Control Register n
+#define PORTC_PCR3              *(volatile uint32_t *)0x4004B00C // Pin Control Register n
+#define PORTC_PCR4              *(volatile uint32_t *)0x4004B010 // Pin Control Register n
+#define PORTC_PCR5              *(volatile uint32_t *)0x4004B014 // Pin Control Register n
+#define PORTC_PCR6              *(volatile uint32_t *)0x4004B018 // Pin Control Register n
+#define PORTC_PCR7              *(volatile uint32_t *)0x4004B01C // Pin Control Register n
+#define PORTC_PCR8              *(volatile uint32_t *)0x4004B020 // Pin Control Register n
+#define PORTC_PCR9              *(volatile uint32_t *)0x4004B024 // Pin Control Register n
+#define PORTC_PCR10             *(volatile uint32_t *)0x4004B028 // Pin Control Register n
+#define PORTC_PCR11             *(volatile uint32_t *)0x4004B02C // Pin Control Register n
+#define PORTC_PCR12             *(volatile uint32_t *)0x4004B030 // Pin Control Register n
+#define PORTC_PCR13             *(volatile uint32_t *)0x4004B034 // Pin Control Register n
+#define PORTC_PCR14             *(volatile uint32_t *)0x4004B038 // Pin Control Register n
+#define PORTC_PCR15             *(volatile uint32_t *)0x4004B03C // Pin Control Register n
+#define PORTC_PCR16             *(volatile uint32_t *)0x4004B040 // Pin Control Register n
+#define PORTC_PCR17             *(volatile uint32_t *)0x4004B044 // Pin Control Register n
+#define PORTC_PCR18             *(volatile uint32_t *)0x4004B048 // Pin Control Register n
+#define PORTC_PCR19             *(volatile uint32_t *)0x4004B04C // Pin Control Register n
+#define PORTC_PCR20             *(volatile uint32_t *)0x4004B050 // Pin Control Register n
+#define PORTC_PCR21             *(volatile uint32_t *)0x4004B054 // Pin Control Register n
+#define PORTC_PCR22             *(volatile uint32_t *)0x4004B058 // Pin Control Register n
+#define PORTC_PCR23             *(volatile uint32_t *)0x4004B05C // Pin Control Register n
+#define PORTC_PCR24             *(volatile uint32_t *)0x4004B060 // Pin Control Register n
+#define PORTC_PCR25             *(volatile uint32_t *)0x4004B064 // Pin Control Register n
+#define PORTC_PCR26             *(volatile uint32_t *)0x4004B068 // Pin Control Register n
+#define PORTC_PCR27             *(volatile uint32_t *)0x4004B06C // Pin Control Register n
+#define PORTC_PCR28             *(volatile uint32_t *)0x4004B070 // Pin Control Register n
+#define PORTC_PCR29             *(volatile uint32_t *)0x4004B074 // Pin Control Register n
+#define PORTC_PCR30             *(volatile uint32_t *)0x4004B078 // Pin Control Register n
+#define PORTC_PCR31             *(volatile uint32_t *)0x4004B07C // Pin Control Register n
+#define PORTC_GPCLR             *(volatile uint32_t *)0x4004B080 // Global Pin Control Low Register
+#define PORTC_GPCHR             *(volatile uint32_t *)0x4004B084 // Global Pin Control High Register
+#define PORTC_ISFR              *(volatile uint32_t *)0x4004B0A0 // Interrupt Status Flag Register
+#define PORTD_PCR0              *(volatile uint32_t *)0x4004C000 // Pin Control Register n
+#define PORTD_PCR1              *(volatile uint32_t *)0x4004C004 // Pin Control Register n
+#define PORTD_PCR2              *(volatile uint32_t *)0x4004C008 // Pin Control Register n
+#define PORTD_PCR3              *(volatile uint32_t *)0x4004C00C // Pin Control Register n
+#define PORTD_PCR4              *(volatile uint32_t *)0x4004C010 // Pin Control Register n
+#define PORTD_PCR5              *(volatile uint32_t *)0x4004C014 // Pin Control Register n
+#define PORTD_PCR6              *(volatile uint32_t *)0x4004C018 // Pin Control Register n
+#define PORTD_PCR7              *(volatile uint32_t *)0x4004C01C // Pin Control Register n
+#define PORTD_PCR8              *(volatile uint32_t *)0x4004C020 // Pin Control Register n
+#define PORTD_PCR9              *(volatile uint32_t *)0x4004C024 // Pin Control Register n
+#define PORTD_PCR10             *(volatile uint32_t *)0x4004C028 // Pin Control Register n
+#define PORTD_PCR11             *(volatile uint32_t *)0x4004C02C // Pin Control Register n
+#define PORTD_PCR12             *(volatile uint32_t *)0x4004C030 // Pin Control Register n
+#define PORTD_PCR13             *(volatile uint32_t *)0x4004C034 // Pin Control Register n
+#define PORTD_PCR14             *(volatile uint32_t *)0x4004C038 // Pin Control Register n
+#define PORTD_PCR15             *(volatile uint32_t *)0x4004C03C // Pin Control Register n
+#define PORTD_PCR16             *(volatile uint32_t *)0x4004C040 // Pin Control Register n
+#define PORTD_PCR17             *(volatile uint32_t *)0x4004C044 // Pin Control Register n
+#define PORTD_PCR18             *(volatile uint32_t *)0x4004C048 // Pin Control Register n
+#define PORTD_PCR19             *(volatile uint32_t *)0x4004C04C // Pin Control Register n
+#define PORTD_PCR20             *(volatile uint32_t *)0x4004C050 // Pin Control Register n
+#define PORTD_PCR21             *(volatile uint32_t *)0x4004C054 // Pin Control Register n
+#define PORTD_PCR22             *(volatile uint32_t *)0x4004C058 // Pin Control Register n
+#define PORTD_PCR23             *(volatile uint32_t *)0x4004C05C // Pin Control Register n
+#define PORTD_PCR24             *(volatile uint32_t *)0x4004C060 // Pin Control Register n
+#define PORTD_PCR25             *(volatile uint32_t *)0x4004C064 // Pin Control Register n
+#define PORTD_PCR26             *(volatile uint32_t *)0x4004C068 // Pin Control Register n
+#define PORTD_PCR27             *(volatile uint32_t *)0x4004C06C // Pin Control Register n
+#define PORTD_PCR28             *(volatile uint32_t *)0x4004C070 // Pin Control Register n
+#define PORTD_PCR29             *(volatile uint32_t *)0x4004C074 // Pin Control Register n
+#define PORTD_PCR30             *(volatile uint32_t *)0x4004C078 // Pin Control Register n
+#define PORTD_PCR31             *(volatile uint32_t *)0x4004C07C // Pin Control Register n
+#define PORTD_GPCLR             *(volatile uint32_t *)0x4004C080 // Global Pin Control Low Register
+#define PORTD_GPCHR             *(volatile uint32_t *)0x4004C084 // Global Pin Control High Register
+#define PORTD_ISFR              *(volatile uint32_t *)0x4004C0A0 // Interrupt Status Flag Register
+#define PORTE_PCR0              *(volatile uint32_t *)0x4004D000 // Pin Control Register n
+#define PORTE_PCR1              *(volatile uint32_t *)0x4004D004 // Pin Control Register n
+#define PORTE_PCR2              *(volatile uint32_t *)0x4004D008 // Pin Control Register n
+#define PORTE_PCR3              *(volatile uint32_t *)0x4004D00C // Pin Control Register n
+#define PORTE_PCR4              *(volatile uint32_t *)0x4004D010 // Pin Control Register n
+#define PORTE_PCR5              *(volatile uint32_t *)0x4004D014 // Pin Control Register n
+#define PORTE_PCR6              *(volatile uint32_t *)0x4004D018 // Pin Control Register n
+#define PORTE_PCR7              *(volatile uint32_t *)0x4004D01C // Pin Control Register n
+#define PORTE_PCR8              *(volatile uint32_t *)0x4004D020 // Pin Control Register n
+#define PORTE_PCR9              *(volatile uint32_t *)0x4004D024 // Pin Control Register n
+#define PORTE_PCR10             *(volatile uint32_t *)0x4004D028 // Pin Control Register n
+#define PORTE_PCR11             *(volatile uint32_t *)0x4004D02C // Pin Control Register n
+#define PORTE_PCR12             *(volatile uint32_t *)0x4004D030 // Pin Control Register n
+#define PORTE_PCR13             *(volatile uint32_t *)0x4004D034 // Pin Control Register n
+#define PORTE_PCR14             *(volatile uint32_t *)0x4004D038 // Pin Control Register n
+#define PORTE_PCR15             *(volatile uint32_t *)0x4004D03C // Pin Control Register n
+#define PORTE_PCR16             *(volatile uint32_t *)0x4004D040 // Pin Control Register n
+#define PORTE_PCR17             *(volatile uint32_t *)0x4004D044 // Pin Control Register n
+#define PORTE_PCR18             *(volatile uint32_t *)0x4004D048 // Pin Control Register n
+#define PORTE_PCR19             *(volatile uint32_t *)0x4004D04C // Pin Control Register n
+#define PORTE_PCR20             *(volatile uint32_t *)0x4004D050 // Pin Control Register n
+#define PORTE_PCR21             *(volatile uint32_t *)0x4004D054 // Pin Control Register n
+#define PORTE_PCR22             *(volatile uint32_t *)0x4004D058 // Pin Control Register n
+#define PORTE_PCR23             *(volatile uint32_t *)0x4004D05C // Pin Control Register n
+#define PORTE_PCR24             *(volatile uint32_t *)0x4004D060 // Pin Control Register n
+#define PORTE_PCR25             *(volatile uint32_t *)0x4004D064 // Pin Control Register n
+#define PORTE_PCR26             *(volatile uint32_t *)0x4004D068 // Pin Control Register n
+#define PORTE_PCR27             *(volatile uint32_t *)0x4004D06C // Pin Control Register n
+#define PORTE_PCR28             *(volatile uint32_t *)0x4004D070 // Pin Control Register n
+#define PORTE_PCR29             *(volatile uint32_t *)0x4004D074 // Pin Control Register n
+#define PORTE_PCR30             *(volatile uint32_t *)0x4004D078 // Pin Control Register n
+#define PORTE_PCR31             *(volatile uint32_t *)0x4004D07C // Pin Control Register n
+#define PORTE_GPCLR             *(volatile uint32_t *)0x4004D080 // Global Pin Control Low Register
+#define PORTE_GPCHR             *(volatile uint32_t *)0x4004D084 // Global Pin Control High Register
+#define PORTE_ISFR              *(volatile uint32_t *)0x4004D0A0 // Interrupt Status Flag Register
+
+// Chapter 12: System Integration Module (SIM)
+#define SIM_SOPT1               *(volatile uint32_t *)0x40047000 // System Options Register 1
+#define SIM_SOPT1CFG            *(volatile uint32_t *)0x40047004 // SOPT1 Configuration Register
+#define SIM_SOPT2               *(volatile uint32_t *)0x40048004 // System Options Register 2
+#define SIM_SOPT2_USBSRC		(uint32_t)0x00040000		// 0=USB_CLKIN, 1=FFL/PLL 
+#define SIM_SOPT2_PLLFLLSEL		(uint32_t)0x00010000		// 0=FLL, 1=PLL
+#define SIM_SOPT2_TRACECLKSEL		(uint32_t)0x00001000		// 0=MCGOUTCLK, 1=CPU
+#define SIM_SOPT2_PTD7PAD		(uint32_t)0x00000800		// 0=normal, 1=double drive PTD7
+#define SIM_SOPT2_CLKOUTSEL(n)		(uint32_t)(((n) & 7) << 5)	// Selects the clock to output on the CLKOUT pin.
+#define SIM_SOPT2_RTCCLKOUTSEL		(uint32_t)0x00000010		// RTC clock out select
+#define SIM_SOPT4               *(volatile uint32_t *)0x4004800C // System Options Register 4
+#define SIM_SOPT5               *(volatile uint32_t *)0x40048010 // System Options Register 5
+#define SIM_SOPT7               *(volatile uint32_t *)0x40048018 // System Options Register 7
+#define SIM_SDID                *(const    uint32_t *)0x40048024 // System Device Identification Register
+#define SIM_SCGC4               *(volatile uint32_t *)0x40048034 // System Clock Gating Control Register 4
+#define SIM_SCGC4_VREF			(uint32_t)0x00100000		// VREF Clock Gate Control
+#define SIM_SCGC4_CMP			(uint32_t)0x00080000		// Comparator Clock Gate Control
+#define SIM_SCGC4_USBOTG		(uint32_t)0x00040000		// USB Clock Gate Control
+#define SIM_SCGC4_UART2			(uint32_t)0x00001000		// UART2 Clock Gate Control
+#define SIM_SCGC4_UART1			(uint32_t)0x00000800		// UART1 Clock Gate Control
+#define SIM_SCGC4_UART0			(uint32_t)0x00000400		// UART0 Clock Gate Control
+#define SIM_SCGC4_I2C0			(uint32_t)0x00000040		// I2C0 Clock Gate Control
+#define SIM_SCGC4_CMT			(uint32_t)0x00000004		// CMT Clock Gate Control
+#define SIM_SCGC4_EWM			(uint32_t)0x00000002		// EWM Clock Gate Control
+#define SIM_SCGC5               *(volatile uint32_t *)0x40048038 // System Clock Gating Control Register 5
+#define SIM_SCGC5_PORTE			(uint32_t)0x00002000		// Port E Clock Gate Control
+#define SIM_SCGC5_PORTD			(uint32_t)0x00001000		// Port D Clock Gate Control
+#define SIM_SCGC5_PORTC			(uint32_t)0x00000800		// Port C Clock Gate Control
+#define SIM_SCGC5_PORTB			(uint32_t)0x00000400		// Port B Clock Gate Control
+#define SIM_SCGC5_PORTA			(uint32_t)0x00000200		// Port A Clock Gate Control
+#define SIM_SCGC5_TSI			(uint32_t)0x00000020		// Touch Sense Input TSI Clock Gate Control
+#define SIM_SCGC5_LPTIMER		(uint32_t)0x00000001		// Low Power Timer Access Control
+#define SIM_SCGC6               *(volatile uint32_t *)0x4004803C // System Clock Gating Control Register 6
+#define SIM_SCGC6_RTC			(uint32_t)0x20000000		// RTC Access
+#define SIM_SCGC6_ADC0			(uint32_t)0x08000000		// ADC0 Clock Gate Control
+#define SIM_SCGC6_FTM1			(uint32_t)0x02000000		// FTM1 Clock Gate Control
+#define SIM_SCGC6_FTM0			(uint32_t)0x01000000		// FTM0 Clock Gate Control
+#define SIM_SCGC6_PIT			(uint32_t)0x00800000		// PIT Clock Gate Control
+#define SIM_SCGC6_PDB			(uint32_t)0x00400000		// PDB Clock Gate Control
+#define SIM_SCGC6_USBDCD		(uint32_t)0x00200000		// USB DCD Clock Gate Control
+#define SIM_SCGC6_CRC			(uint32_t)0x00040000		// CRC Clock Gate Control
+#define SIM_SCGC6_I2S			(uint32_t)0x00008000		// I2S Clock Gate Control
+#define SIM_SCGC6_SPI0			(uint32_t)0x00001000		// SPI0 Clock Gate Control
+#define SIM_SCGC6_DMAMUX		(uint32_t)0x00000002		// DMA Mux Clock Gate Control
+#define SIM_SCGC6_FTFL			(uint32_t)0x00000001		// Flash Memory Clock Gate Control
+#define SIM_SCGC7               *(volatile uint32_t *)0x40048040 // System Clock Gating Control Register 7
+#define SIM_SCGC7_DMA			(uint32_t)0x00000020		// DMA Clock Gate Control
+#define SIM_CLKDIV1             *(volatile uint32_t *)0x40048044 // System Clock Divider Register 1
+#define SIM_CLKDIV1_OUTDIV1(n)		(uint32_t)(((n) & 0x0F) << 28)	// divide value for the core/system clock
+#define SIM_CLKDIV1_OUTDIV2(n)		(uint32_t)(((n) & 0x0F) << 24)	// divide value for the peripheral clock
+#define SIM_CLKDIV1_OUTDIV4(n)		(uint32_t)(((n) & 0x0F) << 16)	// divide value for the flash clock
+#define SIM_CLKDIV2             *(volatile uint32_t *)0x40048048 // System Clock Divider Register 2
+#define SIM_CLKDIV2_USBDIV(n)		(uint32_t)(((n) & 0x07) << 1)
+#define SIM_CLKDIV2_USBFRAC		(uint32_t)0x01
+#define SIM_FCFG1               *(const    uint32_t *)0x4004804C // Flash Configuration Register 1
+#define SIM_FCFG2               *(const    uint32_t *)0x40048050 // Flash Configuration Register 2
+#define SIM_UIDH                *(const    uint32_t *)0x40048054 // Unique Identification Register High
+#define SIM_UIDMH               *(const    uint32_t *)0x40048058 // Unique Identification Register Mid-High
+#define SIM_UIDML               *(const    uint32_t *)0x4004805C // Unique Identification Register Mid Low
+#define SIM_UIDL                *(const    uint32_t *)0x40048060 // Unique Identification Register Low
+
+// Chapter 13: Reset Control Module (RCM)
+#define RCM_SRS0                *(volatile uint8_t  *)0x4007F000 // System Reset Status Register 0
+#define RCM_SRS1                *(volatile uint8_t  *)0x4007F001 // System Reset Status Register 1
+#define RCM_RPFC                *(volatile uint8_t  *)0x4007F004 // Reset Pin Filter Control Register
+#define RCM_RPFW                *(volatile uint8_t  *)0x4007F005 // Reset Pin Filter Width Register
+#define RCM_MR                  *(volatile uint8_t  *)0x4007F007 // Mode Register
+
+// Chapter 14: System Mode Controller
+#define SMC_PMPROT              *(volatile uint8_t  *)0x4007E000 // Power Mode Protection Register
+#define SMC_PMPROT_AVLP			(uint8_t)0x20			// Allow very low power modes
+#define SMC_PMPROT_ALLS			(uint8_t)0x08			// Allow low leakage stop mode
+#define SMC_PMPROT_AVLLS		(uint8_t)0x02			// Allow very low leakage stop mode
+#define SMC_PMCTRL              *(volatile uint8_t  *)0x4007E001 // Power Mode Control Register
+#define SMC_PMCTRL_LPWUI		(uint8_t)0x80			// Low Power Wake Up on Interrupt
+#define SMC_PMCTRL_RUNM(n)		(uint8_t)(((n) & 0x03) << 5)	// Run Mode Control
+#define SMC_PMCTRL_STOPA		(uint8_t)0x08			// Stop Aborted
+#define SMC_PMCTRL_STOPM(n)		(uint8_t)((n) & 0x07)		// Stop Mode Control
+#define SMC_VLLSCTRL            *(volatile uint8_t  *)0x4007E002 // VLLS Control Register
+#define SMC_VLLSCTRL_PORPO		(uint8_t)0x20			// POR Power Option
+#define SMC_VLLSCTRL_VLLSM(n)		(uint8_t)((n) & 0x07)		// VLLS Mode Control
+#define SMC_PMSTAT              *(volatile uint8_t  *)0x4007E003 // Power Mode Status Register
+#define SMC_PMSTAT_RUN			(uint8_t)0x01			// Current power mode is RUN
+#define SMC_PMSTAT_STOP			(uint8_t)0x02			// Current power mode is STOP
+#define SMC_PMSTAT_VLPR			(uint8_t)0x04			// Current power mode is VLPR
+#define SMC_PMSTAT_VLPW			(uint8_t)0x08			// Current power mode is VLPW
+#define SMC_PMSTAT_VLPS			(uint8_t)0x10			// Current power mode is VLPS
+#define SMC_PMSTAT_LLS			(uint8_t)0x20			// Current power mode is LLS
+#define SMC_PMSTAT_VLLS			(uint8_t)0x40			// Current power mode is VLLS
+
+// Chapter 15: Power Management Controller
+#define PMC_LVDSC1              *(volatile uint8_t  *)0x4007D000 // Low Voltage Detect Status And Control 1 register
+#define PMC_LVDSC1_LVDF			(uint8_t)0x80			// Low-Voltage Detect Flag
+#define PMC_LVDSC1_LVDACK		(uint8_t)0x40			// Low-Voltage Detect Acknowledge
+#define PMC_LVDSC1_LVDIE		(uint8_t)0x20			// Low-Voltage Detect Interrupt Enable
+#define PMC_LVDSC1_LVDRE		(uint8_t)0x10			// Low-Voltage Detect Reset Enable
+#define PMC_LVDSC1_LVDV(n)		(uint8_t)((n) & 0x03)		// Low-Voltage Detect Voltage Select
+#define PMC_LVDSC2              *(volatile uint8_t  *)0x4007D001 // Low Voltage Detect Status And Control 2 register
+#define PMC_LVDSC2_LVWF			(uint8_t)0x80			// Low-Voltage Warning Flag
+#define PMC_LVDSC2_LVWACK		(uint8_t)0x40			// Low-Voltage Warning Acknowledge
+#define PMC_LVDSC2_LVWIE		(uint8_t)0x20			// Low-Voltage Warning Interrupt Enable
+#define PMC_LVDSC2_LVWV(n)		(uint8_t)((n) & 0x03)		// Low-Voltage Warning Voltage Select
+#define PMC_REGSC               *(volatile uint8_t  *)0x4007D002 // Regulator Status And Control register
+#define PMC_REGSC_BGEN			(uint8_t)0x10			// Bandgap Enable In VLPx Operation
+#define PMC_REGSC_ACKISO		(uint8_t)0x08			// Acknowledge Isolation
+#define PMC_REGSC_REGONS		(uint8_t)0x04			// Regulator In Run Regulation Status
+#define PMC_REGSC_BGBE			(uint8_t)0x01			// Bandgap Buffer Enable
+
+// Chapter 16: Low-Leakage Wakeup Unit (LLWU)
+#define LLWU_PE1                *(volatile uint8_t  *)0x4007C000 // LLWU Pin Enable 1 register
+#define LLWU_PE2                *(volatile uint8_t  *)0x4007C001 // LLWU Pin Enable 2 register
+#define LLWU_PE3                *(volatile uint8_t  *)0x4007C002 // LLWU Pin Enable 3 register
+#define LLWU_PE4                *(volatile uint8_t  *)0x4007C003 // LLWU Pin Enable 4 register
+#define LLWU_ME                 *(volatile uint8_t  *)0x4007C004 // LLWU Module Enable register
+#define LLWU_F1                 *(volatile uint8_t  *)0x4007C005 // LLWU Flag 1 register
+#define LLWU_F2                 *(volatile uint8_t  *)0x4007C006 // LLWU Flag 2 register
+#define LLWU_F3                 *(volatile uint8_t  *)0x4007C007 // LLWU Flag 3 register
+#define LLWU_FILT1              *(volatile uint8_t  *)0x4007C008 // LLWU Pin Filter 1 register
+#define LLWU_FILT2              *(volatile uint8_t  *)0x4007C009 // LLWU Pin Filter 2 register
+#define LLWU_RST                *(volatile uint8_t  *)0x4007C00A // LLWU Reset Enable register
+
+// Chapter 17: Miscellaneous Control Module (MCM)
+#define MCM_PLASC               *(volatile uint16_t *)0xE0080008 // Crossbar Switch (AXBS) Slave Configuration
+#define MCM_PLAMC               *(volatile uint16_t *)0xE008000A // Crossbar Switch (AXBS) Master Configuration
+#define MCM_PLACR               *(volatile uint32_t *)0xE008000C // Crossbar Switch (AXBS) Control Register
+
+// Chapter 20: Direct Memory Access Multiplexer (DMAMUX)
+#define DMAMUX0_CHCFG0          *(volatile uint8_t  *)0x40021000 // Channel Configuration register
+#define DMAMUX0_CHCFG1          *(volatile uint8_t  *)0x40021001 // Channel Configuration register
+#define DMAMUX0_CHCFG2          *(volatile uint8_t  *)0x40021002 // Channel Configuration register
+#define DMAMUX0_CHCFG3          *(volatile uint8_t  *)0x40021003 // Channel Configuration register
+#define DMAMUX0_CHCFG4          *(volatile uint8_t  *)0x40021004 // Channel Configuration register
+#define DMAMUX0_CHCFG5          *(volatile uint8_t  *)0x40021005 // Channel Configuration register
+#define DMAMUX0_CHCFG6          *(volatile uint8_t  *)0x40021006 // Channel Configuration register
+#define DMAMUX0_CHCFG7          *(volatile uint8_t  *)0x40021007 // Channel Configuration register
+#define DMAMUX0_CHCFG8          *(volatile uint8_t  *)0x40021008 // Channel Configuration register
+#define DMAMUX0_CHCFG9          *(volatile uint8_t  *)0x40021009 // Channel Configuration register
+#define DMAMUX0_CHCFG10         *(volatile uint8_t  *)0x4002100A // Channel Configuration register
+#define DMAMUX0_CHCFG11         *(volatile uint8_t  *)0x4002100B // Channel Configuration register
+#define DMAMUX0_CHCFG12         *(volatile uint8_t  *)0x4002100C // Channel Configuration register
+#define DMAMUX0_CHCFG13         *(volatile uint8_t  *)0x4002100D // Channel Configuration register
+#define DMAMUX0_CHCFG14         *(volatile uint8_t  *)0x4002100E // Channel Configuration register
+#define DMAMUX0_CHCFG15         *(volatile uint8_t  *)0x4002100F // Channel Configuration register
+#define DMAMUX_DISABLE			0
+#define DMAMUX_TRIG			64
+#define DMAMUX_ENABLE			128
+#define DMAMUX_SOURCE_UART0_RX		2
+#define DMAMUX_SOURCE_UART0_TX		3
+#define DMAMUX_SOURCE_UART1_RX		4
+#define DMAMUX_SOURCE_UART1_TX		5
+#define DMAMUX_SOURCE_UART2_RX		6
+#define DMAMUX_SOURCE_UART2_TX		7
+#define DMAMUX_SOURCE_I2S0_RX		14
+#define DMAMUX_SOURCE_I2S0_TX		15
+#define DMAMUX_SOURCE_SPI0_RX		16
+#define DMAMUX_SOURCE_SPI0_TX		17
+#define DMAMUX_SOURCE_I2C0		22
+#define DMAMUX_SOURCE_FTM0_CH0		24
+#define DMAMUX_SOURCE_FTM0_CH1		25
+#define DMAMUX_SOURCE_FTM0_CH2		26
+#define DMAMUX_SOURCE_FTM0_CH3		27
+#define DMAMUX_SOURCE_FTM0_CH4		28
+#define DMAMUX_SOURCE_FTM0_CH5		29
+#define DMAMUX_SOURCE_FTM0_CH6		30
+#define DMAMUX_SOURCE_FTM0_CH7		31
+#define DMAMUX_SOURCE_FTM1_CH0		32
+#define DMAMUX_SOURCE_FTM1_CH1		33
+#define DMAMUX_SOURCE_ADC0		40
+#define DMAMUX_SOURCE_CMP0		42
+#define DMAMUX_SOURCE_CMP1		43
+#define DMAMUX_SOURCE_CMT		47
+#define DMAMUX_SOURCE_PDB		48
+#define DMAMUX_SOURCE_PORTA		49
+#define DMAMUX_SOURCE_PORTB		50
+#define DMAMUX_SOURCE_PORTC		51
+#define DMAMUX_SOURCE_PORTD		52
+#define DMAMUX_SOURCE_PORTE		53
+#define DMAMUX_SOURCE_ALWAYS0		54
+#define DMAMUX_SOURCE_ALWAYS1		55
+#define DMAMUX_SOURCE_ALWAYS2		56
+#define DMAMUX_SOURCE_ALWAYS3		57
+#define DMAMUX_SOURCE_ALWAYS4		58
+#define DMAMUX_SOURCE_ALWAYS5		59
+#define DMAMUX_SOURCE_ALWAYS6		60
+#define DMAMUX_SOURCE_ALWAYS7		61
+#define DMAMUX_SOURCE_ALWAYS8		62
+#define DMAMUX_SOURCE_ALWAYS9		63
+
+// Chapter 21: Direct Memory Access Controller (eDMA)
+#define DMA_CR                  *(volatile uint32_t *)0x40008000 // Control Register
+#define DMA_ES                  *(volatile uint32_t *)0x40008004 // Error Status Register
+#define DMA_ERQ                 *(volatile uint32_t *)0x4000800C // Enable Request Register
+#define DMA_EEI                 *(volatile uint32_t *)0x40008014 // Enable Error Interrupt Register
+#define DMA_CEEI                *(volatile uint8_t  *)0x40008018 // Clear Enable Error Interrupt Register
+#define DMA_SEEI                *(volatile uint8_t  *)0x40008019 // Set Enable Error Interrupt Register
+#define DMA_CERQ                *(volatile uint8_t  *)0x4000801A // Clear Enable Request Register
+#define DMA_SERQ                *(volatile uint8_t  *)0x4000801B // Set Enable Request Register
+#define DMA_CDNE                *(volatile uint8_t  *)0x4000801C // Clear DONE Status Bit Register
+#define DMA_SSRT                *(volatile uint8_t  *)0x4000801D // Set START Bit Register
+#define DMA_CERR                *(volatile uint8_t  *)0x4000801E // Clear Error Register
+#define DMA_CINT                *(volatile uint8_t  *)0x4000801F // Clear Interrupt Request Register
+#define DMA_INT                 *(volatile uint32_t *)0x40008024 // Interrupt Request Register
+#define DMA_ERR                 *(volatile uint32_t *)0x4000802C // Error Register
+#define DMA_HRS                 *(volatile uint32_t *)0x40008034 // Hardware Request Status Register
+#define DMA_DCHPRI3             *(volatile uint8_t  *)0x40008100 // Channel n Priority Register
+#define DMA_DCHPRI2             *(volatile uint8_t  *)0x40008101 // Channel n Priority Register
+#define DMA_DCHPRI1             *(volatile uint8_t  *)0x40008102 // Channel n Priority Register
+#define DMA_DCHPRI0             *(volatile uint8_t  *)0x40008103 // Channel n Priority Register
+
+#define DMA_TCD_ATTR_SMOD(n)		(((n) & 0x1F) << 11)
+#define DMA_TCD_ATTR_SSIZE(n)		(((n) & 0x7) << 8)
+#define DMA_TCD_ATTR_DMOD(n)		(((n) & 0x1F) << 3)
+#define DMA_TCD_ATTR_DSIZE(n)		(((n) & 0x7) << 0)
+#define DMA_TCD_ATTR_SIZE_8BIT		0
+#define DMA_TCD_ATTR_SIZE_16BIT		1
+#define DMA_TCD_ATTR_SIZE_32BIT		2
+#define DMA_TCD_ATTR_SIZE_16BYTE	4
+#define DMA_TCD_ATTR_SIZE_32BYTE	5
+#define DMA_TCD_CSR_BWC(n)		(((n) & 0x3) << 14)
+#define DMA_TCD_CSR_MAJORLINKCH(n)	(((n) & 0x3) << 8)
+#define DMA_TCD_CSR_DONE		0x0080
+#define DMA_TCD_CSR_ACTIVE		0x0040
+#define DMA_TCD_CSR_MAJORELINK		0x0020
+#define DMA_TCD_CSR_ESG			0x0010
+#define DMA_TCD_CSR_DREQ		0x0008
+#define DMA_TCD_CSR_INTHALF		0x0004
+#define DMA_TCD_CSR_INTMAJOR		0x0002
+#define DMA_TCD_CSR_START		0x0001
+
+#define DMA_TCD0_SADDR          *(volatile const void * volatile *)0x40009000 // TCD Source Address
+#define DMA_TCD0_SOFF           *(volatile int16_t *)0x40009004  // TCD Signed Source Address Offset
+#define DMA_TCD0_ATTR           *(volatile uint16_t *)0x40009006 // TCD Transfer Attributes
+#define DMA_TCD0_NBYTES_MLNO    *(volatile uint32_t *)0x40009008 // TCD Minor Byte Count (Minor Loop Disabled)
+#define DMA_TCD0_NBYTES_MLOFFNO *(volatile uint32_t *)0x40009008 // TCD Signed Minor Loop Offset (Minor Loop Enabled and Offset Disabled)
+#define DMA_TCD0_NBYTES_MLOFFYES *(volatile uint32_t *)0x40009008 // TCD Signed Minor Loop Offset (Minor Loop and Offset Enabled)
+#define DMA_TCD0_SLAST          *(volatile int32_t *)0x4000900C  // TCD Last Source Address Adjustment
+#define DMA_TCD0_DADDR          *(volatile void * volatile *)0x40009010 // TCD Destination Address
+#define DMA_TCD0_DOFF           *(volatile int16_t *)0x40009014  // TCD Signed Destination Address Offset
+#define DMA_TCD0_CITER_ELINKYES *(volatile uint16_t *)0x40009016 // TCD Current Minor Loop Link, Major Loop Count, Channel Linking Enabled
+#define DMA_TCD0_CITER_ELINKNO  *(volatile uint16_t *)0x40009016 // ??
+#define DMA_TCD0_DLASTSGA       *(volatile int32_t *)0x40009018  // TCD Last Destination Address Adjustment/Scatter Gather Address
+#define DMA_TCD0_CSR            *(volatile uint16_t *)0x4000901C // TCD Control and Status
+#define DMA_TCD0_BITER_ELINKYES *(volatile uint16_t *)0x4000901E // TCD Beginning Minor Loop Link, Major Loop Count, Channel Linking Enabled
+#define DMA_TCD0_BITER_ELINKNO  *(volatile uint16_t *)0x4000901E // TCD Beginning Minor Loop Link, Major Loop Count, Channel Linking Disabled
+
+#define DMA_TCD1_SADDR          *(volatile const void * volatile *)0x40009020 // TCD Source Address
+#define DMA_TCD1_SOFF           *(volatile int16_t *)0x40009024  // TCD Signed Source Address Offset
+#define DMA_TCD1_ATTR           *(volatile uint16_t *)0x40009026 // TCD Transfer Attributes
+#define DMA_TCD1_NBYTES_MLNO    *(volatile uint32_t *)0x40009028 // TCD Minor Byte Count, Minor Loop Disabled
+#define DMA_TCD1_NBYTES_MLOFFNO *(volatile uint32_t *)0x40009028 // TCD Signed Minor Loop Offset, Minor Loop Enabled and Offset Disabled
+#define DMA_TCD1_NBYTES_MLOFFYES *(volatile uint32_t *)0x40009028 // TCD Signed Minor Loop Offset, Minor Loop and Offset Enabled
+#define DMA_TCD1_SLAST          *(volatile int32_t *)0x4000902C  // TCD Last Source Address Adjustment
+#define DMA_TCD1_DADDR          *(volatile void * volatile *)0x40009030 // TCD Destination Address
+#define DMA_TCD1_DOFF           *(volatile int16_t *)0x40009034  // TCD Signed Destination Address Offset
+#define DMA_TCD1_CITER_ELINKYES *(volatile uint16_t *)0x40009036 // TCD Current Minor Loop Link, Major Loop Count, Channel Linking Enabled
+#define DMA_TCD1_CITER_ELINKNO  *(volatile uint16_t *)0x40009036 // ??
+#define DMA_TCD1_DLASTSGA       *(volatile int32_t *)0x40009038  // TCD Last Destination Address Adjustment/Scatter Gather Address
+#define DMA_TCD1_CSR            *(volatile uint16_t *)0x4000903C // TCD Control and Status
+#define DMA_TCD1_BITER_ELINKYES *(volatile uint16_t *)0x4000903E // TCD Beginning Minor Loop Link, Major Loop Count Channel Linking Enabled
+#define DMA_TCD1_BITER_ELINKNO  *(volatile uint16_t *)0x4000903E // TCD Beginning Minor Loop Link, Major Loop Count, Channel Linking Disabled
+
+#define DMA_TCD2_SADDR          *(volatile const void * volatile *)0x40009040 // TCD Source Address
+#define DMA_TCD2_SOFF           *(volatile int16_t *)0x40009044  // TCD Signed Source Address Offset
+#define DMA_TCD2_ATTR           *(volatile uint16_t *)0x40009046 // TCD Transfer Attributes
+#define DMA_TCD2_NBYTES_MLNO    *(volatile uint32_t *)0x40009048 // TCD Minor Byte Count, Minor Loop Disabled
+#define DMA_TCD2_NBYTES_MLOFFNO *(volatile uint32_t *)0x40009048 // TCD Signed Minor Loop Offset, Minor Loop Enabled and Offset Disabled
+#define DMA_TCD2_NBYTES_MLOFFYES *(volatile uint32_t *)0x40009048 // TCD Signed Minor Loop Offset, Minor Loop and Offset Enabled
+#define DMA_TCD2_SLAST          *(volatile int32_t *)0x4000904C  // TCD Last Source Address Adjustment
+#define DMA_TCD2_DADDR          *(volatile void * volatile *)0x40009050 // TCD Destination Address
+#define DMA_TCD2_DOFF           *(volatile int16_t *)0x40009054  // TCD Signed Destination Address Offset
+#define DMA_TCD2_CITER_ELINKYES *(volatile uint16_t *)0x40009056 // TCD Current Minor Loop Link, Major Loop Count, Channel Linking Enabled
+#define DMA_TCD2_CITER_ELINKNO  *(volatile uint16_t *)0x40009056 // ??
+#define DMA_TCD2_DLASTSGA       *(volatile int32_t *)0x40009058  // TCD Last Destination Address Adjustment/Scatter Gather Address
+#define DMA_TCD2_CSR            *(volatile uint16_t *)0x4000905C // TCD Control and Status
+#define DMA_TCD2_BITER_ELINKYES *(volatile uint16_t *)0x4000905E // TCD Beginning Minor Loop Link, Major Loop Count, Channel Linking Enabled
+#define DMA_TCD2_BITER_ELINKNO  *(volatile uint16_t *)0x4000905E // TCD Beginning Minor Loop Link, Major Loop Count, Channel Linking Disabled
+
+#define DMA_TCD3_SADDR          *(volatile const void * volatile *)0x40009060 // TCD Source Address
+#define DMA_TCD3_SOFF           *(volatile int16_t *)0x40009064  // TCD Signed Source Address Offset
+#define DMA_TCD3_ATTR           *(volatile uint16_t *)0x40009066 // TCD Transfer Attributes
+#define DMA_TCD3_NBYTES_MLNO    *(volatile uint32_t *)0x40009068 // TCD Minor Byte Count, Minor Loop Disabled
+#define DMA_TCD3_NBYTES_MLOFFNO *(volatile uint32_t *)0x40009068 // TCD Signed Minor Loop Offset, Minor Loop Enabled and Offset Disabled
+#define DMA_TCD3_NBYTES_MLOFFYES *(volatile uint32_t *)0x40009068 // TCD Signed Minor Loop Offset, Minor Loop and Offset Enabled
+#define DMA_TCD3_SLAST          *(volatile int32_t *)0x4000906C  // TCD Last Source Address Adjustment
+#define DMA_TCD3_DADDR          *(volatile void * volatile *)0x40009070 // TCD Destination Address
+#define DMA_TCD3_DOFF           *(volatile int16_t *)0x40009074  // TCD Signed Destination Address Offset
+#define DMA_TCD3_CITER_ELINKYES *(volatile uint16_t *)0x40009076 // TCD Current Minor Loop Link, Major Loop Count, Channel Linking Enabled
+#define DMA_TCD3_CITER_ELINKNO  *(volatile uint16_t *)0x40009076 // ??
+#define DMA_TCD3_DLASTSGA       *(volatile int32_t *)0x40009078  // TCD Last Destination Address Adjustment/Scatter Gather Address
+#define DMA_TCD3_CSR            *(volatile uint16_t *)0x4000907C // TCD Control and Status
+#define DMA_TCD3_BITER_ELINKYES *(volatile uint16_t *)0x4000907E // TCD Beginning Minor Loop Link, Major Loop Count ,Channel Linking Enabled
+#define DMA_TCD3_BITER_ELINKNO  *(volatile uint16_t *)0x4000907E // TCD Beginning Minor Loop Link, Major Loop Count ,Channel Linking Disabled
+
+// Chapter 22: External Watchdog Monitor (EWM)
+#define EWM_CTRL                *(volatile uint8_t  *)0x40061000 // Control Register
+#define EWM_SERV                *(volatile uint8_t  *)0x40061001 // Service Register
+#define EWM_CMPL                *(volatile uint8_t  *)0x40061002 // Compare Low Register
+#define EWM_CMPH                *(volatile uint8_t  *)0x40061003 // Compare High Register
+
+// Chapter 23: Watchdog Timer (WDOG)
+#define WDOG_STCTRLH            *(volatile uint16_t *)0x40052000 // Watchdog Status and Control Register High
+#define WDOG_STCTRLH_DISTESTWDOG	(uint16_t)0x4000		// Allows the WDOG's functional test mode to be disabled permanently.
+#define WDOG_STCTRLH_BYTESEL(n)		(uint16_t)(((n) & 3) << 12)	// selects the byte to be tested when the watchdog is in the byte test mode.
+#define WDOG_STCTRLH_TESTSEL		(uint16_t)0x0800
+#define WDOG_STCTRLH_TESTWDOG		(uint16_t)0x0400
+#define WDOG_STCTRLH_WAITEN		(uint16_t)0x0080
+#define WDOG_STCTRLH_STOPEN		(uint16_t)0x0040
+#define WDOG_STCTRLH_DBGEN		(uint16_t)0x0020
+#define WDOG_STCTRLH_ALLOWUPDATE	(uint16_t)0x0010
+#define WDOG_STCTRLH_WINEN		(uint16_t)0x0008
+#define WDOG_STCTRLH_IRQRSTEN		(uint16_t)0x0004
+#define WDOG_STCTRLH_CLKSRC		(uint16_t)0x0002
+#define WDOG_STCTRLH_WDOGEN		(uint16_t)0x0001
+#define WDOG_STCTRLL            *(volatile uint16_t *)0x40052002 // Watchdog Status and Control Register Low
+#define WDOG_TOVALH             *(volatile uint16_t *)0x40052004 // Watchdog Time-out Value Register High
+#define WDOG_TOVALL             *(volatile uint16_t *)0x40052006 // Watchdog Time-out Value Register Low
+#define WDOG_WINH               *(volatile uint16_t *)0x40052008 // Watchdog Window Register High
+#define WDOG_WINL               *(volatile uint16_t *)0x4005200A // Watchdog Window Register Low
+#define WDOG_REFRESH            *(volatile uint16_t *)0x4005200C // Watchdog Refresh register
+#define WDOG_UNLOCK             *(volatile uint16_t *)0x4005200E // Watchdog Unlock register
+#define WDOG_UNLOCK_SEQ1		(uint16_t)0xC520
+#define WDOG_UNLOCK_SEQ2		(uint16_t)0xD928
+#define WDOG_TMROUTH            *(volatile uint16_t *)0x40052010 // Watchdog Timer Output Register High
+#define WDOG_TMROUTL            *(volatile uint16_t *)0x40052012 // Watchdog Timer Output Register Low
+#define WDOG_RSTCNT             *(volatile uint16_t *)0x40052014 // Watchdog Reset Count register
+#define WDOG_PRESC              *(volatile uint16_t *)0x40052016 // Watchdog Prescaler register
+
+// Chapter 24: Multipurpose Clock Generator (MCG)
+#define MCG_C1                  *(volatile uint8_t  *)0x40064000 // MCG Control 1 Register
+#define MCG_C1_IREFSTEN			(uint8_t)0x01			// Internal Reference Stop Enable, Controls whether or not the internal reference clock remains enabled when the MCG enters Stop mode.
+#define MCG_C1_IRCLKEN			(uint8_t)0x02			// Internal Reference Clock Enable, Enables the internal reference clock for use as MCGIRCLK.
+#define MCG_C1_IREFS			(uint8_t)0x04			// Internal Reference Select, Selects the reference clock source for the FLL.
+#define MCG_C1_FRDIV(n)			(uint8_t)(((n) & 0x07) << 3)	// FLL External Reference Divider, Selects the amount to divide down the external reference clock for the FLL
+#define MCG_C1_CLKS(n)			(uint8_t)(((n) & 0x03) << 6)	// Clock Source Select, Selects the clock source for MCGOUTCLK
+#define MCG_C2                  *(volatile uint8_t  *)0x40064001 // MCG Control 2 Register
+#define MCG_C2_IRCS			(uint8_t)0x01			// Internal Reference Clock Select, Selects between the fast or slow internal reference clock source.
+#define MCG_C2_LP			(uint8_t)0x02			// Low Power Select, Controls whether the FLL or PLL is disabled in BLPI and BLPE modes.
+#define MCG_C2_EREFS			(uint8_t)0x04			// External Reference Select, Selects the source for the external reference clock. 
+#define MCG_C2_HGO0			(uint8_t)0x08			// High Gain Oscillator Select, Controls the crystal oscillator mode of operation
+#define MCG_C2_RANGE0(n)		(uint8_t)(((n) & 0x03) << 4)	// Frequency Range Select, Selects the frequency range for the crystal oscillator
+#define MCG_C2_LOCRE0			(uint8_t)0x80			// Loss of Clock Reset Enable, Determines whether an interrupt or a reset request is made following a loss of OSC0 
+#define MCG_C3                  *(volatile uint8_t  *)0x40064002 // MCG Control 3 Register
+#define MCG_C3_SCTRIM(n)		(uint8_t)(n)			// Slow Internal Reference Clock Trim Setting
+#define MCG_C4                  *(volatile uint8_t  *)0x40064003 // MCG Control 4 Register
+#define MCG_C4_SCFTRIM			(uint8_t)0x01			// Slow Internal Reference Clock Fine Trim
+#define MCG_C4_FCTRIM(n)		(uint8_t)(((n) & 0x0F) << 1)	// Fast Internal Reference Clock Trim Setting
+#define MCG_C4_DRST_DRS(n)		(uint8_t)(((n) & 0x03) << 5)	// DCO Range Select
+#define MCG_C4_DMX32			(uint8_t)0x80			// DCO Maximum Frequency with 32.768 kHz Reference, controls whether the DCO frequency range is narrowed
+#define MCG_C5                  *(volatile uint8_t  *)0x40064004 // MCG Control 5 Register
+#define MCG_C5_PRDIV0(n)		(uint8_t)((n) & 0x1F)		// PLL External Reference Divider
+#define MCG_C5_PLLSTEN0			(uint8_t)0x20			// PLL Stop Enable
+#define MCG_C5_PLLCLKEN0		(uint8_t)0x40			// PLL Clock Enable
+#define MCG_C6                  *(volatile uint8_t  *)0x40064005 // MCG Control 6 Register
+#define MCG_C6_VDIV0(n)			(uint8_t)((n) & 0x1F)		// VCO 0 Divider
+#define MCG_C6_CME0			(uint8_t)0x20			// Clock Monitor Enable
+#define MCG_C6_PLLS			(uint8_t)0x40			// PLL Select, Controls whether the PLL or FLL output is selected as the MCG source when CLKS[1:0]=00. 
+#define MCG_C6_LOLIE0			(uint8_t)0x80			// Loss of Lock Interrrupt Enable
+#define MCG_S                   *(volatile uint8_t  *)0x40064006 // MCG Status Register
+#define MCG_S_IRCST			(uint8_t)0x01			// Internal Reference Clock Status
+#define MCG_S_OSCINIT0			(uint8_t)0x02			// OSC Initialization,  resets to 0, is set to 1 after the initialization cycles of the crystal oscillator
+#define MCG_S_CLKST(n)			(uint8_t)(((n) & 0x03) << 2)	// Clock Mode Status, 0=FLL is selected, 1= Internal ref, 2=External ref, 3=PLL
+#define MCG_S_CLKST_MASK		(uint8_t)0x0C
+#define MCG_S_IREFST			(uint8_t)0x10			// Internal Reference Status
+#define MCG_S_PLLST			(uint8_t)0x20			// PLL Select Status
+#define MCG_S_LOCK0			(uint8_t)0x40			// Lock Status, 0=PLL Unlocked, 1=PLL Locked
+#define MCG_S_LOLS0			(uint8_t)0x80			// Loss of Lock Status
+#define MCG_SC                  *(volatile uint8_t  *)0x40064008 // MCG Status and Control Register
+#define MCG_SC_LOCS0			(uint8_t)0x01			// OSC0 Loss of Clock Status
+#define MCG_SC_FCRDIV(n)		(uint8_t)(((n) & 0x07) << 1)	// Fast Clock Internal Reference Divider
+#define MCG_SC_FLTPRSRV			(uint8_t)0x10			// FLL Filter Preserve Enable
+#define MCG_SC_ATMF			(uint8_t)0x20			// Automatic Trim Machine Fail Flag
+#define MCG_SC_ATMS			(uint8_t)0x40			// Automatic Trim Machine Select
+#define MCG_SC_ATME			(uint8_t)0x80			// Automatic Trim Machine Enable
+#define MCG_ATCVH               *(volatile uint8_t  *)0x4006400A // MCG Auto Trim Compare Value High Register
+#define MCG_ATCVL               *(volatile uint8_t  *)0x4006400B // MCG Auto Trim Compare Value Low Register
+#define MCG_C7                  *(volatile uint8_t  *)0x4006400C // MCG Control 7 Register
+#define MCG_C8                  *(volatile uint8_t  *)0x4006400D // MCG Control 8 Register
+
+// Chapter 25: Oscillator (OSC)
+#define OSC0_CR                 *(volatile uint8_t  *)0x40065000 // OSC Control Register
+#define OSC_SC16P			(uint8_t)0x01			// Oscillator 16 pF Capacitor Load Configure
+#define OSC_SC8P			(uint8_t)0x02			// Oscillator 8 pF Capacitor Load Configure
+#define OSC_SC4P			(uint8_t)0x04			// Oscillator 4 pF Capacitor Load Configure
+#define OSC_SC2P			(uint8_t)0x08			// Oscillator 2 pF Capacitor Load Configure
+#define OSC_EREFSTEN			(uint8_t)0x20			// External Reference Stop Enable, Controls whether or not the external reference clock (OSCERCLK) remains enabled when MCU enters Stop mode.
+#define OSC_ERCLKEN			(uint8_t)0x80			// External Reference Enable, Enables external reference clock (OSCERCLK).
+
+// Chapter 27: Flash Memory Controller (FMC)
+#define FMC_PFAPR		*(volatile uint32_t *)0x4001F000	// Flash Access Protection
+#define FMC_PFB0CR		*(volatile uint32_t *)0x4001F004	// Flash Control
+#define FMC_TAGVDW0S0		*(volatile uint32_t *)0x4001F100	// Cache Tag Storage
+#define FMC_TAGVDW0S1		*(volatile uint32_t *)0x4001F104	// Cache Tag Storage
+#define FMC_TAGVDW1S0		*(volatile uint32_t *)0x4001F108	// Cache Tag Storage
+#define FMC_TAGVDW1S1		*(volatile uint32_t *)0x4001F10C	// Cache Tag Storage
+#define FMC_TAGVDW2S0		*(volatile uint32_t *)0x4001F110	// Cache Tag Storage
+#define FMC_TAGVDW2S1		*(volatile uint32_t *)0x4001F114	// Cache Tag Storage
+#define FMC_TAGVDW3S0		*(volatile uint32_t *)0x4001F118	// Cache Tag Storage
+#define FMC_TAGVDW3S1		*(volatile uint32_t *)0x4001F11C	// Cache Tag Storage
+#define FMC_DATAW0S0		*(volatile uint32_t *)0x4001F200	// Cache Data Storage
+#define FMC_DATAW0S1		*(volatile uint32_t *)0x4001F204	// Cache Data Storage
+#define FMC_DATAW1S0		*(volatile uint32_t *)0x4001F208	// Cache Data Storage
+#define FMC_DATAW1S1		*(volatile uint32_t *)0x4001F20C	// Cache Data Storage
+#define FMC_DATAW2S0		*(volatile uint32_t *)0x4001F210	// Cache Data Storage
+#define FMC_DATAW2S1		*(volatile uint32_t *)0x4001F214	// Cache Data Storage
+#define FMC_DATAW3S0		*(volatile uint32_t *)0x4001F218	// Cache Data Storage
+#define FMC_DATAW3S1		*(volatile uint32_t *)0x4001F21C	// Cache Data Storage
+
+// Chapter 28: Flash Memory Module (FTFL)
+#define FTFL_FSTAT		*(volatile uint8_t  *)0x40020000      // Flash Status Register
+#define FTFL_FSTAT_CCIF			(uint8_t)0x80			// Command Complete Interrupt Flag
+#define FTFL_FSTAT_RDCOLERR		(uint8_t)0x40			// Flash Read Collision Error Flag
+#define FTFL_FSTAT_ACCERR		(uint8_t)0x20			// Flash Access Error Flag
+#define FTFL_FSTAT_FPVIOL		(uint8_t)0x10			// Flash Protection Violation Flag
+#define FTFL_FSTAT_MGSTAT0		(uint8_t)0x01			// Memory Controller Command Completion Status Flag
+#define FTFL_FCNFG		*(volatile uint8_t  *)0x40020001      // Flash Configuration Register
+#define FTFL_FCNFG_CCIE			(uint8_t)0x80			// Command Complete Interrupt Enable
+#define FTFL_FCNFG_RDCOLLIE		(uint8_t)0x40			// Read Collision Error Interrupt Enable
+#define FTFL_FCNFG_ERSAREQ		(uint8_t)0x20			// Erase All Request
+#define FTFL_FCNFG_ERSSUSP		(uint8_t)0x10			// Erase Suspend
+#define FTFL_FCNFG_PFLSH		(uint8_t)0x04			// Flash memory configuration
+#define FTFL_FCNFG_RAMRDY		(uint8_t)0x02			// RAM Ready
+#define FTFL_FCNFG_EEERDY		(uint8_t)0x01			// EEPROM Ready
+#define FTFL_FSEC               *(const    uint8_t  *)0x40020002      // Flash Security Register
+#define FTFL_FOPT               *(const    uint8_t  *)0x40020003      // Flash Option Register
+#define FTFL_FCCOB3             *(volatile uint8_t  *)0x40020004      // Flash Common Command Object Registers
+#define FTFL_FCCOB2             *(volatile uint8_t  *)0x40020005
+#define FTFL_FCCOB1             *(volatile uint8_t  *)0x40020006
+#define FTFL_FCCOB0             *(volatile uint8_t  *)0x40020007
+#define FTFL_FCCOB7             *(volatile uint8_t  *)0x40020008
+#define FTFL_FCCOB6             *(volatile uint8_t  *)0x40020009
+#define FTFL_FCCOB5             *(volatile uint8_t  *)0x4002000A
+#define FTFL_FCCOB4             *(volatile uint8_t  *)0x4002000B
+#define FTFL_FCCOBB             *(volatile uint8_t  *)0x4002000C
+#define FTFL_FCCOBA             *(volatile uint8_t  *)0x4002000D
+#define FTFL_FCCOB9             *(volatile uint8_t  *)0x4002000E
+#define FTFL_FCCOB8             *(volatile uint8_t  *)0x4002000F
+#define FTFL_FPROT3             *(volatile uint8_t  *)0x40020010      // Program Flash Protection Registers
+#define FTFL_FPROT2             *(volatile uint8_t  *)0x40020011      // Program Flash Protection Registers
+#define FTFL_FPROT1             *(volatile uint8_t  *)0x40020012      // Program Flash Protection Registers
+#define FTFL_FPROT0             *(volatile uint8_t  *)0x40020013      // Program Flash Protection Registers
+#define FTFL_FEPROT             *(volatile uint8_t  *)0x40020016      // EEPROM Protection Register
+#define FTFL_FDPROT             *(volatile uint8_t  *)0x40020017      // Data Flash Protection Register
+
+// Chapter 30: Cyclic Redundancy Check (CRC)
+#define CRC_CRC                 *(volatile uint32_t *)0x40032000 // CRC Data register
+#define CRC_GPOLY               *(volatile uint32_t *)0x40032004 // CRC Polynomial register
+#define CRC_CTRL                *(volatile uint32_t *)0x40032008 // CRC Control register
+
+// Chapter 31: Analog-to-Digital Converter (ADC)
+#define ADC0_SC1A               *(volatile uint32_t *)0x4003B000 // ADC status and control registers 1
+#define ADC0_SC1B               *(volatile uint32_t *)0x4003B004 // ADC status and control registers 1
+#define ADC_SC1_COCO			(uint32_t)0x80			// Conversion complete flag
+#define ADC_SC1_AIEN			(uint32_t)0x40			// Interrupt enable
+#define ADC_SC1_DIFF			(uint32_t)0x20			// Differential mode enable
+#define ADC_SC1_ADCH(n)			(uint32_t)((n) & 0x1F)		// Input channel select
+#define ADC0_CFG1               *(volatile uint32_t *)0x4003B008 // ADC configuration register 1
+#define ADC_CFG1_ADLPC			(uint32_t)0x80			// Low-power configuration
+#define ADC_CFG1_ADIV(n)		(uint32_t)(((n) & 3) << 5)	// Clock divide select, 0=direct, 1=div2, 2=div4, 3=div8
+#define ADC_CFG1_ADLSMP			(uint32_t)0x10			// Sample time configuration, 0=Short, 1=Long
+#define ADC_CFG1_MODE(n)		(uint32_t)(((n) & 3) << 2)	// Conversion mode, 0=8 bit, 1=12 bit, 2=10 bit, 3=16 bit
+#define ADC_CFG1_ADICLK(n)		(uint32_t)(((n) & 3) << 0)	// Input clock, 0=bus, 1=bus/2, 2=OSCERCLK, 3=async
+#define ADC0_CFG2               *(volatile uint32_t *)0x4003B00C // Configuration register 2
+#define ADC_CFG2_MUXSEL			(uint32_t)0x10			// 0=a channels, 1=b channels
+#define ADC_CFG2_ADACKEN		(uint32_t)0x08			// async clock enable
+#define ADC_CFG2_ADHSC			(uint32_t)0x04			// High speed configuration
+#define ADC_CFG2_ADLSTS(n)		(uint32_t)(((n) & 3) << 0)	// Sample time, 0=24 cycles, 1=12 cycles, 2=6 cycles, 3=2 cycles
+#define ADC0_RA                 *(volatile uint32_t *)0x4003B010 // ADC data result register
+#define ADC0_RB                 *(volatile uint32_t *)0x4003B014 // ADC data result register
+#define ADC0_CV1                *(volatile uint32_t *)0x4003B018 // Compare value registers
+#define ADC0_CV2                *(volatile uint32_t *)0x4003B01C // Compare value registers
+#define ADC0_SC2                *(volatile uint32_t *)0x4003B020 // Status and control register 2
+#define ADC_SC2_ADACT			(uint32_t)0x80			// Conversion active
+#define ADC_SC2_ADTRG			(uint32_t)0x40			// Conversion trigger select, 0=software, 1=hardware
+#define ADC_SC2_ACFE			(uint32_t)0x20			// Compare function enable
+#define ADC_SC2_ACFGT			(uint32_t)0x10			// Compare function greater than enable
+#define ADC_SC2_ACREN			(uint32_t)0x08			// Compare function range enable
+#define ADC_SC2_DMAEN			(uint32_t)0x04			// DMA enable
+#define ADC_SC2_REFSEL(n)		(uint32_t)(((n) & 3) << 0)	// Voltage reference, 0=vcc/external, 1=1.2 volts
+#define ADC0_SC3                *(volatile uint32_t *)0x4003B024 // Status and control register 3
+#define ADC_SC3_CAL			(uint32_t)0x80			// Calibration, 1=begin, stays set while cal in progress
+#define ADC_SC3_CALF			(uint32_t)0x40			// Calibration failed flag
+#define ADC_SC3_ADCO			(uint32_t)0x08			// Continuous conversion enable
+#define ADC_SC3_AVGE			(uint32_t)0x04			// Hardware average enable
+#define ADC_SC3_AVGS(n)			(uint32_t)(((n) & 3) << 0)	// avg select, 0=4 samples, 1=8 samples, 2=16 samples, 3=32 samples
+#define ADC0_OFS                *(volatile uint32_t *)0x4003B028 // ADC offset correction register
+#define ADC0_PG                 *(volatile uint32_t *)0x4003B02C // ADC plus-side gain register
+#define ADC0_MG                 *(volatile uint32_t *)0x4003B030 // ADC minus-side gain register
+#define ADC0_CLPD               *(volatile uint32_t *)0x4003B034 // ADC plus-side general calibration value register
+#define ADC0_CLPS               *(volatile uint32_t *)0x4003B038 // ADC plus-side general calibration value register
+#define ADC0_CLP4               *(volatile uint32_t *)0x4003B03C // ADC plus-side general calibration value register
+#define ADC0_CLP3               *(volatile uint32_t *)0x4003B040 // ADC plus-side general calibration value register
+#define ADC0_CLP2               *(volatile uint32_t *)0x4003B044 // ADC plus-side general calibration value register
+#define ADC0_CLP1               *(volatile uint32_t *)0x4003B048 // ADC plus-side general calibration value register
+#define ADC0_CLP0               *(volatile uint32_t *)0x4003B04C // ADC plus-side general calibration value register
+#define ADC0_CLMD               *(volatile uint32_t *)0x4003B054 // ADC minus-side general calibration value register
+#define ADC0_CLMS               *(volatile uint32_t *)0x4003B058 // ADC minus-side general calibration value register
+#define ADC0_CLM4               *(volatile uint32_t *)0x4003B05C // ADC minus-side general calibration value register
+#define ADC0_CLM3               *(volatile uint32_t *)0x4003B060 // ADC minus-side general calibration value register
+#define ADC0_CLM2               *(volatile uint32_t *)0x4003B064 // ADC minus-side general calibration value register
+#define ADC0_CLM1               *(volatile uint32_t *)0x4003B068 // ADC minus-side general calibration value register
+#define ADC0_CLM0               *(volatile uint32_t *)0x4003B06C // ADC minus-side general calibration value register
+//#define MCG_C2_RANGE0(n)		(uint8_t)(((n) & 0x03) << 4)	// Frequency Range Select, Selects the frequency range for the crystal oscillator
+//#define MCG_C2_LOCRE0			(uint8_t)0x80			// Loss of Clock Reset Enable, Determines whether an interrupt or a reset request is made following a loss of OSC0 
+
+// Chapter 32: Comparator (CMP)
+#define CMP0_CR0                *(volatile uint8_t  *)0x40073000 // CMP Control Register 0
+#define CMP0_CR1                *(volatile uint8_t  *)0x40073001 // CMP Control Register 1
+#define CMP0_FPR                *(volatile uint8_t  *)0x40073002 // CMP Filter Period Register
+#define CMP0_SCR                *(volatile uint8_t  *)0x40073003 // CMP Status and Control Register
+#define CMP0_DACCR              *(volatile uint8_t  *)0x40073004 // DAC Control Register
+#define CMP0_MUXCR              *(volatile uint8_t  *)0x40073005 // MUX Control Register
+#define CMP1_CR0                *(volatile uint8_t  *)0x40073008 // CMP Control Register 0
+#define CMP1_CR1                *(volatile uint8_t  *)0x40073009 // CMP Control Register 1
+#define CMP1_FPR                *(volatile uint8_t  *)0x4007300A // CMP Filter Period Register
+#define CMP1_SCR                *(volatile uint8_t  *)0x4007300B // CMP Status and Control Register
+#define CMP1_DACCR              *(volatile uint8_t  *)0x4007300C // DAC Control Register
+#define CMP1_MUXCR              *(volatile uint8_t  *)0x4007300D // MUX Control Register
+
+// Chapter 33: Voltage Reference (VREFV1)
+#define VREF_TRM                *(volatile uint8_t  *)0x40074000 // VREF Trim Register
+#define VREF_SC                 *(volatile uint8_t  *)0x40074001 // VREF Status and Control Register
+
+// Chapter 34: Programmable Delay Block (PDB)
+#define PDB0_SC                 *(volatile uint32_t *)0x40036000 // Status and Control Register
+#define PDB_SC_LDMOD(n)			(((n) & 3) << 18)	// Load Mode Select
+#define PDB_SC_PDBEIE			0x00020000		// Sequence Error Interrupt Enable
+#define PDB_SC_SWTRIG			0x00010000		// Software Trigger
+#define PDB_SC_DMAEN			0x00008000		// DMA Enable
+#define PDB_SC_PRESCALER(n)		(((n) & 7) << 12)	// Prescaler Divider Select
+#define PDB_SC_TRGSEL(n)		(((n) & 15) << 8)	// Trigger Input Source Select
+#define PDB_SC_PDBEN			0x00000080		// PDB Enable
+#define PDB_SC_PDBIF			0x00000040		// PDB Interrupt Flag
+#define PDB_SC_PDBIE			0x00000020		// PDB Interrupt Enable.
+#define PDB_SC_MULT(n)			(((n) & 3) << 2)	// Multiplication Factor
+#define PDB_SC_CONT			0x00000002		// Continuous Mode Enable
+#define PDB_SC_LDOK			0x00000001		// Load OK
+#define PDB0_MOD                *(volatile uint32_t *)0x40036004 // Modulus Register
+#define PDB0_CNT                *(volatile uint32_t *)0x40036008 // Counter Register
+#define PDB0_IDLY               *(volatile uint32_t *)0x4003600C // Interrupt Delay Register
+#define PDB0_CH0C1              *(volatile uint32_t *)0x40036010 // Channel n Control Register 1
+#define PDB0_CH0S               *(volatile uint32_t *)0x40036014 // Channel n Status Register
+#define PDB0_CH0DLY0            *(volatile uint32_t *)0x40036018 // Channel n Delay 0 Register
+#define PDB0_CH0DLY1            *(volatile uint32_t *)0x4003601C // Channel n Delay 1 Register
+#define PDB0_POEN               *(volatile uint32_t *)0x40036190 // Pulse-Out n Enable Register
+#define PDB0_PO0DLY             *(volatile uint32_t *)0x40036194 // Pulse-Out n Delay Register
+#define PDB0_PO1DLY             *(volatile uint32_t *)0x40036198 // Pulse-Out n Delay Register
+
+// Chapter 35: FlexTimer Module (FTM)
+#define FTM0_SC                 *(volatile uint32_t *)0x40038000 // Status And Control
+#define FTM_SC_TOF			0x80				// Timer Overflow Flag
+#define FTM_SC_TOIE			0x40				// Timer Overflow Interrupt Enable
+#define FTM_SC_CPWMS			0x20				// Center-Aligned PWM Select
+#define FTM_SC_CLKS(n)			(((n) & 3) << 3)		// Clock Source Selection
+#define FTM_SC_PS(n)			(((n) & 7) << 0)		// Prescale Factor Selection
+#define FTM0_CNT                *(volatile uint32_t *)0x40038004 // Counter
+#define FTM0_MOD                *(volatile uint32_t *)0x40038008 // Modulo
+#define FTM0_C0SC		*(volatile uint32_t *)0x4003800C // Channel 0 Status And Control
+#define FTM0_C0V		*(volatile uint32_t *)0x40038010 // Channel 0 Value
+#define FTM0_C1SC		*(volatile uint32_t *)0x40038014 // Channel 1 Status And Control
+#define FTM0_C1V		*(volatile uint32_t *)0x40038018 // Channel 1 Value
+#define FTM0_C2SC		*(volatile uint32_t *)0x4003801C // Channel 2 Status And Control
+#define FTM0_C2V		*(volatile uint32_t *)0x40038020 // Channel 2 Value
+#define FTM0_C3SC		*(volatile uint32_t *)0x40038024 // Channel 3 Status And Control
+#define FTM0_C3V		*(volatile uint32_t *)0x40038028 // Channel 3 Value
+#define FTM0_C4SC		*(volatile uint32_t *)0x4003802C // Channel 4 Status And Control
+#define FTM0_C4V		*(volatile uint32_t *)0x40038030 // Channel 4 Value
+#define FTM0_C5SC		*(volatile uint32_t *)0x40038034 // Channel 5 Status And Control
+#define FTM0_C5V		*(volatile uint32_t *)0x40038038 // Channel 5 Value
+#define FTM0_C6SC		*(volatile uint32_t *)0x4003803C // Channel 6 Status And Control
+#define FTM0_C6V		*(volatile uint32_t *)0x40038040 // Channel 6 Value
+#define FTM0_C7SC		*(volatile uint32_t *)0x40038044 // Channel 7 Status And Control
+#define FTM0_C7V		*(volatile uint32_t *)0x40038048 // Channel 7 Value
+#define FTM0_CNTIN              *(volatile uint32_t *)0x4003804C // Counter Initial Value
+#define FTM0_STATUS             *(volatile uint32_t *)0x40038050 // Capture And Compare Status
+#define FTM0_MODE               *(volatile uint32_t *)0x40038054 // Features Mode Selection
+#define FTM_MODE_FAULTIE		0x80				// Fault Interrupt Enable
+#define FTM_MODE_FAULTM(n)		(((n) & 3) << 5)		// Fault Control Mode
+#define FTM_MODE_CAPTEST		0x10				// Capture Test Mode Enable
+#define FTM_MODE_PWMSYNC		0x08				// PWM Synchronization Mode
+#define FTM_MODE_WPDIS			0x04				// Write Protection Disable
+#define FTM_MODE_INIT			0x02				// Initialize The Channels Output
+#define FTM_MODE_FTMEN			0x01				// FTM Enable
+#define FTM0_SYNC               *(volatile uint32_t *)0x40038058 // Synchronization
+#define FTM_SYNC_SWSYNC			0x80				// 
+#define FTM_SYNC_TRIG2			0x40				// 
+#define FTM_SYNC_TRIG1			0x20				// 
+#define FTM_SYNC_TRIG0			0x10				// 
+#define FTM_SYNC_SYNCHOM		0x08				// 
+#define FTM_SYNC_REINIT			0x04				// 
+#define FTM_SYNC_CNTMAX			0x02				// 
+#define FTM_SYNC_CNTMIN			0x01				// 
+#define FTM0_OUTINIT            *(volatile uint32_t *)0x4003805C // Initial State For Channels Output
+#define FTM0_OUTMASK            *(volatile uint32_t *)0x40038060 // Output Mask
+#define FTM0_COMBINE            *(volatile uint32_t *)0x40038064 // Function For Linked Channels
+#define FTM0_DEADTIME           *(volatile uint32_t *)0x40038068 // Deadtime Insertion Control
+#define FTM0_EXTTRIG            *(volatile uint32_t *)0x4003806C // FTM External Trigger
+#define FTM0_POL                *(volatile uint32_t *)0x40038070 // Channels Polarity
+#define FTM0_FMS                *(volatile uint32_t *)0x40038074 // Fault Mode Status
+#define FTM0_FILTER             *(volatile uint32_t *)0x40038078 // Input Capture Filter Control
+#define FTM0_FLTCTRL            *(volatile uint32_t *)0x4003807C // Fault Control
+#define FTM0_QDCTRL             *(volatile uint32_t *)0x40038080 // Quadrature Decoder Control And Status
+#define FTM0_CONF               *(volatile uint32_t *)0x40038084 // Configuration
+#define FTM0_FLTPOL             *(volatile uint32_t *)0x40038088 // FTM Fault Input Polarity
+#define FTM0_SYNCONF            *(volatile uint32_t *)0x4003808C // Synchronization Configuration
+#define FTM0_INVCTRL            *(volatile uint32_t *)0x40038090 // FTM Inverting Control
+#define FTM0_SWOCTRL            *(volatile uint32_t *)0x40038094 // FTM Software Output Control
+#define FTM0_PWMLOAD            *(volatile uint32_t *)0x40038098 // FTM PWM Load
+#define FTM1_SC                 *(volatile uint32_t *)0x40039000 // Status And Control
+#define FTM1_CNT                *(volatile uint32_t *)0x40039004 // Counter
+#define FTM1_MOD                *(volatile uint32_t *)0x40039008 // Modulo
+#define FTM1_C0SC		*(volatile uint32_t *)0x4003900C // Channel 0 Status And Control
+#define FTM1_C0V		*(volatile uint32_t *)0x40039010 // Channel 0 Value
+#define FTM1_C1SC		*(volatile uint32_t *)0x40039014 // Channel 1 Status And Control
+#define FTM1_C1V		*(volatile uint32_t *)0x40039018 // Channel 1 Value
+#define FTM1_CNTIN              *(volatile uint32_t *)0x4003904C // Counter Initial Value
+#define FTM1_STATUS             *(volatile uint32_t *)0x40039050 // Capture And Compare Status
+#define FTM1_MODE               *(volatile uint32_t *)0x40039054 // Features Mode Selection
+#define FTM1_SYNC               *(volatile uint32_t *)0x40039058 // Synchronization
+#define FTM1_OUTINIT            *(volatile uint32_t *)0x4003905C // Initial State For Channels Output
+#define FTM1_OUTMASK            *(volatile uint32_t *)0x40039060 // Output Mask
+#define FTM1_COMBINE            *(volatile uint32_t *)0x40039064 // Function For Linked Channels
+#define FTM1_DEADTIME           *(volatile uint32_t *)0x40039068 // Deadtime Insertion Control
+#define FTM1_EXTTRIG            *(volatile uint32_t *)0x4003906C // FTM External Trigger
+#define FTM1_POL                *(volatile uint32_t *)0x40039070 // Channels Polarity
+#define FTM1_FMS                *(volatile uint32_t *)0x40039074 // Fault Mode Status
+#define FTM1_FILTER             *(volatile uint32_t *)0x40039078 // Input Capture Filter Control
+#define FTM1_FLTCTRL            *(volatile uint32_t *)0x4003907C // Fault Control
+#define FTM1_QDCTRL             *(volatile uint32_t *)0x40039080 // Quadrature Decoder Control And Status
+#define FTM1_CONF               *(volatile uint32_t *)0x40039084 // Configuration
+#define FTM1_FLTPOL             *(volatile uint32_t *)0x40039088 // FTM Fault Input Polarity
+#define FTM1_SYNCONF            *(volatile uint32_t *)0x4003908C // Synchronization Configuration
+#define FTM1_INVCTRL            *(volatile uint32_t *)0x40039090 // FTM Inverting Control
+#define FTM1_SWOCTRL            *(volatile uint32_t *)0x40039094 // FTM Software Output Control
+#define FTM1_PWMLOAD            *(volatile uint32_t *)0x40039098 // FTM PWM Load
+
+// Chapter 36: Periodic Interrupt Timer (PIT)
+#define PIT_MCR                 *(volatile uint32_t *)0x40037000 // PIT Module Control Register
+#define PIT_LDVAL0              *(volatile uint32_t *)0x40037100 // Timer Load Value Register
+#define PIT_CVAL0               *(volatile uint32_t *)0x40037104 // Current Timer Value Register
+#define PIT_TCTRL0              *(volatile uint32_t *)0x40037108 // Timer Control Register
+#define PIT_TFLG0               *(volatile uint32_t *)0x4003710C // Timer Flag Register
+#define PIT_LDVAL1              *(volatile uint32_t *)0x40037110 // Timer Load Value Register
+#define PIT_CVAL1               *(volatile uint32_t *)0x40037114 // Current Timer Value Register
+#define PIT_TCTRL1              *(volatile uint32_t *)0x40037118 // Timer Control Register
+#define PIT_TFLG1               *(volatile uint32_t *)0x4003711C // Timer Flag Register
+#define PIT_LDVAL2              *(volatile uint32_t *)0x40037120 // Timer Load Value Register
+#define PIT_CVAL2               *(volatile uint32_t *)0x40037124 // Current Timer Value Register
+#define PIT_TCTRL2              *(volatile uint32_t *)0x40037128 // Timer Control Register
+#define PIT_TFLG2               *(volatile uint32_t *)0x4003712C // Timer Flag Register
+#define PIT_LDVAL3              *(volatile uint32_t *)0x40037130 // Timer Load Value Register
+#define PIT_CVAL3               *(volatile uint32_t *)0x40037134 // Current Timer Value Register
+#define PIT_TCTRL3              *(volatile uint32_t *)0x40037138 // Timer Control Register
+#define PIT_TFLG3               *(volatile uint32_t *)0x4003713C // Timer Flag Register
+
+// Chapter 37: Low-Power Timer (LPTMR)
+#define LPTMR0_CSR              *(volatile uint32_t *)0x40040000 // Low Power Timer Control Status Register
+#define LPTMR0_PSR              *(volatile uint32_t *)0x40040004 // Low Power Timer Prescale Register
+#define LPTMR0_CMR              *(volatile uint32_t *)0x40040008 // Low Power Timer Compare Register
+#define LPTMR0_CNR              *(volatile uint32_t *)0x4004000C // Low Power Timer Counter Register
+
+// Chapter 38: Carrier Modulator Transmitter (CMT)
+#define CMT_CGH1                *(volatile uint8_t  *)0x40062000 // CMT Carrier Generator High Data Register 1
+#define CMT_CGL1                *(volatile uint8_t  *)0x40062001 // CMT Carrier Generator Low Data Register 1
+#define CMT_CGH2                *(volatile uint8_t  *)0x40062002 // CMT Carrier Generator High Data Register 2
+#define CMT_CGL2                *(volatile uint8_t  *)0x40062003 // CMT Carrier Generator Low Data Register 2
+#define CMT_OC                  *(volatile uint8_t  *)0x40062004 // CMT Output Control Register
+#define CMT_MSC                 *(volatile uint8_t  *)0x40062005 // CMT Modulator Status and Control Register
+#define CMT_CMD1                *(volatile uint8_t  *)0x40062006 // CMT Modulator Data Register Mark High
+#define CMT_CMD2                *(volatile uint8_t  *)0x40062007 // CMT Modulator Data Register Mark Low
+#define CMT_CMD3                *(volatile uint8_t  *)0x40062008 // CMT Modulator Data Register Space High
+#define CMT_CMD4                *(volatile uint8_t  *)0x40062009 // CMT Modulator Data Register Space Low
+#define CMT_PPS                 *(volatile uint8_t  *)0x4006200A // CMT Primary Prescaler Register
+#define CMT_DMA                 *(volatile uint8_t  *)0x4006200B // CMT Direct Memory Access Register
+
+// Chapter 39: Real Time Clock (RTC)
+#define RTC_TSR                 *(volatile uint32_t *)0x4003D000 // RTC Time Seconds Register
+#define RTC_TPR                 *(volatile uint32_t *)0x4003D004 // RTC Time Prescaler Register
+#define RTC_TAR                 *(volatile uint32_t *)0x4003D008 // RTC Time Alarm Register
+#define RTC_TCR                 *(volatile uint32_t *)0x4003D00C // RTC Time Compensation Register
+#define RTC_TCR_CIC(n)			(((n) & 255) << 24)		// Compensation Interval Counter
+#define RTC_TCR_TCV(n)			(((n) & 255) << 16)		// Time Compensation Value
+#define RTC_TCR_CIR(n)			(((n) & 255) << 8)		// Compensation Interval Register
+#define RTC_TCR_TCR(n)			(((n) & 255) << 0)		// Time Compensation Register
+#define RTC_CR                  *(volatile uint32_t *)0x4003D010 // RTC Control Register
+#define RTC_CR_SC2P			(uint32_t)0x00002000		// 
+#define RTC_CR_SC4P			(uint32_t)0x00001000		// 
+#define RTC_CR_SC8P			(uint32_t)0x00000800		// 
+#define RTC_CR_SC16P			(uint32_t)0x00000400		// 
+#define RTC_CR_CLKO			(uint32_t)0x00000200		// 
+#define RTC_CR_OSCE			(uint32_t)0x00000100		// 
+#define RTC_CR_UM			(uint32_t)0x00000008		// 
+#define RTC_CR_SUP			(uint32_t)0x00000004		// 
+#define RTC_CR_WPE			(uint32_t)0x00000002		// 
+#define RTC_CR_SWR			(uint32_t)0x00000001		// 
+#define RTC_SR                  *(volatile uint32_t *)0x4003D014 // RTC Status Register
+#define RTC_SR_TCE			(uint32_t)0x00000010		// 
+#define RTC_SR_TAF			(uint32_t)0x00000004		// 
+#define RTC_SR_TOF			(uint32_t)0x00000002		// 
+#define RTC_SR_TIF			(uint32_t)0x00000001		// 
+#define RTC_LR                  *(volatile uint32_t *)0x4003D018 // RTC Lock Register
+#define RTC_IER                 *(volatile uint32_t *)0x4003D01C // RTC Interrupt Enable Register
+#define RTC_WAR                 *(volatile uint32_t *)0x4003D800 // RTC Write Access Register
+#define RTC_RAR                 *(volatile uint32_t *)0x4003D804 // RTC Read Access Register
+
+// Chapter 40: Universal Serial Bus OTG Controller (USBOTG)
+#define USB0_PERID              *(const    uint8_t  *)0x40072000 // Peripheral ID register
+#define USB0_IDCOMP             *(const    uint8_t  *)0x40072004 // Peripheral ID Complement register
+#define USB0_REV                *(const    uint8_t  *)0x40072008 // Peripheral Revision register
+#define USB0_ADDINFO            *(volatile uint8_t  *)0x4007200C // Peripheral Additional Info register
+#define USB0_OTGISTAT           *(volatile uint8_t  *)0x40072010 // OTG Interrupt Status register
+#define USB_OTGISTAT_IDCHG		(uint8_t)0x80			//
+#define USB_OTGISTAT_ONEMSEC		(uint8_t)0x40			//
+#define USB_OTGISTAT_LINE_STATE_CHG	(uint8_t)0x20			//
+#define USB_OTGISTAT_SESSVLDCHG		(uint8_t)0x08			//
+#define USB_OTGISTAT_B_SESS_CHG		(uint8_t)0x04			//
+#define USB_OTGISTAT_AVBUSCHG		(uint8_t)0x01			//
+#define USB0_OTGICR             *(volatile uint8_t  *)0x40072014 // OTG Interrupt Control Register
+#define USB_OTGICR_IDEN			(uint8_t)0x80			// 
+#define USB_OTGICR_ONEMSECEN		(uint8_t)0x40			// 
+#define USB_OTGICR_LINESTATEEN		(uint8_t)0x20			// 
+#define USB_OTGICR_SESSVLDEN		(uint8_t)0x08			// 
+#define USB_OTGICR_BSESSEN		(uint8_t)0x04			// 
+#define USB_OTGICR_AVBUSEN		(uint8_t)0x01			// 
+#define USB0_OTGSTAT            *(volatile uint8_t  *)0x40072018 // OTG Status register
+#define USB_OTGSTAT_ID			(uint8_t)0x80			// 
+#define USB_OTGSTAT_ONEMSECEN		(uint8_t)0x40			// 
+#define USB_OTGSTAT_LINESTATESTABLE	(uint8_t)0x20			// 
+#define USB_OTGSTAT_SESS_VLD		(uint8_t)0x08			// 
+#define USB_OTGSTAT_BSESSEND		(uint8_t)0x04			// 
+#define USB_OTGSTAT_AVBUSVLD		(uint8_t)0x01			// 
+#define USB0_OTGCTL             *(volatile uint8_t  *)0x4007201C // OTG Control Register
+#define USB_OTGCTL_DPHIGH		(uint8_t)0x80			// 
+#define USB_OTGCTL_DPLOW		(uint8_t)0x20			// 
+#define USB_OTGCTL_DMLOW		(uint8_t)0x10			// 
+#define USB_OTGCTL_OTGEN		(uint8_t)0x04			// 
+#define USB0_ISTAT              *(volatile uint8_t  *)0x40072080 // Interrupt Status Register
+#define USB_ISTAT_STALL			(uint8_t)0x80			// 
+#define USB_ISTAT_ATTACH		(uint8_t)0x40			// 
+#define USB_ISTAT_RESUME		(uint8_t)0x20			// 
+#define USB_ISTAT_SLEEP			(uint8_t)0x10			// 
+#define USB_ISTAT_TOKDNE		(uint8_t)0x08			// 
+#define USB_ISTAT_SOFTOK		(uint8_t)0x04			// 
+#define USB_ISTAT_ERROR			(uint8_t)0x02			// 
+#define USB_ISTAT_USBRST		(uint8_t)0x01			// 
+#define USB0_INTEN              *(volatile uint8_t  *)0x40072084 // Interrupt Enable Register
+#define USB_INTEN_STALLEN		(uint8_t)0x80			// 
+#define USB_INTEN_ATTACHEN		(uint8_t)0x40			// 
+#define USB_INTEN_RESUMEEN		(uint8_t)0x20			// 
+#define USB_INTEN_SLEEPEN		(uint8_t)0x10			// 
+#define USB_INTEN_TOKDNEEN		(uint8_t)0x08			// 
+#define USB_INTEN_SOFTOKEN		(uint8_t)0x04			// 
+#define USB_INTEN_ERROREN		(uint8_t)0x02			// 
+#define USB_INTEN_USBRSTEN		(uint8_t)0x01			// 
+#define USB0_ERRSTAT            *(volatile uint8_t  *)0x40072088 // Error Interrupt Status Register
+#define USB_ERRSTAT_BTSERR		(uint8_t)0x80			// 
+#define USB_ERRSTAT_DMAERR		(uint8_t)0x20			// 
+#define USB_ERRSTAT_BTOERR		(uint8_t)0x10			// 
+#define USB_ERRSTAT_DFN8		(uint8_t)0x08			// 
+#define USB_ERRSTAT_CRC16		(uint8_t)0x04			// 
+#define USB_ERRSTAT_CRC5EOF		(uint8_t)0x02			// 
+#define USB_ERRSTAT_PIDERR		(uint8_t)0x01			// 
+#define USB0_ERREN              *(volatile uint8_t  *)0x4007208C // Error Interrupt Enable Register
+#define USB_ERREN_BTSERREN		(uint8_t)0x80			// 
+#define USB_ERREN_DMAERREN		(uint8_t)0x20			// 
+#define USB_ERREN_BTOERREN		(uint8_t)0x10			// 
+#define USB_ERREN_DFN8EN		(uint8_t)0x08			// 
+#define USB_ERREN_CRC16EN		(uint8_t)0x04			// 
+#define USB_ERREN_CRC5EOFEN		(uint8_t)0x02			// 
+#define USB_ERREN_PIDERREN		(uint8_t)0x01			// 
+#define USB0_STAT               *(volatile uint8_t  *)0x40072090 // Status Register
+#define USB_STAT_TX			(uint8_t)0x08			// 
+#define USB_STAT_ODD			(uint8_t)0x04			// 
+#define USB_STAT_ENDP(n)		(uint8_t)((n) >> 4)		// 
+#define USB0_CTL                *(volatile uint8_t  *)0x40072094 // Control Register
+#define USB_CTL_JSTATE			(uint8_t)0x80			// 
+#define USB_CTL_SE0			(uint8_t)0x40			// 
+#define USB_CTL_TXSUSPENDTOKENBUSY	(uint8_t)0x20			// 
+#define USB_CTL_RESET			(uint8_t)0x10			// 
+#define USB_CTL_HOSTMODEEN		(uint8_t)0x08			// 
+#define USB_CTL_RESUME			(uint8_t)0x04			// 
+#define USB_CTL_ODDRST			(uint8_t)0x02			// 
+#define USB_CTL_USBENSOFEN		(uint8_t)0x01			// 
+#define USB0_ADDR               *(volatile uint8_t  *)0x40072098 // Address Register
+#define USB0_BDTPAGE1           *(volatile uint8_t  *)0x4007209C // BDT Page Register 1
+#define USB0_FRMNUML            *(volatile uint8_t  *)0x400720A0 // Frame Number Register Low
+#define USB0_FRMNUMH            *(volatile uint8_t  *)0x400720A4 // Frame Number Register High
+#define USB0_TOKEN              *(volatile uint8_t  *)0x400720A8 // Token Register
+#define USB0_SOFTHLD            *(volatile uint8_t  *)0x400720AC // SOF Threshold Register
+#define USB0_BDTPAGE2           *(volatile uint8_t  *)0x400720B0 // BDT Page Register 2
+#define USB0_BDTPAGE3           *(volatile uint8_t  *)0x400720B4 // BDT Page Register 3
+#define USB0_ENDPT0             *(volatile uint8_t  *)0x400720C0 // Endpoint Control Register
+#define USB_ENDPT_HOSTWOHUB		(uint8_t)0x80			// host only, enable low speed
+#define USB_ENDPT_RETRYDIS		(uint8_t)0x40			// host only, set to disable NAK retry
+#define USB_ENDPT_EPCTLDIS		(uint8_t)0x10			// 0=control, 1=bulk, interrupt, isync
+#define USB_ENDPT_EPRXEN		(uint8_t)0x08			// enables the endpoint for RX transfers.
+#define USB_ENDPT_EPTXEN		(uint8_t)0x04			// enables the endpoint for TX transfers.
+#define USB_ENDPT_EPSTALL		(uint8_t)0x02			// set to stall endpoint
+#define USB_ENDPT_EPHSHK		(uint8_t)0x01			// enable handshaking during a transaction, generally set unless Isochronous
+#define USB0_ENDPT1             *(volatile uint8_t  *)0x400720C4 // Endpoint Control Register
+#define USB0_ENDPT2             *(volatile uint8_t  *)0x400720C8 // Endpoint Control Register
+#define USB0_ENDPT3             *(volatile uint8_t  *)0x400720CC // Endpoint Control Register
+#define USB0_ENDPT4             *(volatile uint8_t  *)0x400720D0 // Endpoint Control Register
+#define USB0_ENDPT5             *(volatile uint8_t  *)0x400720D4 // Endpoint Control Register
+#define USB0_ENDPT6             *(volatile uint8_t  *)0x400720D8 // Endpoint Control Register
+#define USB0_ENDPT7             *(volatile uint8_t  *)0x400720DC // Endpoint Control Register
+#define USB0_ENDPT8             *(volatile uint8_t  *)0x400720E0 // Endpoint Control Register
+#define USB0_ENDPT9             *(volatile uint8_t  *)0x400720E4 // Endpoint Control Register
+#define USB0_ENDPT10            *(volatile uint8_t  *)0x400720E8 // Endpoint Control Register
+#define USB0_ENDPT11            *(volatile uint8_t  *)0x400720EC // Endpoint Control Register
+#define USB0_ENDPT12            *(volatile uint8_t  *)0x400720F0 // Endpoint Control Register
+#define USB0_ENDPT13            *(volatile uint8_t  *)0x400720F4 // Endpoint Control Register
+#define USB0_ENDPT14            *(volatile uint8_t  *)0x400720F8 // Endpoint Control Register
+#define USB0_ENDPT15            *(volatile uint8_t  *)0x400720FC // Endpoint Control Register
+#define USB0_USBCTRL            *(volatile uint8_t  *)0x40072100 // USB Control Register
+#define USB_USBCTRL_SUSP		(uint8_t)0x80			// Places the USB transceiver into the suspend state.
+#define USB_USBCTRL_PDE			(uint8_t)0x40			// Enables the weak pulldowns on the USB transceiver.
+#define USB0_OBSERVE            *(volatile uint8_t  *)0x40072104 // USB OTG Observe Register
+#define USB_OBSERVE_DPPU		(uint8_t)0x80			// 
+#define USB_OBSERVE_DPPD		(uint8_t)0x40			// 
+#define USB_OBSERVE_DMPD		(uint8_t)0x10			// 
+#define USB0_CONTROL            *(volatile uint8_t  *)0x40072108 // USB OTG Control Register
+#define USB_CONTROL_DPPULLUPNONOTG	(uint8_t)0x10			//  Provides control of the DP PULLUP in the USB OTG module, if USB is configured in non-OTG device mode.
+#define USB0_USBTRC0            *(volatile uint8_t  *)0x4007210C // USB Transceiver Control Register 0
+#define USB_USBTRC_USBRESET		(uint8_t)0x80			//
+#define USB_USBTRC_USBRESMEN		(uint8_t)0x20			//
+#define USB_USBTRC_SYNC_DET		(uint8_t)0x02			//
+#define USB_USBTRC_USB_RESUME_INT	(uint8_t)0x01			//
+#define USB0_USBFRMADJUST       *(volatile uint8_t  *)0x40072114 // Frame Adjust Register
+
+// Chapter 41: USB Device Charger Detection Module (USBDCD)
+#define USBDCD_CONTROL          *(volatile uint32_t *)0x40035000 // Control register
+#define USBDCD_CLOCK            *(volatile uint32_t *)0x40035004 // Clock register
+#define USBDCD_STATUS           *(volatile uint32_t *)0x40035008 // Status register
+#define USBDCD_TIMER0           *(volatile uint32_t *)0x40035010 // TIMER0 register
+#define USBDCD_TIMER1           *(volatile uint32_t *)0x40035014 // TIMER1 register
+#define USBDCD_TIMER2           *(volatile uint32_t *)0x40035018 // TIMER2 register
+
+// Chapter 43: SPI (DSPI)
+#define SPI0_MCR                *(volatile uint32_t *)0x4002C000 // DSPI Module Configuration Register
+#define SPI_MCR_MSTR			(uint32_t)0x80000000		// Master/Slave Mode Select
+#define SPI_MCR_CONT_SCKE		(uint32_t)0x40000000		// 
+#define SPI_MCR_DCONF(n)		(((n) & 3) << 28)		// 
+#define SPI_MCR_FRZ			(uint32_t)0x08000000		// 
+#define SPI_MCR_MTFE			(uint32_t)0x04000000		// 
+#define SPI_MCR_ROOE			(uint32_t)0x01000000		// 
+#define SPI_MCR_PCSIS(n)		(((n) & 0x1F) << 16)		//
+#define SPI_MCR_DOZE			(uint32_t)0x00008000		// 
+#define SPI_MCR_MDIS			(uint32_t)0x00004000		// 
+#define SPI_MCR_DIS_TXF			(uint32_t)0x00002000		// 
+#define SPI_MCR_DIS_RXF			(uint32_t)0x00001000		// 
+#define SPI_MCR_CLR_TXF			(uint32_t)0x00000800		// 
+#define SPI_MCR_CLR_RXF			(uint32_t)0x00000400		// 
+#define SPI_MCR_SMPL_PT(n)		(((n) & 3) << 8)		//
+#define SPI_MCR_HALT			(uint32_t)0x00000001		// 
+#define SPI0_TCR                *(volatile uint32_t *)0x4002C008 // DSPI Transfer Count Register
+#define SPI0_CTAR0              *(volatile uint32_t *)0x4002C00C // DSPI Clock and Transfer Attributes Register, In Master Mode
+#define SPI_CTAR_DBR			(uint32_t)0x80000000		// Double Baud Rate
+#define SPI_CTAR_FMSZ(n)		(((n) & 15) << 27)		// Frame Size (+1)
+#define SPI_CTAR_CPOL			(uint32_t)0x04000000		// Clock Polarity
+#define SPI_CTAR_CPHA			(uint32_t)0x02000000		// Clock Phase
+#define SPI_CTAR_LSBFE			(uint32_t)0x01000000		// LSB First
+#define SPI_CTAR_PCSSCK(n)		(((n) & 3) << 22)		// PCS to SCK Delay Prescaler
+#define SPI_CTAR_PASC(n)		(((n) & 3) << 20)		// After SCK Delay Prescaler
+#define SPI_CTAR_PDT(n)			(((n) & 3) << 18)		// Delay after Transfer Prescaler
+#define SPI_CTAR_PBR(n)			(((n) & 3) << 16)		// Baud Rate Prescaler
+#define SPI_CTAR_CSSCK(n)		(((n) & 15) << 12)		// PCS to SCK Delay Scaler
+#define SPI_CTAR_ASC(n)			(((n) & 15) << 8)		// After SCK Delay Scaler
+#define SPI_CTAR_DT(n)			(((n) & 15) << 4)		// Delay After Transfer Scaler
+#define SPI_CTAR_BR(n)			(((n) & 15) << 0)		// Baud Rate Scaler
+#define SPI0_CTAR0_SLAVE        *(volatile uint32_t *)0x4002C00C // DSPI Clock and Transfer Attributes Register, In Slave Mode
+#define SPI0_CTAR1              *(volatile uint32_t *)0x4002C010 // DSPI Clock and Transfer Attributes Register, In Master Mode
+#define SPI0_SR                 *(volatile uint32_t *)0x4002C02C // DSPI Status Register
+#define SPI_SR_TCF			(uint32_t)0x80000000		// Transfer Complete Flag
+#define SPI_SR_TXRXS			(uint32_t)0x40000000		// TX and RX Status
+#define SPI_SR_EOQF			(uint32_t)0x10000000		// End of Queue Flag
+#define SPI_SR_TFUF			(uint32_t)0x08000000		// Transmit FIFO Underflow Flag
+#define SPI_SR_TFFF			(uint32_t)0x02000000		// Transmit FIFO Fill Flag
+#define SPI_SR_RFOF			(uint32_t)0x00080000		// Receive FIFO Overflow Flag
+#define SPI_SR_RFDF			(uint32_t)0x00020000		// Receive FIFO Drain Flag
+#define SPI0_RSER               *(volatile uint32_t *)0x4002C030 // DSPI DMA/Interrupt Request Select and Enable Register
+#define SPI0_PUSHR              *(volatile uint32_t *)0x4002C034 // DSPI PUSH TX FIFO Register In Master Mode
+#define SPI_PUSHR_CONT			(uint32_t)0x80000000		// 
+#define SPI_PUSHR_CTAS(n)		(((n) & 7) << 28)		// 
+#define SPI_PUSHR_EOQ			(uint32_t)0x08000000		// 
+#define SPI_PUSHR_CTCNT			(uint32_t)0x04000000		// 
+#define SPI_PUSHR_PCS(n)		(((n) & 31) << 16)		//
+#define SPI0_PUSHR_SLAVE        *(volatile uint32_t *)0x4002C034 // DSPI PUSH TX FIFO Register In Slave Mode
+#define SPI0_POPR               *(volatile uint32_t *)0x4002C038 // DSPI POP RX FIFO Register
+#define SPI0_TXFR0              *(volatile uint32_t *)0x4002C03C // DSPI Transmit FIFO Registers
+#define SPI0_TXFR1              *(volatile uint32_t *)0x4002C040 // DSPI Transmit FIFO Registers
+#define SPI0_TXFR2              *(volatile uint32_t *)0x4002C044 // DSPI Transmit FIFO Registers
+#define SPI0_TXFR3              *(volatile uint32_t *)0x4002C048 // DSPI Transmit FIFO Registers
+#define SPI0_RXFR0              *(volatile uint32_t *)0x4002C07C // DSPI Receive FIFO Registers
+#define SPI0_RXFR1              *(volatile uint32_t *)0x4002C080 // DSPI Receive FIFO Registers
+#define SPI0_RXFR2              *(volatile uint32_t *)0x4002C084 // DSPI Receive FIFO Registers
+#define SPI0_RXFR3              *(volatile uint32_t *)0x4002C088 // DSPI Receive FIFO Registers
+
+// Chapter 44: Inter-Integrated Circuit (I2C)
+#define I2C0_A1                 *(volatile uint8_t  *)0x40066000 // I2C Address Register 1
+#define I2C0_F                  *(volatile uint8_t  *)0x40066001 // I2C Frequency Divider register
+#define I2C0_C1                 *(volatile uint8_t  *)0x40066002 // I2C Control Register 1
+#define I2C_C1_IICEN			(uint8_t)0x80			// I2C Enable
+#define I2C_C1_IICIE			(uint8_t)0x40			// I2C Interrupt Enable
+#define I2C_C1_MST			(uint8_t)0x20			// Master Mode Select
+#define I2C_C1_TX			(uint8_t)0x10			// Transmit Mode Select
+#define I2C_C1_TXAK			(uint8_t)0x08			// Transmit Acknowledge Enable
+#define I2C_C1_RSTA			(uint8_t)0x04			// Repeat START
+#define I2C_C1_WUEN			(uint8_t)0x02			// Wakeup Enable
+#define I2C_C1_DMAEN			(uint8_t)0x01			// DMA Enable
+#define I2C0_S                  *(volatile uint8_t  *)0x40066003 // I2C Status register
+#define I2C_S_TCF			(uint8_t)0x80			// Transfer Complete Flag
+#define I2C_S_IAAS			(uint8_t)0x40			// Addressed As A Slave
+#define I2C_S_BUSY			(uint8_t)0x20			// Bus Busy
+#define I2C_S_ARBL			(uint8_t)0x10			// Arbitration Lost
+#define I2C_S_RAM			(uint8_t)0x08			// Range Address Match
+#define I2C_S_SRW			(uint8_t)0x04			// Slave Read/Write
+#define I2C_S_IICIF			(uint8_t)0x02			// Interrupt Flag
+#define I2C_S_RXAK			(uint8_t)0x01			// Receive Acknowledge
+#define I2C0_D                  *(volatile uint8_t  *)0x40066004 // I2C Data I/O register
+#define I2C0_C2                 *(volatile uint8_t  *)0x40066005 // I2C Control Register 2
+#define I2C_C2_GCAEN			(uint8_t)0x80			// General Call Address Enable
+#define I2C_C2_ADEXT			(uint8_t)0x40			// Address Extension
+#define I2C_C2_HDRS			(uint8_t)0x20			// High Drive Select
+#define I2C_C2_SBRC			(uint8_t)0x10			// Slave Baud Rate Control
+#define I2C_C2_RMEN			(uint8_t)0x08			// Range Address Matching Enable
+#define I2C_C2_AD(n)			((n) & 7)			// Slave Address, upper 3 bits
+#define I2C0_FLT                *(volatile uint8_t  *)0x40066006 // I2C Programmable Input Glitch Filter register
+#define I2C0_RA                 *(volatile uint8_t  *)0x40066007 // I2C Range Address register
+#define I2C0_SMB                *(volatile uint8_t  *)0x40066008 // I2C SMBus Control and Status register
+#define I2C0_A2                 *(volatile uint8_t  *)0x40066009 // I2C Address Register 2
+#define I2C0_SLTH               *(volatile uint8_t  *)0x4006600A // I2C SCL Low Timeout Register High
+#define I2C0_SLTL               *(volatile uint8_t  *)0x4006600B // I2C SCL Low Timeout Register Low
+
+// Chapter 45: Universal Asynchronous Receiver/Transmitter (UART)
+#define UART0_BDH               *(volatile uint8_t  *)0x4006A000 // UART Baud Rate Registers: High
+#define UART0_BDL               *(volatile uint8_t  *)0x4006A001 // UART Baud Rate Registers: Low
+#define UART0_C1                *(volatile uint8_t  *)0x4006A002 // UART Control Register 1
+#define UART_C1_LOOPS			(uint8_t)0x80			// When LOOPS is set, the RxD pin is disconnected from the UART and the transmitter output is internally connected to the receiver input
+#define UART_C1_UARTSWAI		(uint8_t)0x40			// UART Stops in Wait Mode
+#define UART_C1_RSRC			(uint8_t)0x20			// When LOOPS is set, the RSRC field determines the source for the receiver shift register input
+#define UART_C1_M			(uint8_t)0x10			// 9-bit or 8-bit Mode Select
+#define UART_C1_WAKE			(uint8_t)0x08			// Determines which condition wakes the UART
+#define UART_C1_ILT			(uint8_t)0x04			// Idle Line Type Select
+#define UART_C1_PE			(uint8_t)0x02			// Parity Enable
+#define UART_C1_PT			(uint8_t)0x01			// Parity Type, 0=even, 1=odd
+#define UART0_C2                *(volatile uint8_t  *)0x4006A003 // UART Control Register 2
+#define UART_C2_TIE			(uint8_t)0x80			// Transmitter Interrupt or DMA Transfer Enable.
+#define UART_C2_TCIE			(uint8_t)0x40			// Transmission Complete Interrupt Enable
+#define UART_C2_RIE			(uint8_t)0x20			// Receiver Full Interrupt or DMA Transfer Enable
+#define UART_C2_ILIE			(uint8_t)0x10			// Idle Line Interrupt Enable
+#define UART_C2_TE			(uint8_t)0x08			// Transmitter Enable
+#define UART_C2_RE			(uint8_t)0x04			// Receiver Enable
+#define UART_C2_RWU			(uint8_t)0x02			// Receiver Wakeup Control
+#define UART_C2_SBK			(uint8_t)0x01			// Send Break
+#define UART0_S1                *(volatile uint8_t  *)0x4006A004 // UART Status Register 1
+#define UART_S1_TDRE			(uint8_t)0x80			// Transmit Data Register Empty Flag
+#define UART_S1_TC			(uint8_t)0x40			// Transmit Complete Flag
+#define UART_S1_RDRF			(uint8_t)0x20			// Receive Data Register Full Flag
+#define UART_S1_IDLE			(uint8_t)0x10			// Idle Line Flag
+#define UART_S1_OR			(uint8_t)0x08			// Receiver Overrun Flag
+#define UART_S1_NF			(uint8_t)0x04			// Noise Flag
+#define UART_S1_FE			(uint8_t)0x02			// Framing Error Flag
+#define UART_S1_PF			(uint8_t)0x01			// Parity Error Flag
+#define UART0_S2                *(volatile uint8_t  *)0x4006A005 // UART Status Register 2
+#define UART0_C3                *(volatile uint8_t  *)0x4006A006 // UART Control Register 3
+#define UART0_D                 *(volatile uint8_t  *)0x4006A007 // UART Data Register
+#define UART0_MA1               *(volatile uint8_t  *)0x4006A008 // UART Match Address Registers 1
+#define UART0_MA2               *(volatile uint8_t  *)0x4006A009 // UART Match Address Registers 2
+#define UART0_C4                *(volatile uint8_t  *)0x4006A00A // UART Control Register 4
+#define UART0_C5                *(volatile uint8_t  *)0x4006A00B // UART Control Register 5
+#define UART0_ED                *(volatile uint8_t  *)0x4006A00C // UART Extended Data Register
+#define UART0_MODEM             *(volatile uint8_t  *)0x4006A00D // UART Modem Register
+#define UART0_IR                *(volatile uint8_t  *)0x4006A00E // UART Infrared Register
+#define UART0_PFIFO             *(volatile uint8_t  *)0x4006A010 // UART FIFO Parameters
+#define UART_PFIFO_TXFE			(uint8_t)0x80
+#define UART_PFIFO_RXFE			(uint8_t)0x08
+#define UART0_CFIFO             *(volatile uint8_t  *)0x4006A011 // UART FIFO Control Register
+#define UART_CFIFO_TXFLUSH		(uint8_t)0x80			// 
+#define UART_CFIFO_RXFLUSH		(uint8_t)0x40			// 
+#define UART_CFIFO_RXOFE		(uint8_t)0x04			// 
+#define UART_CFIFO_TXOFE		(uint8_t)0x02			// 
+#define UART_CFIFO_RXUFE		(uint8_t)0x01			// 
+#define UART0_SFIFO             *(volatile uint8_t  *)0x4006A012 // UART FIFO Status Register
+#define UART_SFIFO_TXEMPT		(uint8_t)0x80
+#define UART_SFIFO_RXEMPT		(uint8_t)0x40
+#define UART_SFIFO_RXOF			(uint8_t)0x04
+#define UART_SFIFO_TXOF			(uint8_t)0x02
+#define UART_SFIFO_RXUF			(uint8_t)0x01
+#define UART0_TWFIFO            *(volatile uint8_t  *)0x4006A013 // UART FIFO Transmit Watermark
+#define UART0_TCFIFO            *(volatile uint8_t  *)0x4006A014 // UART FIFO Transmit Count
+#define UART0_RWFIFO            *(volatile uint8_t  *)0x4006A015 // UART FIFO Receive Watermark
+#define UART0_RCFIFO            *(volatile uint8_t  *)0x4006A016 // UART FIFO Receive Count
+#define UART0_C7816             *(volatile uint8_t  *)0x4006A018 // UART 7816 Control Register
+#define UART0_IE7816            *(volatile uint8_t  *)0x4006A019 // UART 7816 Interrupt Enable Register
+#define UART0_IS7816            *(volatile uint8_t  *)0x4006A01A // UART 7816 Interrupt Status Register
+#define UART0_WP7816T0          *(volatile uint8_t  *)0x4006A01B // UART 7816 Wait Parameter Register
+#define UART0_WP7816T1          *(volatile uint8_t  *)0x4006A01B // UART 7816 Wait Parameter Register
+#define UART0_WN7816            *(volatile uint8_t  *)0x4006A01C // UART 7816 Wait N Register
+#define UART0_WF7816            *(volatile uint8_t  *)0x4006A01D // UART 7816 Wait FD Register
+#define UART0_ET7816            *(volatile uint8_t  *)0x4006A01E // UART 7816 Error Threshold Register
+#define UART0_TL7816            *(volatile uint8_t  *)0x4006A01F // UART 7816 Transmit Length Register
+#define UART0_C6                *(volatile uint8_t  *)0x4006A021 // UART CEA709.1-B Control Register 6
+#define UART0_PCTH              *(volatile uint8_t  *)0x4006A022 // UART CEA709.1-B Packet Cycle Time Counter High
+#define UART0_PCTL              *(volatile uint8_t  *)0x4006A023 // UART CEA709.1-B Packet Cycle Time Counter Low
+#define UART0_B1T               *(volatile uint8_t  *)0x4006A024 // UART CEA709.1-B Beta1 Timer
+#define UART0_SDTH              *(volatile uint8_t  *)0x4006A025 // UART CEA709.1-B Secondary Delay Timer High
+#define UART0_SDTL              *(volatile uint8_t  *)0x4006A026 // UART CEA709.1-B Secondary Delay Timer Low
+#define UART0_PRE               *(volatile uint8_t  *)0x4006A027 // UART CEA709.1-B Preamble
+#define UART0_TPL               *(volatile uint8_t  *)0x4006A028 // UART CEA709.1-B Transmit Packet Length
+#define UART0_IE                *(volatile uint8_t  *)0x4006A029 // UART CEA709.1-B Interrupt Enable Register
+#define UART0_WB                *(volatile uint8_t  *)0x4006A02A // UART CEA709.1-B WBASE
+#define UART0_S3                *(volatile uint8_t  *)0x4006A02B // UART CEA709.1-B Status Register
+#define UART0_S4                *(volatile uint8_t  *)0x4006A02C // UART CEA709.1-B Status Register
+#define UART0_RPL               *(volatile uint8_t  *)0x4006A02D // UART CEA709.1-B Received Packet Length
+#define UART0_RPREL             *(volatile uint8_t  *)0x4006A02E // UART CEA709.1-B Received Preamble Length
+#define UART0_CPW               *(volatile uint8_t  *)0x4006A02F // UART CEA709.1-B Collision Pulse Width
+#define UART0_RIDT              *(volatile uint8_t  *)0x4006A030 // UART CEA709.1-B Receive Indeterminate Time
+#define UART0_TIDT              *(volatile uint8_t  *)0x4006A031 // UART CEA709.1-B Transmit Indeterminate Time
+#define UART1_BDH               *(volatile uint8_t  *)0x4006B000 // UART Baud Rate Registers: High
+#define UART1_BDL               *(volatile uint8_t  *)0x4006B001 // UART Baud Rate Registers: Low
+#define UART1_C1                *(volatile uint8_t  *)0x4006B002 // UART Control Register 1
+#define UART1_C2                *(volatile uint8_t  *)0x4006B003 // UART Control Register 2
+#define UART1_S1                *(volatile uint8_t  *)0x4006B004 // UART Status Register 1
+#define UART1_S2                *(volatile uint8_t  *)0x4006B005 // UART Status Register 2
+#define UART1_C3                *(volatile uint8_t  *)0x4006B006 // UART Control Register 3
+#define UART1_D                 *(volatile uint8_t  *)0x4006B007 // UART Data Register
+#define UART1_MA1               *(volatile uint8_t  *)0x4006B008 // UART Match Address Registers 1
+#define UART1_MA2               *(volatile uint8_t  *)0x4006B009 // UART Match Address Registers 2
+#define UART1_C4                *(volatile uint8_t  *)0x4006B00A // UART Control Register 4
+#define UART1_C5                *(volatile uint8_t  *)0x4006B00B // UART Control Register 5
+#define UART1_ED                *(volatile uint8_t  *)0x4006B00C // UART Extended Data Register
+#define UART1_MODEM             *(volatile uint8_t  *)0x4006B00D // UART Modem Register
+#define UART1_IR                *(volatile uint8_t  *)0x4006B00E // UART Infrared Register
+#define UART1_PFIFO             *(volatile uint8_t  *)0x4006B010 // UART FIFO Parameters
+#define UART1_CFIFO             *(volatile uint8_t  *)0x4006B011 // UART FIFO Control Register
+#define UART1_SFIFO             *(volatile uint8_t  *)0x4006B012 // UART FIFO Status Register
+#define UART1_TWFIFO            *(volatile uint8_t  *)0x4006B013 // UART FIFO Transmit Watermark
+#define UART1_TCFIFO            *(volatile uint8_t  *)0x4006B014 // UART FIFO Transmit Count
+#define UART1_RWFIFO            *(volatile uint8_t  *)0x4006B015 // UART FIFO Receive Watermark
+#define UART1_RCFIFO            *(volatile uint8_t  *)0x4006B016 // UART FIFO Receive Count
+#define UART1_C7816             *(volatile uint8_t  *)0x4006B018 // UART 7816 Control Register
+#define UART1_IE7816            *(volatile uint8_t  *)0x4006B019 // UART 7816 Interrupt Enable Register
+#define UART1_IS7816            *(volatile uint8_t  *)0x4006B01A // UART 7816 Interrupt Status Register
+#define UART1_WP7816T0          *(volatile uint8_t  *)0x4006B01B // UART 7816 Wait Parameter Register
+#define UART1_WP7816T1          *(volatile uint8_t  *)0x4006B01B // UART 7816 Wait Parameter Register
+#define UART1_WN7816            *(volatile uint8_t  *)0x4006B01C // UART 7816 Wait N Register
+#define UART1_WF7816            *(volatile uint8_t  *)0x4006B01D // UART 7816 Wait FD Register
+#define UART1_ET7816            *(volatile uint8_t  *)0x4006B01E // UART 7816 Error Threshold Register
+#define UART1_TL7816            *(volatile uint8_t  *)0x4006B01F // UART 7816 Transmit Length Register
+#define UART1_C6                *(volatile uint8_t  *)0x4006B021 // UART CEA709.1-B Control Register 6
+#define UART1_PCTH              *(volatile uint8_t  *)0x4006B022 // UART CEA709.1-B Packet Cycle Time Counter High
+#define UART1_PCTL              *(volatile uint8_t  *)0x4006B023 // UART CEA709.1-B Packet Cycle Time Counter Low
+#define UART1_B1T               *(volatile uint8_t  *)0x4006B024 // UART CEA709.1-B Beta1 Timer
+#define UART1_SDTH              *(volatile uint8_t  *)0x4006B025 // UART CEA709.1-B Secondary Delay Timer High
+#define UART1_SDTL              *(volatile uint8_t  *)0x4006B026 // UART CEA709.1-B Secondary Delay Timer Low
+#define UART1_PRE               *(volatile uint8_t  *)0x4006B027 // UART CEA709.1-B Preamble
+#define UART1_TPL               *(volatile uint8_t  *)0x4006B028 // UART CEA709.1-B Transmit Packet Length
+#define UART1_IE                *(volatile uint8_t  *)0x4006B029 // UART CEA709.1-B Interrupt Enable Register
+#define UART1_WB                *(volatile uint8_t  *)0x4006B02A // UART CEA709.1-B WBASE
+#define UART1_S3                *(volatile uint8_t  *)0x4006B02B // UART CEA709.1-B Status Register
+#define UART1_S4                *(volatile uint8_t  *)0x4006B02C // UART CEA709.1-B Status Register
+#define UART1_RPL               *(volatile uint8_t  *)0x4006B02D // UART CEA709.1-B Received Packet Length
+#define UART1_RPREL             *(volatile uint8_t  *)0x4006B02E // UART CEA709.1-B Received Preamble Length
+#define UART1_CPW               *(volatile uint8_t  *)0x4006B02F // UART CEA709.1-B Collision Pulse Width
+#define UART1_RIDT              *(volatile uint8_t  *)0x4006B030 // UART CEA709.1-B Receive Indeterminate Time
+#define UART1_TIDT              *(volatile uint8_t  *)0x4006B031 // UART CEA709.1-B Transmit Indeterminate Time
+#define UART2_BDH               *(volatile uint8_t  *)0x4006C000 // UART Baud Rate Registers: High
+#define UART2_BDL               *(volatile uint8_t  *)0x4006C001 // UART Baud Rate Registers: Low
+#define UART2_C1                *(volatile uint8_t  *)0x4006C002 // UART Control Register 1
+#define UART2_C2                *(volatile uint8_t  *)0x4006C003 // UART Control Register 2
+#define UART2_S1                *(volatile uint8_t  *)0x4006C004 // UART Status Register 1
+#define UART2_S2                *(volatile uint8_t  *)0x4006C005 // UART Status Register 2
+#define UART2_C3                *(volatile uint8_t  *)0x4006C006 // UART Control Register 3
+#define UART2_D                 *(volatile uint8_t  *)0x4006C007 // UART Data Register
+#define UART2_MA1               *(volatile uint8_t  *)0x4006C008 // UART Match Address Registers 1
+#define UART2_MA2               *(volatile uint8_t  *)0x4006C009 // UART Match Address Registers 2
+#define UART2_C4                *(volatile uint8_t  *)0x4006C00A // UART Control Register 4
+#define UART2_C5                *(volatile uint8_t  *)0x4006C00B // UART Control Register 5
+#define UART2_ED                *(volatile uint8_t  *)0x4006C00C // UART Extended Data Register
+#define UART2_MODEM             *(volatile uint8_t  *)0x4006C00D // UART Modem Register
+#define UART2_IR                *(volatile uint8_t  *)0x4006C00E // UART Infrared Register
+#define UART2_PFIFO             *(volatile uint8_t  *)0x4006C010 // UART FIFO Parameters
+#define UART2_CFIFO             *(volatile uint8_t  *)0x4006C011 // UART FIFO Control Register
+#define UART2_SFIFO             *(volatile uint8_t  *)0x4006C012 // UART FIFO Status Register
+#define UART2_TWFIFO            *(volatile uint8_t  *)0x4006C013 // UART FIFO Transmit Watermark
+#define UART2_TCFIFO            *(volatile uint8_t  *)0x4006C014 // UART FIFO Transmit Count
+#define UART2_RWFIFO            *(volatile uint8_t  *)0x4006C015 // UART FIFO Receive Watermark
+#define UART2_RCFIFO            *(volatile uint8_t  *)0x4006C016 // UART FIFO Receive Count
+#define UART2_C7816             *(volatile uint8_t  *)0x4006C018 // UART 7816 Control Register
+#define UART2_IE7816            *(volatile uint8_t  *)0x4006C019 // UART 7816 Interrupt Enable Register
+#define UART2_IS7816            *(volatile uint8_t  *)0x4006C01A // UART 7816 Interrupt Status Register
+#define UART2_WP7816T0          *(volatile uint8_t  *)0x4006C01B // UART 7816 Wait Parameter Register
+#define UART2_WP7816T1          *(volatile uint8_t  *)0x4006C01B // UART 7816 Wait Parameter Register
+#define UART2_WN7816            *(volatile uint8_t  *)0x4006C01C // UART 7816 Wait N Register
+#define UART2_WF7816            *(volatile uint8_t  *)0x4006C01D // UART 7816 Wait FD Register
+#define UART2_ET7816            *(volatile uint8_t  *)0x4006C01E // UART 7816 Error Threshold Register
+#define UART2_TL7816            *(volatile uint8_t  *)0x4006C01F // UART 7816 Transmit Length Register
+#define UART2_C6                *(volatile uint8_t  *)0x4006C021 // UART CEA709.1-B Control Register 6
+#define UART2_PCTH              *(volatile uint8_t  *)0x4006C022 // UART CEA709.1-B Packet Cycle Time Counter High
+#define UART2_PCTL              *(volatile uint8_t  *)0x4006C023 // UART CEA709.1-B Packet Cycle Time Counter Low
+#define UART2_B1T               *(volatile uint8_t  *)0x4006C024 // UART CEA709.1-B Beta1 Timer
+#define UART2_SDTH              *(volatile uint8_t  *)0x4006C025 // UART CEA709.1-B Secondary Delay Timer High
+#define UART2_SDTL              *(volatile uint8_t  *)0x4006C026 // UART CEA709.1-B Secondary Delay Timer Low
+#define UART2_PRE               *(volatile uint8_t  *)0x4006C027 // UART CEA709.1-B Preamble
+#define UART2_TPL               *(volatile uint8_t  *)0x4006C028 // UART CEA709.1-B Transmit Packet Length
+#define UART2_IE                *(volatile uint8_t  *)0x4006C029 // UART CEA709.1-B Interrupt Enable Register
+#define UART2_WB                *(volatile uint8_t  *)0x4006C02A // UART CEA709.1-B WBASE
+#define UART2_S3                *(volatile uint8_t  *)0x4006C02B // UART CEA709.1-B Status Register
+#define UART2_S4                *(volatile uint8_t  *)0x4006C02C // UART CEA709.1-B Status Register
+#define UART2_RPL               *(volatile uint8_t  *)0x4006C02D // UART CEA709.1-B Received Packet Length
+#define UART2_RPREL             *(volatile uint8_t  *)0x4006C02E // UART CEA709.1-B Received Preamble Length
+#define UART2_CPW               *(volatile uint8_t  *)0x4006C02F // UART CEA709.1-B Collision Pulse Width
+#define UART2_RIDT              *(volatile uint8_t  *)0x4006C030 // UART CEA709.1-B Receive Indeterminate Time
+#define UART2_TIDT              *(volatile uint8_t  *)0x4006C031 // UART CEA709.1-B Transmit Indeterminate Time
+
+// Chapter 46: Synchronous Audio Interface (SAI)
+#define I2S0_TCSR               *(volatile uint32_t *)0x4002F000 // SAI Transmit Control Register
+#define I2S0_TCR1               *(volatile uint32_t *)0x4002F004 // SAI Transmit Configuration 1 Register
+#define I2S0_TCR2               *(volatile uint32_t *)0x4002F008 // SAI Transmit Configuration 2 Register
+#define I2S0_TCR3               *(volatile uint32_t *)0x4002F00C // SAI Transmit Configuration 3 Register
+#define I2S0_TCR4               *(volatile uint32_t *)0x4002F010 // SAI Transmit Configuration 4 Register
+#define I2S0_TCR5               *(volatile uint32_t *)0x4002F014 // SAI Transmit Configuration 5 Register
+#define I2S0_TDR0               *(volatile uint32_t *)0x4002F020 // SAI Transmit Data Register
+#define I2S0_TFR0               *(volatile uint32_t *)0x4002F040 // SAI Transmit FIFO Register
+#define I2S0_TMR                *(volatile uint32_t *)0x4002F060 // SAI Transmit Mask Register
+#define I2S0_RCSR               *(volatile uint32_t *)0x4002F080 // SAI Receive Control Register
+#define I2S0_RCR1               *(volatile uint32_t *)0x4002F084 // SAI Receive Configuration 1 Register
+#define I2S0_RCR2               *(volatile uint32_t *)0x4002F088 // SAI Receive Configuration 2 Register
+#define I2S0_RCR3               *(volatile uint32_t *)0x4002F08C // SAI Receive Configuration 3 Register
+#define I2S0_RCR4               *(volatile uint32_t *)0x4002F090 // SAI Receive Configuration 4 Register
+#define I2S0_RCR5               *(volatile uint32_t *)0x4002F094 // SAI Receive Configuration 5 Register
+#define I2S0_RDR0               *(volatile uint32_t *)0x4002F0A0 // SAI Receive Data Register
+#define I2S0_RFR0               *(volatile uint32_t *)0x4002F0C0 // SAI Receive FIFO Register
+#define I2S0_RMR                *(volatile uint32_t *)0x4002F0E0 // SAI Receive Mask Register
+#define I2S0_MCR                *(volatile uint32_t *)0x4002F100 // SAI MCLK Control Register
+#define I2S0_MDR                *(volatile uint32_t *)0x4002F104 // SAI MCLK Divide Register
+
+// Chapter 47: General-Purpose Input/Output (GPIO)
+#define GPIOA_PDOR              *(volatile uint32_t *)0x400FF000 // Port Data Output Register
+#define GPIOA_PSOR              *(volatile uint32_t *)0x400FF004 // Port Set Output Register
+#define GPIOA_PCOR              *(volatile uint32_t *)0x400FF008 // Port Clear Output Register
+#define GPIOA_PTOR              *(volatile uint32_t *)0x400FF00C // Port Toggle Output Register
+#define GPIOA_PDIR              *(volatile uint32_t *)0x400FF010 // Port Data Input Register
+#define GPIOA_PDDR              *(volatile uint32_t *)0x400FF014 // Port Data Direction Register
+#define GPIOB_PDOR              *(volatile uint32_t *)0x400FF040 // Port Data Output Register
+#define GPIOB_PSOR              *(volatile uint32_t *)0x400FF044 // Port Set Output Register
+#define GPIOB_PCOR              *(volatile uint32_t *)0x400FF048 // Port Clear Output Register
+#define GPIOB_PTOR              *(volatile uint32_t *)0x400FF04C // Port Toggle Output Register
+#define GPIOB_PDIR              *(volatile uint32_t *)0x400FF050 // Port Data Input Register
+#define GPIOB_PDDR              *(volatile uint32_t *)0x400FF054 // Port Data Direction Register
+#define GPIOC_PDOR              *(volatile uint32_t *)0x400FF080 // Port Data Output Register
+#define GPIOC_PSOR              *(volatile uint32_t *)0x400FF084 // Port Set Output Register
+#define GPIOC_PCOR              *(volatile uint32_t *)0x400FF088 // Port Clear Output Register
+#define GPIOC_PTOR              *(volatile uint32_t *)0x400FF08C // Port Toggle Output Register
+#define GPIOC_PDIR              *(volatile uint32_t *)0x400FF090 // Port Data Input Register
+#define GPIOC_PDDR              *(volatile uint32_t *)0x400FF094 // Port Data Direction Register
+#define GPIOD_PDOR              *(volatile uint32_t *)0x400FF0C0 // Port Data Output Register
+#define GPIOD_PSOR              *(volatile uint32_t *)0x400FF0C4 // Port Set Output Register
+#define GPIOD_PCOR              *(volatile uint32_t *)0x400FF0C8 // Port Clear Output Register
+#define GPIOD_PTOR              *(volatile uint32_t *)0x400FF0CC // Port Toggle Output Register
+#define GPIOD_PDIR              *(volatile uint32_t *)0x400FF0D0 // Port Data Input Register
+#define GPIOD_PDDR              *(volatile uint32_t *)0x400FF0D4 // Port Data Direction Register
+#define GPIOE_PDOR              *(volatile uint32_t *)0x400FF100 // Port Data Output Register
+#define GPIOE_PSOR              *(volatile uint32_t *)0x400FF104 // Port Set Output Register
+#define GPIOE_PCOR              *(volatile uint32_t *)0x400FF108 // Port Clear Output Register
+#define GPIOE_PTOR              *(volatile uint32_t *)0x400FF10C // Port Toggle Output Register
+#define GPIOE_PDIR              *(volatile uint32_t *)0x400FF110 // Port Data Input Register
+#define GPIOE_PDDR              *(volatile uint32_t *)0x400FF114 // Port Data Direction Register
+
+// Chapter 48: Touch sense input (TSI)
+#define TSI0_GENCS              *(volatile uint32_t *)0x40045000 // General Control and Status Register
+#define TSI_GENCS_LPCLKS		(uint32_t)0x10000000		// 
+#define TSI_GENCS_LPSCNITV(n)		(((n) & 15) << 24)		// 
+#define TSI_GENCS_NSCN(n)		(((n) & 31) << 19)		// 
+#define TSI_GENCS_PS(n)			(((n) & 7) << 16)		// 
+#define TSI_GENCS_EOSF			(uint32_t)0x00008000		// 
+#define TSI_GENCS_OUTRGF		(uint32_t)0x00004000		// 
+#define TSI_GENCS_EXTERF		(uint32_t)0x00002000		// 
+#define TSI_GENCS_OVRF			(uint32_t)0x00001000		// 
+#define TSI_GENCS_SCNIP			(uint32_t)0x00000200		// 
+#define TSI_GENCS_SWTS			(uint32_t)0x00000100		// 
+#define TSI_GENCS_TSIEN			(uint32_t)0x00000080		// 
+#define TSI_GENCS_TSIIE			(uint32_t)0x00000040		// 
+#define TSI_GENCS_ERIE			(uint32_t)0x00000020		// 
+#define TSI_GENCS_ESOR			(uint32_t)0x00000010		// 
+#define TSI_GENCS_STM			(uint32_t)0x00000002		// 
+#define TSI_GENCS_STPE			(uint32_t)0x00000001		// 
+#define TSI0_SCANC              *(volatile uint32_t *)0x40045004 // SCAN Control Register
+#define TSI_SCANC_REFCHRG(n)		(((n) & 15) << 24)		// 
+#define TSI_SCANC_EXTCHRG(n)		(((n) & 7) << 16)		// 
+#define TSI_SCANC_SMOD(n)		(((n) & 255) << 8)		// 
+#define TSI_SCANC_AMCLKS(n)		(((n) & 3) << 3)		// 
+#define TSI_SCANC_AMPSC(n)		(((n) & 7) << 0)		// 
+#define TSI0_PEN                *(volatile uint32_t *)0x40045008 // Pin Enable Register
+#define TSI0_WUCNTR             *(volatile uint32_t *)0x4004500C // Wake-Up Channel Counter Register
+#define TSI0_CNTR1              *(volatile uint32_t *)0x40045100 // Counter Register
+#define TSI0_CNTR3              *(volatile uint32_t *)0x40045104 // Counter Register
+#define TSI0_CNTR5              *(volatile uint32_t *)0x40045108 // Counter Register
+#define TSI0_CNTR7              *(volatile uint32_t *)0x4004510C // Counter Register
+#define TSI0_CNTR9              *(volatile uint32_t *)0x40045110 // Counter Register
+#define TSI0_CNTR11             *(volatile uint32_t *)0x40045114 // Counter Register
+#define TSI0_CNTR13             *(volatile uint32_t *)0x40045118 // Counter Register
+#define TSI0_CNTR15             *(volatile uint32_t *)0x4004511C // Counter Register
+#define TSI0_THRESHOLD          *(volatile uint32_t *)0x40045120 // Low Power Channel Threshold Register
+
+// Nested Vectored Interrupt Controller, Table 3-4 & ARMv7 ref, appendix B3.4 (page 750)
+#define NVIC_ENABLE_IRQ(n)	(*((volatile uint32_t *)0xE000E100 + (n >> 5)) = (1 << (n & 31)))
+#define NVIC_DISABLE_IRQ(n)	(*((volatile uint32_t *)0xE000E180 + (n >> 5)) = (1 << (n & 31)))
+#define NVIC_SET_PENDING(n)	(*((volatile uint32_t *)0xE000E200 + (n >> 5)) = (1 << (n & 31)))
+#define NVIC_CLEAR_PENDING(n)	(*((volatile uint32_t *)0xE000E280 + (n >> 5)) = (1 << (n & 31)))
+
+#define NVIC_ISER0		*(volatile uint32_t *)0xE000E100
+#define NVIC_ISER1		*(volatile uint32_t *)0xE000E104
+#define NVIC_ICER0		*(volatile uint32_t *)0xE000E180
+#define NVIC_ICER1		*(volatile uint32_t *)0xE000E184
+
+//#define NVIC_SET_PRIORITY(n, p)	
+#define IRQ_DMA_CH0		0
+#define IRQ_DMA_CH1		1
+#define IRQ_DMA_CH2		2
+#define IRQ_DMA_CH3		3
+#define IRQ_DMA_ERROR		4
+#define IRQ_FTFL_COMPLETE	6
+#define IRQ_FTFL_COLLISION	7
+#define IRQ_LOW_VOLTAGE		8
+#define IRQ_LLWU		9
+#define IRQ_WDOG		10
+#define IRQ_I2C0		11
+#define IRQ_SPI0		12
+#define IRQ_I2S0_TX		13
+#define IRQ_I2S0_RX		14
+#define IRQ_UART0_LON		15
+#define IRQ_UART0_STATUS	16
+#define IRQ_UART0_ERROR		17
+#define IRQ_UART1_STATUS	18
+#define IRQ_UART1_ERROR		19
+#define IRQ_UART2_STATUS	20
+#define IRQ_UART2_ERROR		21
+#define IRQ_ADC0		22
+#define IRQ_CMP0		23
+#define IRQ_CMP1		24
+#define IRQ_FTM0		25
+#define IRQ_FTM1		26
+#define IRQ_CMT			27
+#define IRQ_RTC_ALARM		28
+#define IRQ_RTC_SECOND		29
+#define IRQ_PIT_CH0		30
+#define IRQ_PIT_CH1		31
+#define IRQ_PIT_CH2		32
+#define IRQ_PIT_CH3		33
+#define IRQ_PDB			34
+#define IRQ_USBOTG		35
+#define IRQ_USBDCD		36
+#define IRQ_TSI			37
+#define IRQ_MCG			38
+#define IRQ_LPTMR		39
+#define IRQ_PORTA		40
+#define IRQ_PORTB		41
+#define IRQ_PORTC		42
+#define IRQ_PORTD		43
+#define IRQ_PORTE		44
+#define IRQ_SOFTWARE		45
+
+
+#define __disable_irq() asm volatile("CPSID i");
+#define __enable_irq()  asm volatile("CPSIE i");
+
+// System Control Space (SCS), ARMv7 ref manual, B3.2, page 708
+#define SCB_CPUID		*(const    uint32_t *)0xE000ED00 // CPUID Base Register
+#define SCB_ICSR		*(volatile uint32_t *)0xE000ED04 // Interrupt Control and State
+#define SCB_ICSR_PENDSTSET		(uint32_t)0x04000000
+#define SCB_VTOR		*(volatile uint32_t *)0xE000ED08 // Vector Table Offset
+#define SCB_AIRCR		*(volatile uint32_t *)0xE000ED0C // Application Interrupt and Reset Control
+#define SCB_SCR			*(volatile uint32_t *)0xE000ED10 // System Control Register
+#define SCB_CCR			*(volatile uint32_t *)0xE000ED14 // Configuration and Control
+#define SCB_SHPR1		*(volatile uint32_t *)0xE000ED18 // System Handler Priority Register 1
+#define SCB_SHPR2		*(volatile uint32_t *)0xE000ED1C // System Handler Priority Register 2
+#define SCB_SHPR3		*(volatile uint32_t *)0xE000ED20 // System Handler Priority Register 3
+#define SCB_SHCSR		*(volatile uint32_t *)0xE000ED24 // System Handler Control and State
+#define SCB_CFSR		*(volatile uint32_t *)0xE000ED28 // Configurable Fault Status Register
+#define SCB_HFSR		*(volatile uint32_t *)0xE000ED2C // HardFault Status
+#define SCB_DFSR		*(volatile uint32_t *)0xE000ED30 // Debug Fault Status
+#define SCB_MMFAR		*(volatile uint32_t *)0xE000ED34 // MemManage Fault Address
+
+#define SYST_CSR		*(volatile uint32_t *)0xE000E010 // SysTick Control and Status
+#define SYST_CSR_COUNTFLAG		(uint32_t)0x00010000
+#define SYST_CSR_CLKSOURCE		(uint32_t)0x00000004
+#define SYST_CSR_TICKINT		(uint32_t)0x00000002
+#define SYST_CSR_ENABLE			(uint32_t)0x00000001
+#define SYST_RVR		*(volatile uint32_t *)0xE000E014 // SysTick Reload Value Register
+#define SYST_CVR		*(volatile uint32_t *)0xE000E018 // SysTick Current Value Register
+#define SYST_CALIB		*(const    uint32_t *)0xE000E01C // SysTick Calibration Value
+
+
+#define ARM_DEMCR               *(volatile uint32_t *)0xE000EDFC // Debug Exception and Monitor Control
+#define ARM_DEMCR_TRCENA		(1 << 24)        // Enable debugging & monitoring blocks
+#define ARM_DWT_CTRL            *(volatile uint32_t *)0xE0001000 // DWT control register
+#define ARM_DWT_CTRL_CYCCNTENA          (1 << 0)                // Enable cycle count
+#define ARM_DWT_CYCCNT          *(volatile uint32_t *)0xE0001004 // Cycle count register
+
+
+extern void nmi_isr(void);
+extern void hard_fault_isr(void);
+extern void memmanage_fault_isr(void);
+extern void bus_fault_isr(void);
+extern void usage_fault_isr(void);
+extern void svcall_isr(void);
+extern void debugmonitor_isr(void);
+extern void pendablesrvreq_isr(void);
+extern void systick_isr(void);
+extern void dma_ch0_isr(void);
+extern void dma_ch1_isr(void);
+extern void dma_ch2_isr(void);
+extern void dma_ch3_isr(void);
+extern void dma_error_isr(void);
+extern void flash_cmd_isr(void);
+extern void flash_error_isr(void);
+extern void low_voltage_isr(void);
+extern void wakeup_isr(void);
+extern void watchdog_isr(void);
+extern void i2c0_isr(void);
+extern void spi0_isr(void);
+extern void i2s0_tx_isr(void);
+extern void i2s0_rx_isr(void);
+extern void uart0_lon_isr(void);
+extern void uart0_status_isr(void);
+extern void uart0_error_isr(void);
+extern void uart1_status_isr(void);
+extern void uart1_error_isr(void);
+extern void uart2_status_isr(void);
+extern void uart2_error_isr(void);
+extern void adc0_isr(void);
+extern void cmp0_isr(void);
+extern void cmp1_isr(void);
+extern void ftm0_isr(void);
+extern void ftm1_isr(void);
+extern void cmt_isr(void);
+extern void rtc_alarm_isr(void);
+extern void rtc_seconds_isr(void);
+extern void pit0_isr(void);
+extern void pit1_isr(void);
+extern void pit2_isr(void);
+extern void pit3_isr(void);
+extern void pdb_isr(void);
+extern void usb_isr(void);
+extern void usb_charge_isr(void);
+extern void tsi0_isr(void);
+extern void mcg_isr(void);
+extern void lptmr_isr(void);
+extern void porta_isr(void);
+extern void portb_isr(void);
+extern void portc_isr(void);
+extern void portd_isr(void);
+extern void porte_isr(void);
+extern void software_isr(void);
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/teensy3/mk20dx128.ld b/teensy3/mk20dx128.ld
new file mode 100644
index 0000000000000000000000000000000000000000..a838f85deba42b36d4636eb67abc95d559798cb7
--- /dev/null
+++ b/teensy3/mk20dx128.ld
@@ -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);
+}
+
+
diff --git a/teensy3/nonstd.c b/teensy3/nonstd.c
new file mode 100644
index 0000000000000000000000000000000000000000..39009e3325989ffcad0c6bfe3c85b2ea3b1f459e
--- /dev/null
+++ b/teensy3/nonstd.c
@@ -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;
+}
+
diff --git a/teensy3/pins_arduino.h b/teensy3/pins_arduino.h
new file mode 100644
index 0000000000000000000000000000000000000000..0b0c356f82ac70ad485ce8afe13c90059627723b
--- /dev/null
+++ b/teensy3/pins_arduino.h
@@ -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
diff --git a/teensy3/pins_teensy.c b/teensy3/pins_teensy.c
new file mode 100644
index 0000000000000000000000000000000000000000..329269f518086d5ff70ddfd153c5d3edfea45782
--- /dev/null
+++ b/teensy3/pins_teensy.c
@@ -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);;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/teensy3/serial1.c b/teensy3/serial1.c
new file mode 100644
index 0000000000000000000000000000000000000000..846d7d6f60f6ab3c67b08a4d1a26327f62495df7
--- /dev/null
+++ b/teensy3/serial1.c
@@ -0,0 +1,285 @@
+/* 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 "core_pins.h"
+#include "HardwareSerial.h"
+
+// UART0 and UART1 are clocked by F_CPU, UART2 is clocked by F_BUS
+// UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer
+
+#define TX_BUFFER_SIZE 64
+//#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;
+
+#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 C2_ENABLE		UART_C2_TE | UART_C2_RE | UART_C2_RIE | UART_C2_ILIE
+#define C2_TX_ACTIVE		C2_ENABLE | UART_C2_TIE
+#define C2_TX_COMPLETING	C2_ENABLE | UART_C2_TCIE
+#define C2_TX_INACTIVE		C2_ENABLE
+
+void serial_begin(uint32_t divisor)
+{
+	SIM_SCGC4 |= SIM_SCGC4_UART0;	// turn on clock, TODO: use bitband
+	rx_buffer_head = 0;
+	rx_buffer_tail = 0;
+	tx_buffer_head = 0;
+	tx_buffer_tail = 0;
+	transmitting = 0;
+	CORE_PIN0_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3);
+	CORE_PIN1_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3);
+	UART0_BDH = (divisor >> 13) & 0x1F;
+	UART0_BDL = (divisor >> 5) & 0xFF;
+	UART0_C4 = divisor & 0x1F;
+	//UART0_C1 = 0;
+	UART0_C1 = UART_C1_ILT;
+	UART0_TWFIFO = 2; // tx watermark, causes S1_TDRE to set
+	UART0_RWFIFO = 4; // rx watermark, causes S1_RDRF to set
+	UART0_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE;
+	UART0_C2 = C2_TX_INACTIVE;
+	NVIC_ENABLE_IRQ(IRQ_UART0_STATUS);
+}
+
+void serial_end(void)
+{
+	if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return;
+	while (transmitting) yield();  // wait for buffered data to send
+	NVIC_DISABLE_IRQ(IRQ_UART0_STATUS);
+	UART0_C2 = 0;
+	CORE_PIN0_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
+	CORE_PIN1_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
+	rx_buffer_head = 0;
+	rx_buffer_tail = 0;
+}
+
+void serial_putchar(uint8_t c)
+{
+	uint32_t head;
+
+	if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return;
+	head = tx_buffer_head;
+	if (++head >= TX_BUFFER_SIZE) head = 0;
+	while (tx_buffer_tail == head) {
+		yield(); // wait
+	}
+	tx_buffer[head] = c;
+	transmitting = 1;
+	tx_buffer_head = head;
+	UART0_C2 = C2_TX_ACTIVE;
+}
+
+void serial_write(const void *buf, unsigned int count)
+{
+	const uint8_t *p = (const uint8_t *)buf;
+	const uint8_t *end = p + count;
+        uint32_t head;
+
+        if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return;
+	while (p < end) {
+        	head = tx_buffer_head;
+        	if (++head >= TX_BUFFER_SIZE) head = 0;
+		if (tx_buffer_tail == head) {
+        		UART0_C2 = C2_TX_ACTIVE;
+			do {
+				yield(); // wait
+			} while (tx_buffer_tail == head);
+		}
+        	tx_buffer[head] = *p++;
+        	transmitting = 1;
+        	tx_buffer_head = head;
+	}
+        UART0_C2 = C2_TX_ACTIVE;
+}
+
+void serial_flush(void)
+{
+	while (transmitting) yield(); // wait
+}
+
+int serial_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 serial_getchar(void)
+{
+	uint8_t head, tail;
+	int c;
+
+	head = rx_buffer_head;
+	tail = rx_buffer_tail;
+	if (head == tail) return -1;
+	if (++tail >= RX_BUFFER_SIZE) tail = 0;
+	c = rx_buffer[tail];
+	rx_buffer_tail = tail;
+	return c;
+}
+
+int serial_peek(void)
+{
+	uint8_t head, tail;
+
+	head = rx_buffer_head;
+	tail = rx_buffer_tail;
+	if (head == tail) return -1;
+	return rx_buffer[tail];
+}
+
+void serial_clear(void)
+{
+	if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return;
+	UART0_C2 &= ~(UART_C2_RE | UART_C2_RIE | UART_C2_ILIE);
+	UART0_CFIFO = UART_CFIFO_RXFLUSH;
+	UART0_C2 |= (UART_C2_RE | UART_C2_RIE | UART_C2_ILIE);
+	rx_buffer_head = rx_buffer_tail;
+}
+
+// status interrupt combines 
+//   Transmit data below watermark  UART_S1_TDRE
+//   Transmit complete              UART_S1_TC
+//   Idle line                      UART_S1_IDLE
+//   Receive data above watermark   UART_S1_RDRF
+//   LIN break detect               UART_S2_LBKDIF
+//   RxD pin active edge            UART_S2_RXEDGIF
+
+void uart0_status_isr(void)
+{
+	uint8_t avail, head, newhead, tail, c;
+
+	if (UART0_S1 & (UART_S1_RDRF | UART_S1_IDLE)) {
+		__disable_irq();
+		avail = UART0_RCFIFO;
+		if (avail == 0) {
+			// The only way to clear the IDLE interrupt flag is
+			// to read the data register.  But reading with no
+			// data causes a FIFO underrun, which causes the
+			// FIFO to return corrupted data.  If anyone from
+			// Freescale reads this, what a poor design!  There
+			// write should be a write-1-to-clear for IDLE.
+			c = UART0_D;
+			// flushing the fifo recovers from the underrun,
+			// but there's a possible race condition where a
+			// new character could be received between reading
+			// RCFIFO == 0 and flushing the FIFO.  To minimize
+			// the chance, interrupts are disabled so a higher
+			// priority interrupt (hopefully) doesn't delay.
+			// TODO: change this to disabling the IDLE interrupt
+			// which won't be simple, since we already manage
+			// which transmit interrupts are enabled.
+			UART0_CFIFO = UART_CFIFO_RXFLUSH;
+			__enable_irq();
+		} else {
+			__enable_irq();
+			head = rx_buffer_head;
+			tail = rx_buffer_tail;
+			do {
+				c = UART0_D;
+				newhead = head + 1;
+				if (newhead >= RX_BUFFER_SIZE) newhead = 0;
+				if (newhead != tail) {
+					head = newhead;
+					rx_buffer[head] = c;
+				}
+			} while (--avail > 0);
+			rx_buffer_head = head;
+		}
+	}
+	c = UART0_C2;
+	if ((c & UART_C2_TIE) && (UART0_S1 & UART_S1_TDRE)) {
+		head = tx_buffer_head;
+		tail = tx_buffer_tail;
+		do {
+			if (tail == head) break;
+			if (++tail >= TX_BUFFER_SIZE) tail = 0;
+			avail = UART0_S1;
+			UART0_D = tx_buffer[tail];
+		} while (UART0_TCFIFO < 8);
+		tx_buffer_tail = tail;
+		if (UART0_S1 & UART_S1_TDRE) UART0_C2 = C2_TX_COMPLETING;
+	}
+	if ((c & UART_C2_TCIE) && (UART0_S1 & UART_S1_TC)) {
+		transmitting = 0;
+		UART0_C2 = C2_TX_INACTIVE;
+	}
+}
+
+
+
+void serial_print(const char *p)
+{
+	while (*p) {
+		char c = *p++;
+		if (c == '\n') serial_putchar('\r');
+		serial_putchar(c);
+	}
+}
+
+static void serial_phex1(uint32_t n)
+{
+	n &= 15;
+	if (n < 10) {
+		serial_putchar('0' + n);
+	} else {
+		serial_putchar('A' - 10 + n);
+	}
+}
+
+void serial_phex(uint32_t n)
+{
+	serial_phex1(n >> 4);
+	serial_phex1(n);
+}
+
+void serial_phex16(uint32_t n)
+{
+	serial_phex(n >> 8);
+	serial_phex(n);
+}
+
+void serial_phex32(uint32_t n)
+{
+	serial_phex(n >> 24);
+	serial_phex(n >> 16);
+	serial_phex(n >> 8);
+	serial_phex(n);
+}
+
diff --git a/teensy3/serial2.c b/teensy3/serial2.c
new file mode 100644
index 0000000000000000000000000000000000000000..f87ddae78359ae38598e0bfcc85472e85095378c
--- /dev/null
+++ b/teensy3/serial2.c
@@ -0,0 +1,196 @@
+/* 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 "core_pins.h"
+#include "HardwareSerial.h"
+
+// UART0 and UART1 are clocked by F_CPU, UART2 is clocked by F_BUS
+// UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer
+
+#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;
+
+#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 C2_ENABLE		UART_C2_TE | UART_C2_RE | UART_C2_RIE
+#define C2_TX_ACTIVE		C2_ENABLE | UART_C2_TIE
+#define C2_TX_COMPLETING	C2_ENABLE | UART_C2_TCIE
+#define C2_TX_INACTIVE		C2_ENABLE
+
+void serial2_begin(uint32_t divisor)
+{
+	SIM_SCGC4 |= SIM_SCGC4_UART1;	// turn on clock, TODO: use bitband
+	rx_buffer_head = 0;
+	rx_buffer_tail = 0;
+	tx_buffer_head = 0;
+	tx_buffer_tail = 0;
+	transmitting = 0;
+	CORE_PIN9_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3);
+	CORE_PIN10_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3);
+	UART1_BDH = (divisor >> 13) & 0x1F;
+	UART1_BDL = (divisor >> 5) & 0xFF;
+	UART1_C4 = divisor & 0x1F;
+	UART1_C1 = 0;
+	UART1_PFIFO = 0;
+	UART1_C2 = C2_TX_INACTIVE;
+	NVIC_ENABLE_IRQ(IRQ_UART1_STATUS);
+}
+
+void serial2_end(void)
+{
+	if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return;
+	while (transmitting) yield();  // wait for buffered data to send
+	NVIC_DISABLE_IRQ(IRQ_UART1_STATUS);
+	UART1_C2 = 0;
+	CORE_PIN9_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
+	CORE_PIN10_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
+	rx_buffer_head = 0;
+	rx_buffer_tail = 0;
+}
+
+void serial2_putchar(uint8_t c)
+{
+	uint32_t head;
+
+	if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return;
+	head = tx_buffer_head;
+	if (++head >= TX_BUFFER_SIZE) head = 0;
+	while (tx_buffer_tail == head) {
+		yield(); // wait
+	}
+	tx_buffer[head] = c;
+	transmitting = 1;
+	tx_buffer_head = head;
+	UART1_C2 = C2_TX_ACTIVE;
+}
+
+void serial2_write(const void *buf, unsigned int count)
+{
+	const uint8_t *p = (const uint8_t *)buf;
+	while (count-- > 0) serial2_putchar(*p++);
+}
+
+void serial2_flush(void)
+{
+	while (transmitting) yield(); // wait
+}
+
+int serial2_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 serial2_getchar(void)
+{
+	uint8_t head, tail;
+	int c;
+
+	head = rx_buffer_head;
+	tail = rx_buffer_tail;
+	if (head == tail) return -1;
+	if (++tail >= RX_BUFFER_SIZE) tail = 0;
+	c = rx_buffer[tail];
+	rx_buffer_tail = tail;
+	return c;
+}
+
+int serial2_peek(void)
+{
+	uint8_t head, tail;
+
+	head = rx_buffer_head;
+	tail = rx_buffer_tail;
+	if (head == tail) return -1;
+	return rx_buffer[tail];
+}
+
+void serial2_clear(void)
+{
+	rx_buffer_head = rx_buffer_tail;
+}
+
+// status interrupt combines 
+//   Transmit data below watermark  UART_S1_TDRE
+//   Transmit complete              UART_S1_TC
+//   Idle line                      UART_S1_IDLE
+//   Receive data above watermark   UART_S1_RDRF
+//   LIN break detect               UART_S2_LBKDIF
+//   RxD pin active edge            UART_S2_RXEDGIF
+
+void uart1_status_isr(void)
+{
+	uint8_t head, tail, c;
+
+	//digitalWriteFast(4, HIGH);
+	if (UART1_S1 & UART_S1_RDRF) {
+		//digitalWriteFast(5, HIGH);
+		c = UART1_D;
+		head = rx_buffer_head + 1;
+		if (head >= RX_BUFFER_SIZE) head = 0;
+		if (head != rx_buffer_tail) {
+			rx_buffer[head] = c;
+			rx_buffer_head = head; 
+		}
+		//digitalWriteFast(5, LOW);
+	}
+	c = UART1_C2;
+	if ((c & UART_C2_TIE) && (UART1_S1 & UART_S1_TDRE)) {
+		//digitalWriteFast(5, HIGH);
+		head = tx_buffer_head;
+		tail = tx_buffer_tail;
+		if (head == tail) {
+			UART1_C2 = C2_TX_COMPLETING;
+		} else {
+			if (++tail >= TX_BUFFER_SIZE) tail = 0;
+			UART1_D = tx_buffer[tail];
+			tx_buffer_tail = tail;
+		}
+		//digitalWriteFast(5, LOW);
+	}
+	if ((c & UART_C2_TCIE) && (UART1_S1 & UART_S1_TC)) {
+		transmitting = 0;
+		UART1_C2 = C2_TX_INACTIVE;
+	}
+	//digitalWriteFast(4, LOW);
+}
+
+
diff --git a/teensy3/serial3.c b/teensy3/serial3.c
new file mode 100644
index 0000000000000000000000000000000000000000..16907f8c9af10f25ea1813234becbbba2c32493f
--- /dev/null
+++ b/teensy3/serial3.c
@@ -0,0 +1,196 @@
+/* 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 "core_pins.h"
+#include "HardwareSerial.h"
+
+// UART0 and UART1 are clocked by F_CPU, UART2 is clocked by F_BUS
+// UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer
+
+#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;
+
+#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 C2_ENABLE		UART_C2_TE | UART_C2_RE | UART_C2_RIE
+#define C2_TX_ACTIVE		C2_ENABLE | UART_C2_TIE
+#define C2_TX_COMPLETING	C2_ENABLE | UART_C2_TCIE
+#define C2_TX_INACTIVE		C2_ENABLE
+
+void serial3_begin(uint32_t divisor)
+{
+	SIM_SCGC4 |= SIM_SCGC4_UART2;	// turn on clock, TODO: use bitband
+	rx_buffer_head = 0;
+	rx_buffer_tail = 0;
+	tx_buffer_head = 0;
+	tx_buffer_tail = 0;
+	transmitting = 0;
+	CORE_PIN7_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3);
+	CORE_PIN8_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3);
+	UART2_BDH = (divisor >> 13) & 0x1F;
+	UART2_BDL = (divisor >> 5) & 0xFF;
+	UART2_C4 = divisor & 0x1F;
+	UART2_C1 = 0;
+	UART2_PFIFO = 0;
+	UART2_C2 = C2_TX_INACTIVE;
+	NVIC_ENABLE_IRQ(IRQ_UART2_STATUS);
+}
+
+void serial3_end(void)
+{
+	if (!(SIM_SCGC4 & SIM_SCGC4_UART2)) return;
+	while (transmitting) yield();  // wait for buffered data to send
+	NVIC_DISABLE_IRQ(IRQ_UART2_STATUS);
+	UART2_C2 = 0;
+	CORE_PIN7_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
+	CORE_PIN8_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
+	rx_buffer_head = 0;
+	rx_buffer_tail = 0;
+}
+
+void serial3_putchar(uint8_t c)
+{
+	uint32_t head;
+
+	if (!(SIM_SCGC4 & SIM_SCGC4_UART2)) return;
+	head = tx_buffer_head;
+	if (++head >= TX_BUFFER_SIZE) head = 0;
+	while (tx_buffer_tail == head) {
+		yield(); // wait
+	}
+	tx_buffer[head] = c;
+	transmitting = 1;
+	tx_buffer_head = head;
+	UART2_C2 = C2_TX_ACTIVE;
+}
+
+void serial3_write(const void *buf, unsigned int count)
+{
+	const uint8_t *p = (const uint8_t *)buf;
+	while (count-- > 0) serial3_putchar(*p++);
+}
+
+void serial3_flush(void)
+{
+	while (transmitting) yield(); // wait
+}
+
+int serial3_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 serial3_getchar(void)
+{
+	uint8_t head, tail;
+	int c;
+
+	head = rx_buffer_head;
+	tail = rx_buffer_tail;
+	if (head == tail) return -1;
+	if (++tail >= RX_BUFFER_SIZE) tail = 0;
+	c = rx_buffer[tail];
+	rx_buffer_tail = tail;
+	return c;
+}
+
+int serial3_peek(void)
+{
+	uint8_t head, tail;
+
+	head = rx_buffer_head;
+	tail = rx_buffer_tail;
+	if (head == tail) return -1;
+	return rx_buffer[tail];
+}
+
+void serial3_clear(void)
+{
+	rx_buffer_head = rx_buffer_tail;
+}
+
+// status interrupt combines 
+//   Transmit data below watermark  UART_S1_TDRE
+//   Transmit complete              UART_S1_TC
+//   Idle line                      UART_S1_IDLE
+//   Receive data above watermark   UART_S1_RDRF
+//   LIN break detect               UART_S2_LBKDIF
+//   RxD pin active edge            UART_S2_RXEDGIF
+
+void uart2_status_isr(void)
+{
+	uint8_t head, tail, c;
+
+	//digitalWriteFast(4, HIGH);
+	if (UART2_S1 & UART_S1_RDRF) {
+		//digitalWriteFast(5, HIGH);
+		c = UART2_D;
+		head = rx_buffer_head + 1;
+		if (head >= RX_BUFFER_SIZE) head = 0;
+		if (head != rx_buffer_tail) {
+			rx_buffer[head] = c;
+			rx_buffer_head = head; 
+		}
+		//digitalWriteFast(5, LOW);
+	}
+	c = UART2_C2;
+	if ((c & UART_C2_TIE) && (UART2_S1 & UART_S1_TDRE)) {
+		//digitalWriteFast(5, HIGH);
+		head = tx_buffer_head;
+		tail = tx_buffer_tail;
+		if (head == tail) {
+			UART2_C2 = C2_TX_COMPLETING;
+		} else {
+			if (++tail >= TX_BUFFER_SIZE) tail = 0;
+			UART2_D = tx_buffer[tail];
+			tx_buffer_tail = tail;
+		}
+		//digitalWriteFast(5, LOW);
+	}
+	if ((c & UART_C2_TCIE) && (UART2_S1 & UART_S1_TC)) {
+		transmitting = 0;
+		UART2_C2 = C2_TX_INACTIVE;
+	}
+	//digitalWriteFast(4, LOW);
+}
+
+
diff --git a/teensy3/touch.c b/teensy3/touch.c
new file mode 100644
index 0000000000000000000000000000000000000000..02b8f4f6293b8ae972f10ae2ec04bd596257bc45
--- /dev/null
+++ b/teensy3/touch.c
@@ -0,0 +1,77 @@
+/* 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 const uint8_t pin2tsi[] = {
+//0    1    2    3    4    5    6    7    8    9
+  9,  10, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255,  13,   0,   6,   8,   7,
+255, 255,  14,  15, 255,  12, 255, 255, 255, 255,
+255, 255,  11,   5
+};
+
+// These settings give approx 0.02 pF sensitivity and 1200 pF range
+// Lower current, higher number of scans, and higher prescaler
+// increase sensitivity, but the trade-off is longer measurement
+// time and decreased range.
+#define CURRENT   2 // 0 to 15 - current to use, value is 2*(current+1)
+#define NSCAN     9 // number of times to scan, 0 to 31, value is nscan+1
+#define PRESCALE  2 // prescaler, 0 to 7 - value is 2^(prescaler+1)
+
+
+// output is approx pF * 50
+// time to measure 33 pF is approx 0.25 ms
+// time to measure 1000 pF is approx 4.5 ms
+
+int touchRead(uint8_t pin)
+{
+	uint32_t ch;
+
+	if (pin >= NUM_DIGITAL_PINS) return 0;
+	ch = pin2tsi[pin];
+	if (ch == 255) return 0;
+
+	*portConfigRegister(pin) = PORT_PCR_MUX(0);
+	SIM_SCGC5 |= SIM_SCGC5_TSI;
+	TSI0_GENCS = 0;
+	TSI0_PEN = (1 << ch);
+	TSI0_SCANC = TSI_SCANC_REFCHRG(3) | TSI_SCANC_EXTCHRG(CURRENT);
+	TSI0_GENCS = TSI_GENCS_NSCN(NSCAN) | TSI_GENCS_PS(PRESCALE) | TSI_GENCS_TSIEN | TSI_GENCS_SWTS;
+	delayMicroseconds(10);
+	while (TSI0_GENCS & TSI_GENCS_SCNIP) ; // wait
+	delayMicroseconds(1);
+	return *((volatile uint16_t *)(&TSI0_CNTR1) + ch);
+}
+
+
+
+
diff --git a/teensy3/usb_desc.c b/teensy3/usb_desc.c
new file mode 100644
index 0000000000000000000000000000000000000000..778e0657ba823ecc5869c83b55d364380a6f687d
--- /dev/null
+++ b/teensy3/usb_desc.c
@@ -0,0 +1,882 @@
+/* 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 "usb_desc.h"
+#include "usb_names.h"
+#include "mk20dx128.h"
+#include "avr_functions.h"
+
+// USB Descriptors are binary data which the USB host reads to
+// automatically detect a USB device's capabilities.  The format
+// and meaning of every field is documented in numerous USB
+// standards.  When working with USB descriptors, despite the
+// complexity of the standards and poor writing quality in many
+// of those documents, remember descriptors are nothing more
+// than constant binary data that tells the USB host what the
+// device can do.  Computers will load drivers based on this data.
+// Those drivers then communicate on the endpoints specified by
+// the descriptors.
+
+// To configure a new combination of interfaces or make minor
+// changes to existing configuration (eg, change the name or ID
+// numbers), usually you would edit "usb_desc.h".  This file
+// is meant to be configured by the header, so generally it is
+// only edited to add completely new USB interfaces or features.
+
+
+
+// **************************************************************
+//   USB Device
+// **************************************************************
+
+#define LSB(n) ((n) & 255)
+#define MSB(n) (((n) >> 8) & 255)
+
+// USB Device Descriptor.  The USB host reads this first, to learn
+// what type of device is connected.
+static uint8_t device_descriptor[] = {
+        18,                                     // bLength
+        1,                                      // bDescriptorType
+        0x00, 0x02,                             // bcdUSB
+#ifdef DEVICE_CLASS
+        DEVICE_CLASS,                           // bDeviceClass
+#else
+	0,
+#endif
+#ifdef DEVICE_SUBCLASS
+        DEVICE_SUBCLASS,                        // bDeviceSubClass
+#else
+	0,
+#endif
+#ifdef DEVICE_PROTOCOL
+        DEVICE_PROTOCOL,                        // bDeviceProtocol
+#else
+	0,
+#endif
+        EP0_SIZE,                               // bMaxPacketSize0
+        LSB(VENDOR_ID), MSB(VENDOR_ID),         // idVendor
+        LSB(PRODUCT_ID), MSB(PRODUCT_ID),       // idProduct
+        0x00, 0x01,                             // bcdDevice
+        1,                                      // iManufacturer
+        2,                                      // iProduct
+        3,                                      // iSerialNumber
+        1                                       // bNumConfigurations
+};
+
+// These descriptors must NOT be "const", because the USB DMA
+// has trouble accessing flash memory with enough bandwidth
+// while the processor is executing from flash.
+
+
+
+// **************************************************************
+//   HID Report Descriptors
+// **************************************************************
+
+// Each HID interface needs a special report descriptor that tells
+// the meaning and format of the data.
+
+#ifdef KEYBOARD_INTERFACE
+// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
+static uint8_t keyboard_report_desc[] = {
+        0x05, 0x01,             //  Usage Page (Generic Desktop),
+        0x09, 0x06,             //  Usage (Keyboard),
+        0xA1, 0x01,             //  Collection (Application),
+        0x75, 0x01,             //  Report Size (1),
+        0x95, 0x08,             //  Report Count (8),
+        0x05, 0x07,             //  Usage Page (Key Codes),
+        0x19, 0xE0,             //  Usage Minimum (224),
+        0x29, 0xE7,             //  Usage Maximum (231),
+        0x15, 0x00,             //  Logical Minimum (0),
+        0x25, 0x01,             //  Logical Maximum (1),
+        0x81, 0x02,             //  Input (Data, Variable, Absolute), ;Modifier byte
+        0x95, 0x08,             //  Report Count (8),
+        0x75, 0x01,             //  Report Size (1),
+        0x15, 0x00,             //  Logical Minimum (0),
+        0x25, 0x01,             //  Logical Maximum (1),
+        0x05, 0x0C,             //  Usage Page (Consumer),
+        0x09, 0xE9,             //  Usage (Volume Increment),
+        0x09, 0xEA,             //  Usage (Volume Decrement),
+        0x09, 0xE2,             //  Usage (Mute),
+        0x09, 0xCD,             //  Usage (Play/Pause),
+        0x09, 0xB5,             //  Usage (Scan Next Track),
+        0x09, 0xB6,             //  Usage (Scan Previous Track),
+        0x09, 0xB7,             //  Usage (Stop),
+        0x09, 0xB8,             //  Usage (Eject),
+        0x81, 0x02,             //  Input (Data, Variable, Absolute), ;Media keys
+        0x95, 0x05,             //  Report Count (5),
+        0x75, 0x01,             //  Report Size (1),
+        0x05, 0x08,             //  Usage Page (LEDs),
+        0x19, 0x01,             //  Usage Minimum (1),
+        0x29, 0x05,             //  Usage Maximum (5),
+        0x91, 0x02,             //  Output (Data, Variable, Absolute), ;LED report
+        0x95, 0x01,             //  Report Count (1),
+        0x75, 0x03,             //  Report Size (3),
+        0x91, 0x03,             //  Output (Constant),                 ;LED report padding
+        0x95, 0x06,             //  Report Count (6),
+        0x75, 0x08,             //  Report Size (8),
+        0x15, 0x00,             //  Logical Minimum (0),
+        0x25, 0x7F,             //  Logical Maximum(104),
+        0x05, 0x07,             //  Usage Page (Key Codes),
+        0x19, 0x00,             //  Usage Minimum (0),
+        0x29, 0x7F,             //  Usage Maximum (104),
+        0x81, 0x00,             //  Input (Data, Array),                ;Normal keys
+        0xc0                    // End Collection
+};
+#endif
+
+#ifdef MOUSE_INTERFACE
+// Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
+static uint8_t mouse_report_desc[] = {
+        0x05, 0x01,                     // Usage Page (Generic Desktop)
+        0x09, 0x02,                     // Usage (Mouse)
+        0xA1, 0x01,                     // Collection (Application)
+        0x05, 0x09,                     //   Usage Page (Button)
+        0x19, 0x01,                     //   Usage Minimum (Button #1)
+        0x29, 0x03,                     //   Usage Maximum (Button #3)
+        0x15, 0x00,                     //   Logical Minimum (0)
+        0x25, 0x01,                     //   Logical Maximum (1)
+        0x95, 0x03,                     //   Report Count (3)
+        0x75, 0x01,                     //   Report Size (1)
+        0x81, 0x02,                     //   Input (Data, Variable, Absolute)
+        0x95, 0x01,                     //   Report Count (1)
+        0x75, 0x05,                     //   Report Size (5)
+        0x81, 0x03,                     //   Input (Constant)
+        0x05, 0x01,                     //   Usage Page (Generic Desktop)
+        0x09, 0x30,                     //   Usage (X)
+        0x09, 0x31,                     //   Usage (Y)
+        0x15, 0x81,                     //   Logical Minimum (-127)
+        0x25, 0x7F,                     //   Logical Maximum (127)
+        0x75, 0x08,                     //   Report Size (8),
+        0x95, 0x02,                     //   Report Count (2),
+        0x81, 0x06,                     //   Input (Data, Variable, Relative)
+        0x09, 0x38,                     //   Usage (Wheel)
+        0x95, 0x01,                     //   Report Count (1),
+        0x81, 0x06,                     //   Input (Data, Variable, Relative)
+        0xC0                            // End Collection
+};
+#endif
+
+#ifdef JOYSTICK_INTERFACE
+static uint8_t joystick_report_desc[] = {
+        0x05, 0x01,                     // Usage Page (Generic Desktop)
+        0x09, 0x04,                     // Usage (Joystick)
+        0xA1, 0x01,                     // Collection (Application)
+        0x15, 0x00,                     // Logical Minimum (0)
+        0x25, 0x01,                     // Logical Maximum (1)
+        0x75, 0x01,                     // Report Size (1)
+        0x95, 0x20,                     // Report Count (32)
+        0x05, 0x09,                     // Usage Page (Button)
+        0x19, 0x01,                     // Usage Minimum (Button #1)
+        0x29, 0x20,                     // Usage Maximum (Button #32)
+        0x81, 0x02,                     // Input (variable,absolute)
+        0x15, 0x00,                     // Logical Minimum (0)
+        0x25, 0x07,                     // Logical Maximum (7)
+        0x35, 0x00,                     // Physical Minimum (0)
+        0x46, 0x3B, 0x01,               // Physical Maximum (315)
+        0x75, 0x04,                     // Report Size (4)
+        0x95, 0x01,                     // Report Count (1)
+        0x65, 0x14,                     // Unit (20)
+        0x05, 0x01,                     // Usage Page (Generic Desktop)
+        0x09, 0x39,                     // Usage (Hat switch)
+        0x81, 0x42,                     // Input (variable,absolute,null_state)
+        0x05, 0x01,                     // Usage Page (Generic Desktop)
+        0x09, 0x01,                     // Usage (Pointer)
+        0xA1, 0x00,                     // Collection ()
+        0x15, 0x00,                     //   Logical Minimum (0)
+        0x26, 0xFF, 0x03,               //   Logical Maximum (1023)
+        0x75, 0x0A,                     //   Report Size (10)
+        0x95, 0x04,                     //   Report Count (4)
+        0x09, 0x30,                     //   Usage (X)
+        0x09, 0x31,                     //   Usage (Y)
+        0x09, 0x32,                     //   Usage (Z)
+        0x09, 0x35,                     //   Usage (Rz)
+        0x81, 0x02,                     //   Input (variable,absolute)
+        0xC0,                           // End Collection
+        0x15, 0x00,                     // Logical Minimum (0)
+        0x26, 0xFF, 0x03,               // Logical Maximum (1023)
+        0x75, 0x0A,                     // Report Size (10)
+        0x95, 0x02,                     // Report Count (2)
+        0x09, 0x36,                     // Usage (Slider)
+        0x09, 0x36,                     // Usage (Slider)
+        0x81, 0x02,                     // Input (variable,absolute)
+        0xC0                            // End Collection
+};
+#endif
+
+#ifdef SEREMU_INTERFACE
+static uint8_t seremu_report_desc[] = {
+        0x06, 0xC9, 0xFF,                       // Usage Page 0xFFC9 (vendor defined)
+        0x09, 0x04,                             // Usage 0x04
+        0xA1, 0x5C,                             // Collection 0x5C
+        0x75, 0x08,                             // report size = 8 bits (global)
+        0x15, 0x00,                             // logical minimum = 0 (global)
+        0x26, 0xFF, 0x00,                       // logical maximum = 255 (global)
+        0x95, SEREMU_TX_SIZE,                   // report count (global)
+        0x09, 0x75,                             // usage (local)
+        0x81, 0x02,                             // Input
+        0x95, SEREMU_RX_SIZE,                   // report count (global)
+        0x09, 0x76,                             // usage (local)
+        0x91, 0x02,                             // Output
+        0x95, 0x04,                             // report count (global)
+        0x09, 0x76,                             // usage (local)
+        0xB1, 0x02,                             // Feature
+        0xC0                                    // end collection
+};
+#endif
+
+#ifdef RAWHID_INTERFACE
+static uint8_t rawhid_report_desc[] = {
+        0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE),
+        0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE),
+        0xA1, 0x01,                             // Collection 0x01
+        0x75, 0x08,                             // report size = 8 bits
+        0x15, 0x00,                             // logical minimum = 0
+        0x26, 0xFF, 0x00,                       // logical maximum = 255
+        0x95, RAWHID_TX_SIZE,                   // report count
+        0x09, 0x01,                             // usage
+        0x81, 0x02,                             // Input (array)
+        0x95, RAWHID_RX_SIZE,                   // report count
+        0x09, 0x02,                             // usage
+        0x91, 0x02,                             // Output (array)
+        0xC0                                    // end collection
+};
+#endif
+
+#ifdef FLIGHTSIM_INTERFACE
+static uint8_t flightsim_report_desc[] = {
+        0x06, 0x1C, 0xFF,                       // Usage page = 0xFF1C
+        0x0A, 0x39, 0xA7,                       // Usage = 0xA739
+        0xA1, 0x01,                             // Collection 0x01
+        0x75, 0x08,                             // report size = 8 bits
+        0x15, 0x00,                             // logical minimum = 0
+        0x26, 0xFF, 0x00,                       // logical maximum = 255
+        0x95, FLIGHTSIM_TX_SIZE,                // report count
+        0x09, 0x01,                             // usage
+        0x81, 0x02,                             // Input (array)
+        0x95, FLIGHTSIM_RX_SIZE,                // report count
+        0x09, 0x02,                             // usage
+        0x91, 0x02,                             // Output (array)
+        0xC0                                    // end collection
+};
+#endif
+
+
+
+// **************************************************************
+//   USB Configuration
+// **************************************************************
+
+// USB Configuration Descriptor.  This huge descriptor tells all
+// of the devices capbilities.
+static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
+        // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
+        9,                                      // bLength;
+        2,                                      // bDescriptorType;
+        LSB(CONFIG_DESC_SIZE),                 // wTotalLength
+        MSB(CONFIG_DESC_SIZE),
+        NUM_INTERFACE,                          // bNumInterfaces
+        1,                                      // bConfigurationValue
+        0,                                      // iConfiguration
+        0xC0,                                   // bmAttributes
+        50,                                     // bMaxPower
+
+#ifdef CDC_IAD_DESCRIPTOR
+        // interface association descriptor, USB ECN, Table 9-Z
+        8,                                      // bLength
+        11,                                     // bDescriptorType
+        CDC_STATUS_INTERFACE,                   // bFirstInterface
+        2,                                      // bInterfaceCount
+        0x02,                                   // bFunctionClass
+        0x02,                                   // bFunctionSubClass
+        0x01,                                   // bFunctionProtocol
+        4,                                      // iFunction
+#endif
+
+#ifdef CDC_DATA_INTERFACE
+        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+        9,                                      // bLength
+        4,                                      // bDescriptorType
+        CDC_STATUS_INTERFACE,			// bInterfaceNumber
+        0,                                      // bAlternateSetting
+        1,                                      // bNumEndpoints
+        0x02,                                   // bInterfaceClass
+        0x02,                                   // bInterfaceSubClass
+        0x01,                                   // bInterfaceProtocol
+        0,                                      // iInterface
+        // CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26
+        5,                                      // bFunctionLength
+        0x24,                                   // bDescriptorType
+        0x00,                                   // bDescriptorSubtype
+        0x10, 0x01,                             // bcdCDC
+        // Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27
+        5,                                      // bFunctionLength
+        0x24,                                   // bDescriptorType
+        0x01,                                   // bDescriptorSubtype
+        0x01,                                   // bmCapabilities
+        1,                                      // bDataInterface
+        // Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28
+        4,                                      // bFunctionLength
+        0x24,                                   // bDescriptorType
+        0x02,                                   // bDescriptorSubtype
+        0x06,                                   // bmCapabilities
+        // Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33
+        5,                                      // bFunctionLength
+        0x24,                                   // bDescriptorType
+        0x06,                                   // bDescriptorSubtype
+        CDC_STATUS_INTERFACE,                   // bMasterInterface
+        CDC_DATA_INTERFACE,                     // bSlaveInterface0
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                                      // bLength
+        5,                                      // bDescriptorType
+        CDC_ACM_ENDPOINT | 0x80,                // bEndpointAddress
+        0x03,                                   // bmAttributes (0x03=intr)
+        CDC_ACM_SIZE, 0,                        // wMaxPacketSize
+        64,                                     // bInterval
+        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+        9,                                      // bLength
+        4,                                      // bDescriptorType
+        CDC_DATA_INTERFACE,                     // bInterfaceNumber
+        0,                                      // bAlternateSetting
+        2,                                      // bNumEndpoints
+        0x0A,                                   // bInterfaceClass
+        0x00,                                   // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0,                                      // iInterface
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                                      // bLength
+        5,                                      // bDescriptorType
+        CDC_RX_ENDPOINT,                        // bEndpointAddress
+        0x02,                                   // bmAttributes (0x02=bulk)
+        CDC_RX_SIZE, 0,                         // wMaxPacketSize
+        0,                                      // bInterval
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                                      // bLength
+        5,                                      // bDescriptorType
+        CDC_TX_ENDPOINT | 0x80,                 // bEndpointAddress
+        0x02,                                   // bmAttributes (0x02=bulk)
+        CDC_TX_SIZE, 0,                         // wMaxPacketSize
+        0,                                      // bInterval
+#endif // CDC_DATA_INTERFACE
+
+#ifdef MIDI_INTERFACE
+        // Standard MS Interface Descriptor,
+        9,                                      // bLength
+        4,                                      // bDescriptorType
+        MIDI_INTERFACE,                         // bInterfaceNumber
+        0,                                      // bAlternateSetting
+        2,                                      // bNumEndpoints
+        0x01,                                   // bInterfaceClass (0x01 = Audio)
+        0x03,                                   // bInterfaceSubClass (0x03 = MIDI)
+        0x00,                                   // bInterfaceProtocol (unused for MIDI)
+        0,                                      // iInterface
+        // MIDI MS Interface Header, USB MIDI 6.1.2.1, page 21, Table 6-2
+        7,                                      // bLength
+        0x24,                                   // bDescriptorType = CS_INTERFACE
+        0x01,                                   // bDescriptorSubtype = MS_HEADER 
+        0x00, 0x01,                             // bcdMSC = revision 01.00
+        0x41, 0x00,                             // wTotalLength
+        // MIDI IN Jack Descriptor, B.4.3, Table B-7 (embedded), page 40
+        6,                                      // bLength
+        0x24,                                   // bDescriptorType = CS_INTERFACE
+        0x02,                                   // bDescriptorSubtype = MIDI_IN_JACK
+        0x01,                                   // bJackType = EMBEDDED
+        1,                                      // bJackID, ID = 1
+        0,                                      // iJack
+        // MIDI IN Jack Descriptor, B.4.3, Table B-8 (external), page 40
+        6,                                      // bLength
+        0x24,                                   // bDescriptorType = CS_INTERFACE
+        0x02,                                   // bDescriptorSubtype = MIDI_IN_JACK
+        0x02,                                   // bJackType = EXTERNAL
+        2,                                      // bJackID, ID = 2
+        0,                                      // iJack
+        // MIDI OUT Jack Descriptor, B.4.4, Table B-9, page 41
+        9,
+        0x24,                                   // bDescriptorType = CS_INTERFACE
+        0x03,                                   // bDescriptorSubtype = MIDI_OUT_JACK
+        0x01,                                   // bJackType = EMBEDDED
+        3,                                      // bJackID, ID = 3
+        1,                                      // bNrInputPins = 1 pin
+        2,                                      // BaSourceID(1) = 2
+        1,                                      // BaSourcePin(1) = first pin
+        0,                                      // iJack
+        // MIDI OUT Jack Descriptor, B.4.4, Table B-10, page 41
+        9,
+        0x24,                                   // bDescriptorType = CS_INTERFACE
+        0x03,                                   // bDescriptorSubtype = MIDI_OUT_JACK
+        0x02,                                   // bJackType = EXTERNAL
+        4,                                      // bJackID, ID = 4
+        1,                                      // bNrInputPins = 1 pin
+        1,                                      // BaSourceID(1) = 1
+        1,                                      // BaSourcePin(1) = first pin
+        0,                                      // iJack
+        // Standard Bulk OUT Endpoint Descriptor, B.5.1, Table B-11, pae 42
+        9,                                      // bLength
+        5,                                      // bDescriptorType = ENDPOINT 
+        MIDI_RX_ENDPOINT,                       // bEndpointAddress
+        0x02,                                   // bmAttributes (0x02=bulk)
+        MIDI_RX_SIZE, 0,                        // wMaxPacketSize
+        0,                                      // bInterval
+        0,                                      // bRefresh
+        0,                                      // bSynchAddress
+        // Class-specific MS Bulk OUT Endpoint Descriptor, B.5.2, Table B-12, page 42
+        5,                                      // bLength
+        0x25,                                   // bDescriptorSubtype = CS_ENDPOINT
+        0x01,                                   // bJackType = MS_GENERAL
+        1,                                      // bNumEmbMIDIJack = 1 jack
+        1,                                      // BaAssocJackID(1) = jack ID #1
+        // Standard Bulk IN Endpoint Descriptor, B.5.1, Table B-11, pae 42
+        9,                                      // bLength
+        5,                                      // bDescriptorType = ENDPOINT 
+        MIDI_TX_ENDPOINT | 0x80,                // bEndpointAddress
+        0x02,                                   // bmAttributes (0x02=bulk)
+        MIDI_TX_SIZE, 0,                        // wMaxPacketSize
+        0,                                      // bInterval
+        0,                                      // bRefresh
+        0,                                      // bSynchAddress
+        // Class-specific MS Bulk IN Endpoint Descriptor, B.5.2, Table B-12, page 42
+        5,                                      // bLength
+        0x25,                                   // bDescriptorSubtype = CS_ENDPOINT
+        0x01,                                   // bJackType = MS_GENERAL
+        1,                                      // bNumEmbMIDIJack = 1 jack
+        3,                                      // BaAssocJackID(1) = jack ID #3
+#endif // MIDI_INTERFACE
+
+#ifdef KEYBOARD_INTERFACE
+        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+        9,                                      // bLength
+        4,                                      // bDescriptorType
+        KEYBOARD_INTERFACE,                     // bInterfaceNumber
+        0,                                      // bAlternateSetting
+        1,                                      // bNumEndpoints
+        0x03,                                   // bInterfaceClass (0x03 = HID)
+        0x01,                                   // bInterfaceSubClass (0x01 = Boot)
+        0x01,                                   // bInterfaceProtocol (0x01 = Keyboard)
+        0,                                      // iInterface
+        // HID interface descriptor, HID 1.11 spec, section 6.2.1
+        9,                                      // bLength
+        0x21,                                   // bDescriptorType
+        0x11, 0x01,                             // bcdHID
+        0,                                      // bCountryCode
+        1,                                      // bNumDescriptors
+        0x22,                                   // bDescriptorType
+        LSB(sizeof(keyboard_report_desc)),      // wDescriptorLength
+        MSB(sizeof(keyboard_report_desc)),
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                                      // bLength
+        5,                                      // bDescriptorType
+        KEYBOARD_ENDPOINT | 0x80,               // bEndpointAddress
+        0x03,                                   // bmAttributes (0x03=intr)
+        KEYBOARD_SIZE, 0,                       // wMaxPacketSize
+        KEYBOARD_INTERVAL,                      // bInterval
+#endif // KEYBOARD_INTERFACE
+
+#ifdef MOUSE_INTERFACE
+        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+        9,                                      // bLength
+        4,                                      // bDescriptorType
+        MOUSE_INTERFACE,                        // bInterfaceNumber
+        0,                                      // bAlternateSetting
+        1,                                      // bNumEndpoints
+        0x03,                                   // bInterfaceClass (0x03 = HID)
+        0x01,                                   // bInterfaceSubClass (0x01 = Boot)
+        0x02,                                   // bInterfaceProtocol (0x02 = Mouse)
+        0,                                      // iInterface
+        // HID interface descriptor, HID 1.11 spec, section 6.2.1
+        9,                                      // bLength
+        0x21,                                   // bDescriptorType
+        0x11, 0x01,                             // bcdHID
+        0,                                      // bCountryCode
+        1,                                      // bNumDescriptors
+        0x22,                                   // bDescriptorType
+        LSB(sizeof(mouse_report_desc)),         // wDescriptorLength
+        MSB(sizeof(mouse_report_desc)),
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                                      // bLength
+        5,                                      // bDescriptorType
+        MOUSE_ENDPOINT | 0x80,                  // bEndpointAddress
+        0x03,                                   // bmAttributes (0x03=intr)
+        MOUSE_SIZE, 0,                          // wMaxPacketSize
+        MOUSE_INTERVAL,                         // bInterval
+#endif // MOUSE_INTERFACE
+
+#ifdef RAWHID_INTERFACE
+        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+        9,                                      // bLength
+        4,                                      // bDescriptorType
+        RAWHID_INTERFACE,                       // bInterfaceNumber
+        0,                                      // bAlternateSetting
+        2,                                      // bNumEndpoints
+        0x03,                                   // bInterfaceClass (0x03 = HID)
+        0x00,                                   // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0,                                      // iInterface
+        // HID interface descriptor, HID 1.11 spec, section 6.2.1
+        9,                                      // bLength
+        0x21,                                   // bDescriptorType
+        0x11, 0x01,                             // bcdHID
+        0,                                      // bCountryCode
+        1,                                      // bNumDescriptors
+        0x22,                                   // bDescriptorType
+        LSB(sizeof(rawhid_report_desc)),        // wDescriptorLength
+        MSB(sizeof(rawhid_report_desc)),
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                                      // bLength
+        5,                                      // bDescriptorType
+        RAWHID_TX_ENDPOINT | 0x80,              // bEndpointAddress
+        0x03,                                   // bmAttributes (0x03=intr)
+        RAWHID_TX_SIZE, 0,                      // wMaxPacketSize
+        RAWHID_TX_INTERVAL,                     // bInterval
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                                      // bLength
+        5,                                      // bDescriptorType
+        RAWHID_RX_ENDPOINT,                     // bEndpointAddress
+        0x03,                                   // bmAttributes (0x03=intr)
+        RAWHID_RX_SIZE, 0,                      // wMaxPacketSize
+        RAWHID_RX_INTERVAL,			// bInterval
+#endif // RAWHID_INTERFACE
+
+#ifdef FLIGHTSIM_INTERFACE
+        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+        9,                                      // bLength
+        4,                                      // bDescriptorType
+        FLIGHTSIM_INTERFACE,                    // bInterfaceNumber
+        0,                                      // bAlternateSetting
+        2,                                      // bNumEndpoints
+        0x03,                                   // bInterfaceClass (0x03 = HID)
+        0x00,                                   // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0,                                      // iInterface
+        // HID interface descriptor, HID 1.11 spec, section 6.2.1
+        9,                                      // bLength
+        0x21,                                   // bDescriptorType
+        0x11, 0x01,                             // bcdHID
+        0,                                      // bCountryCode
+        1,                                      // bNumDescriptors
+        0x22,                                   // bDescriptorType
+        LSB(sizeof(flightsim_report_desc)),     // wDescriptorLength
+        MSB(sizeof(flightsim_report_desc)),
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                                      // bLength
+        5,                                      // bDescriptorType
+        FLIGHTSIM_TX_ENDPOINT | 0x80,           // bEndpointAddress
+        0x03,                                   // bmAttributes (0x03=intr)
+        FLIGHTSIM_TX_SIZE, 0,                   // wMaxPacketSize
+        FLIGHTSIM_TX_INTERVAL,                  // bInterval
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                                      // bLength
+        5,                                      // bDescriptorType
+        FLIGHTSIM_RX_ENDPOINT,                  // bEndpointAddress
+        0x03,                                   // bmAttributes (0x03=intr)
+        FLIGHTSIM_RX_SIZE, 0,                   // wMaxPacketSize
+        FLIGHTSIM_RX_INTERVAL,			// bInterval
+#endif // FLIGHTSIM_INTERFACE
+
+#ifdef SEREMU_INTERFACE
+        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+        9,                                      // bLength
+        4,                                      // bDescriptorType
+        SEREMU_INTERFACE,                       // bInterfaceNumber
+        0,                                      // bAlternateSetting
+        2,                                      // bNumEndpoints
+        0x03,                                   // bInterfaceClass (0x03 = HID)
+        0x00,                                   // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0,                                      // iInterface
+        // HID interface descriptor, HID 1.11 spec, section 6.2.1
+        9,                                      // bLength
+        0x21,                                   // bDescriptorType
+        0x11, 0x01,                             // bcdHID
+        0,                                      // bCountryCode
+        1,                                      // bNumDescriptors
+        0x22,                                   // bDescriptorType
+        LSB(sizeof(seremu_report_desc)),        // wDescriptorLength
+        MSB(sizeof(seremu_report_desc)),
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                                      // bLength
+        5,                                      // bDescriptorType
+        SEREMU_TX_ENDPOINT | 0x80,              // bEndpointAddress
+        0x03,                                   // bmAttributes (0x03=intr)
+        SEREMU_TX_SIZE, 0,                      // wMaxPacketSize
+        SEREMU_TX_INTERVAL,                     // bInterval
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                                      // bLength
+        5,                                      // bDescriptorType
+        SEREMU_RX_ENDPOINT,                     // bEndpointAddress
+        0x03,                                   // bmAttributes (0x03=intr)
+        SEREMU_RX_SIZE, 0,                      // wMaxPacketSize
+        SEREMU_RX_INTERVAL,			// bInterval
+#endif // SEREMU_INTERFACE
+
+#ifdef JOYSTICK_INTERFACE
+        // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+        9,                                      // bLength
+        4,                                      // bDescriptorType
+        JOYSTICK_INTERFACE,                     // bInterfaceNumber
+        0,                                      // bAlternateSetting
+        1,                                      // bNumEndpoints
+        0x03,                                   // bInterfaceClass (0x03 = HID)
+        0x00,                                   // bInterfaceSubClass
+        0x00,                                   // bInterfaceProtocol
+        0,                                      // iInterface
+        // HID interface descriptor, HID 1.11 spec, section 6.2.1
+        9,                                      // bLength
+        0x21,                                   // bDescriptorType
+        0x11, 0x01,                             // bcdHID
+        0,                                      // bCountryCode
+        1,                                      // bNumDescriptors
+        0x22,                                   // bDescriptorType
+        LSB(sizeof(joystick_report_desc)),      // wDescriptorLength
+        MSB(sizeof(joystick_report_desc)),
+        // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+        7,                                      // bLength
+        5,                                      // bDescriptorType
+        JOYSTICK_ENDPOINT | 0x80,               // bEndpointAddress
+        0x03,                                   // bmAttributes (0x03=intr)
+        JOYSTICK_SIZE, 0,                       // wMaxPacketSize
+        JOYSTICK_INTERVAL,                      // bInterval
+#endif // JOYSTICK_INTERFACE
+
+};
+
+
+// **************************************************************
+//   String Descriptors
+// **************************************************************
+
+// The descriptors above can provide human readable strings,
+// referenced by index numbers.  These descriptors are the
+// actual string data
+
+/* defined in usb_names.h
+struct usb_string_descriptor_struct {
+        uint8_t bLength;
+        uint8_t bDescriptorType;
+        uint16_t wString[];
+};
+*/
+
+extern struct usb_string_descriptor_struct usb_string_manufacturer_name
+        __attribute__ ((weak, alias("usb_string_manufacturer_name_default")));
+extern struct usb_string_descriptor_struct usb_string_product_name
+        __attribute__ ((weak, alias("usb_string_product_name_default")));
+extern struct usb_string_descriptor_struct usb_string_serial_number
+        __attribute__ ((weak, alias("usb_string_serial_number_default")));
+
+struct usb_string_descriptor_struct string0 = {
+        4,
+        3,
+        {0x0409}
+};
+
+struct usb_string_descriptor_struct usb_string_manufacturer_name_default = {
+        2 + MANUFACTURER_NAME_LEN * 2,
+        3,
+        MANUFACTURER_NAME
+};
+struct usb_string_descriptor_struct usb_string_product_name_default = {
+	2 + PRODUCT_NAME_LEN * 2,
+        3,
+        PRODUCT_NAME
+};
+struct usb_string_descriptor_struct usb_string_serial_number_default = {
+        12,
+        3,
+        {0,0,0,0,0,0,0,0,0,0}
+};
+
+void usb_init_serialnumber(void)
+{
+	char buf[11];
+	uint32_t i, num;
+
+	__disable_irq();
+	FTFL_FSTAT = FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL;
+	FTFL_FCCOB0 = 0x41;
+	FTFL_FCCOB1 = 15;
+	FTFL_FSTAT = FTFL_FSTAT_CCIF;
+	while (!(FTFL_FSTAT & FTFL_FSTAT_CCIF)) ; // wait
+	num = *(uint32_t *)&FTFL_FCCOB7;
+	__enable_irq();
+	ultoa(num, buf, 10);
+	for (i=0; i<10; i++) {
+		char c = buf[i];
+		if (!c) break;
+		usb_string_serial_number_default.wString[i] = c;
+	}
+	usb_string_serial_number_default.bLength = i * 2 + 2;
+}
+
+
+// **************************************************************
+//   Descriptors List
+// **************************************************************
+
+// This table provides access to all the descriptor data above.
+
+const usb_descriptor_list_t usb_descriptor_list[] = {
+	//wValue, wIndex, address,          length
+	{0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
+	{0x0200, 0x0000, config_descriptor, sizeof(config_descriptor)},
+#ifdef SEREMU_INTERFACE
+	{0x2200, SEREMU_INTERFACE, seremu_report_desc, sizeof(seremu_report_desc)},
+	{0x2100, SEREMU_INTERFACE, config_descriptor+SEREMU_DESC_OFFSET, 9},
+#endif
+#ifdef KEYBOARD_INTERFACE
+        {0x2200, KEYBOARD_INTERFACE, keyboard_report_desc, sizeof(keyboard_report_desc)},
+        {0x2100, KEYBOARD_INTERFACE, config_descriptor+KEYBOARD_DESC_OFFSET, 9},
+#endif
+#ifdef MOUSE_INTERFACE
+        {0x2200, MOUSE_INTERFACE, mouse_report_desc, sizeof(mouse_report_desc)},
+        {0x2100, MOUSE_INTERFACE, config_descriptor+MOUSE_DESC_OFFSET, 9},
+#endif
+#ifdef JOYSTICK_INTERFACE
+        {0x2200, JOYSTICK_INTERFACE, joystick_report_desc, sizeof(joystick_report_desc)},
+        {0x2100, JOYSTICK_INTERFACE, config_descriptor+JOYSTICK_DESC_OFFSET, 9},
+#endif
+#ifdef RAWHID_INTERFACE
+	{0x2200, RAWHID_INTERFACE, rawhid_report_desc, sizeof(rawhid_report_desc)},
+	{0x2100, RAWHID_INTERFACE, config_descriptor+RAWHID_DESC_OFFSET, 9},
+#endif
+#ifdef FLIGHTSIM_INTERFACE
+	{0x2200, FLIGHTSIM_INTERFACE, flightsim_report_desc, sizeof(flightsim_report_desc)},
+	{0x2100, FLIGHTSIM_INTERFACE, config_descriptor+FLIGHTSIM_DESC_OFFSET, 9},
+#endif
+        {0x0300, 0x0000, (const uint8_t *)&string0, 0},
+        {0x0301, 0x0409, (const uint8_t *)&usb_string_manufacturer_name, 0},
+        {0x0302, 0x0409, (const uint8_t *)&usb_string_product_name, 0},
+        {0x0303, 0x0409, (const uint8_t *)&usb_string_serial_number, 0},
+        //{0x0301, 0x0409, (const uint8_t *)&string1, 0},
+        //{0x0302, 0x0409, (const uint8_t *)&string2, 0},
+        //{0x0303, 0x0409, (const uint8_t *)&string3, 0},
+	{0, 0, NULL, 0}
+};
+
+
+// **************************************************************
+//   Endpoint Configuration
+// **************************************************************
+
+#if 0
+// 0x00 = not used
+// 0x19 = Recieve only
+// 0x15 = Transmit only
+// 0x1D = Transmit & Recieve
+// 
+const uint8_t usb_endpoint_config_table[NUM_ENDPOINTS] = 
+{
+	0x00, 0x15, 0x19, 0x15, 0x00, 0x00, 0x00, 0x00, 
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+};
+#endif
+
+
+const uint8_t usb_endpoint_config_table[NUM_ENDPOINTS] = 
+{
+#if (defined(ENDPOINT1_CONFIG) && NUM_ENDPOINTS >= 1)
+	ENDPOINT1_CONFIG,
+#elif (NUM_ENDPOINTS >= 1)
+	ENDPOINT_UNUSED,
+#endif
+#if (defined(ENDPOINT2_CONFIG) && NUM_ENDPOINTS >= 2)
+	ENDPOINT2_CONFIG,
+#elif (NUM_ENDPOINTS >= 2)
+	ENDPOINT_UNUSED,
+#endif
+#if (defined(ENDPOINT3_CONFIG) && NUM_ENDPOINTS >= 3)
+	ENDPOINT3_CONFIG,
+#elif (NUM_ENDPOINTS >= 3)
+	ENDPOINT_UNUSED,
+#endif
+#if (defined(ENDPOINT4_CONFIG) && NUM_ENDPOINTS >= 4)
+	ENDPOINT4_CONFIG,
+#elif (NUM_ENDPOINTS >= 4)
+	ENDPOINT_UNUSED,
+#endif
+#if (defined(ENDPOINT5_CONFIG) && NUM_ENDPOINTS >= 5)
+	ENDPOINT5_CONFIG,
+#elif (NUM_ENDPOINTS >= 5)
+	ENDPOINT_UNUSED,
+#endif
+#if (defined(ENDPOINT6_CONFIG) && NUM_ENDPOINTS >= 6)
+	ENDPOINT6_CONFIG,
+#elif (NUM_ENDPOINTS >= 6)
+	ENDPOINT_UNUSED,
+#endif
+#if (defined(ENDPOINT7_CONFIG) && NUM_ENDPOINTS >= 7)
+	ENDPOINT7_CONFIG,
+#elif (NUM_ENDPOINTS >= 7)
+	ENDPOINT_UNUSED,
+#endif
+#if (defined(ENDPOINT8_CONFIG) && NUM_ENDPOINTS >= 8)
+	ENDPOINT8_CONFIG,
+#elif (NUM_ENDPOINTS >= 8)
+	ENDPOINT_UNUSED,
+#endif
+#if (defined(ENDPOINT9_CONFIG) && NUM_ENDPOINTS >= 9)
+	ENDPOINT9_CONFIG,
+#elif (NUM_ENDPOINTS >= 9)
+	ENDPOINT_UNUSED,
+#endif
+#if (defined(ENDPOINT10_CONFIG) && NUM_ENDPOINTS >= 10)
+	ENDPOINT10_CONFIG,
+#elif (NUM_ENDPOINTS >= 10)
+	ENDPOINT_UNUSED,
+#endif
+#if (defined(ENDPOINT11_CONFIG) && NUM_ENDPOINTS >= 11)
+	ENDPOINT11_CONFIG,
+#elif (NUM_ENDPOINTS >= 11)
+	ENDPOINT_UNUSED,
+#endif
+#if (defined(ENDPOINT12_CONFIG) && NUM_ENDPOINTS >= 12)
+	ENDPOINT12_CONFIG,
+#elif (NUM_ENDPOINTS >= 12)
+	ENDPOINT_UNUSED,
+#endif
+#if (defined(ENDPOINT13_CONFIG) && NUM_ENDPOINTS >= 13)
+	ENDPOINT13_CONFIG,
+#elif (NUM_ENDPOINTS >= 13)
+	ENDPOINT_UNUSED,
+#endif
+#if (defined(ENDPOINT14_CONFIG) && NUM_ENDPOINTS >= 14)
+	ENDPOINT14_CONFIG,
+#elif (NUM_ENDPOINTS >= 14)
+	ENDPOINT_UNUSED,
+#endif
+#if (defined(ENDPOINT15_CONFIG) && NUM_ENDPOINTS >= 15)
+	ENDPOINT15_CONFIG,
+#elif (NUM_ENDPOINTS >= 15)
+	ENDPOINT_UNUSED,
+#endif
+};
+
+
+
+
diff --git a/teensy3/usb_desc.h b/teensy3/usb_desc.h
new file mode 100644
index 0000000000000000000000000000000000000000..958ca36d6c32de316a02711639618438f24440b8
--- /dev/null
+++ b/teensy3/usb_desc.h
@@ -0,0 +1,309 @@
+/* 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 _usb_desc_h_
+#define _usb_desc_h_
+
+// This header is NOT meant to be included when compiling
+// user sketches in Arduino.  The low-level functions
+// provided by usb_dev.c are meant to be called only by
+// code which provides higher-level interfaces to the user.
+
+#include <stdint.h>
+#include <stddef.h>
+
+#define ENDPOINT_UNUSED			0x00
+#define ENDPOINT_TRANSIMIT_ONLY		0x15
+#define ENDPOINT_RECEIVE_ONLY		0x19
+#define ENDPOINT_TRANSMIT_AND_RECEIVE	0x1D
+
+/*
+To modify a USB Type to have different interfaces, start in this
+file.  Delete the XYZ_INTERFACE lines for any interfaces you
+wish to remove, and copy them from another USB Type for any you
+want to add.
+
+Give each interface a unique number, and edit NUM_INTERFACE to
+reflect the number of interfaces.
+
+Within each interface, make sure it uses a unique set of endpoints.
+Edit NUM_ENDPOINTS to be at least the largest endpoint number used.
+Then edit the ENDPOINT*_CONFIG lines so each endpoint is configured
+the proper way (transmit, receive, or both).
+
+The CONFIG_DESC_SIZE and any XYZ_DESC_OFFSET numbers must be
+edited to the correct sizes.  See usb_desc.c for the giant array
+of bytes.  Someday these may be done automatically..... (but how?)
+
+If you are using existing interfaces, the code in each file should
+automatically adapt to the changes you specify.  If you need to
+create a new type of interface, you'll need to write the code which
+sends and receives packets, and presents an API to the user.
+
+Finally, edit usb_inst.cpp, which creats instances of the C++
+objects for each combination.
+
+Some operating systems, especially Windows, may cache USB device
+info.  Changes to the device name may not update on the same
+computer unless the vendor or product ID numbers change, or the
+"bcdDevice" revision code is increased.
+
+If these instructions are missing steps or could be improved, please
+let me know?  http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
+*/
+
+
+
+#if defined(USB_SERIAL)
+  #define VENDOR_ID		0x16C0
+  #define PRODUCT_ID		0x0483
+  #define DEVICE_CLASS		2	// 2 = Communication Class
+  #define MANUFACTURER_NAME	{'T','e','e','n','s','y','d','u','i','n','o'}
+  #define MANUFACTURER_NAME_LEN	11
+  #define PRODUCT_NAME		{'U','S','B',' ','S','e','r','i','a','l'}
+  #define PRODUCT_NAME_LEN	10
+  #define EP0_SIZE		64
+  #define NUM_ENDPOINTS		4
+  #define NUM_USB_BUFFERS	12
+  #define NUM_INTERFACE		2
+  #define CDC_STATUS_INTERFACE	0
+  #define CDC_DATA_INTERFACE	1
+  #define CDC_ACM_ENDPOINT	2
+  #define CDC_RX_ENDPOINT       3
+  #define CDC_TX_ENDPOINT       4
+  #define CDC_ACM_SIZE          16
+  #define CDC_RX_SIZE           64
+  #define CDC_TX_SIZE           64
+  #define CONFIG_DESC_SIZE	(9+9+5+5+4+5+7+9+7+7)
+  #define ENDPOINT2_CONFIG	ENDPOINT_TRANSIMIT_ONLY
+  #define ENDPOINT3_CONFIG	ENDPOINT_RECEIVE_ONLY
+  #define ENDPOINT4_CONFIG	ENDPOINT_TRANSIMIT_ONLY
+
+#elif defined(USB_HID)
+  #define VENDOR_ID		0x16C0
+  #define PRODUCT_ID		0x0482
+  #define MANUFACTURER_NAME	{'T','e','e','n','s','y','d','u','i','n','o'}
+  #define MANUFACTURER_NAME_LEN	11
+  #define PRODUCT_NAME		{'K','e','y','b','o','a','r','d','/','M','o','u','s','e','/','J','o','y','s','t','i','c','k'}
+  #define PRODUCT_NAME_LEN	23
+  #define EP0_SIZE		64
+  #define NUM_ENDPOINTS         5
+  #define NUM_USB_BUFFERS	24
+  #define NUM_INTERFACE		4
+  #define SEREMU_INTERFACE      2	// Serial emulation
+  #define SEREMU_TX_ENDPOINT    1
+  #define SEREMU_TX_SIZE        64
+  #define SEREMU_TX_INTERVAL    1
+  #define SEREMU_RX_ENDPOINT    2
+  #define SEREMU_RX_SIZE        32
+  #define SEREMU_RX_INTERVAL    2
+  #define KEYBOARD_INTERFACE    0	// Keyboard
+  #define KEYBOARD_ENDPOINT     3
+  #define KEYBOARD_SIZE         8
+  #define KEYBOARD_INTERVAL     1
+  #define MOUSE_INTERFACE       1	// Mouse
+  #define MOUSE_ENDPOINT        5
+  #define MOUSE_SIZE            8
+  #define MOUSE_INTERVAL        1
+  #define JOYSTICK_INTERFACE    3	// Joystick
+  #define JOYSTICK_ENDPOINT     4
+  #define JOYSTICK_SIZE         16
+  #define JOYSTICK_INTERVAL     2
+  #define KEYBOARD_DESC_OFFSET	(9 + 9)
+  #define MOUSE_DESC_OFFSET	(9 + 9+9+7 + 9)
+  #define SEREMU_DESC_OFFSET	(9 + 9+9+7 + 9+9+7 + 9)
+  #define JOYSTICK_DESC_OFFSET	(9 + 9+9+7 + 9+9+7 + 9+9+7+7 + 9)
+  #define CONFIG_DESC_SIZE	(9 + 9+9+7 + 9+9+7 + 9+9+7+7 + 9+9+7)
+  #define ENDPOINT1_CONFIG	ENDPOINT_TRANSIMIT_ONLY
+  #define ENDPOINT2_CONFIG	ENDPOINT_RECEIVE_ONLY
+  #define ENDPOINT3_CONFIG	ENDPOINT_TRANSIMIT_ONLY
+  #define ENDPOINT4_CONFIG	ENDPOINT_TRANSIMIT_ONLY
+  #define ENDPOINT5_CONFIG	ENDPOINT_TRANSIMIT_ONLY
+
+#elif defined(USB_SERIAL_HID)
+  #define VENDOR_ID		0x16C0
+  #define PRODUCT_ID		0x0487
+  #define DEVICE_CLASS		0xEF
+  #define DEVICE_SUBCLASS	0x02
+  #define DEVICE_PROTOCOL	0x01
+  #define MANUFACTURER_NAME	{'T','e','e','n','s','y','d','u','i','n','o'}
+  #define MANUFACTURER_NAME_LEN	11
+  #define PRODUCT_NAME		{'S','e','r','i','a','l','/','K','e','y','b','o','a','r','d','/','M','o','u','s','e','/','J','o','y','s','t','i','c','k'}
+  #define PRODUCT_NAME_LEN	30
+  #define EP0_SIZE		64
+  #define NUM_ENDPOINTS		6
+  #define NUM_USB_BUFFERS	30
+  #define NUM_INTERFACE		5
+  #define CDC_IAD_DESCRIPTOR	1
+  #define CDC_STATUS_INTERFACE	0
+  #define CDC_DATA_INTERFACE	1	// Serial
+  #define CDC_ACM_ENDPOINT	2
+  #define CDC_RX_ENDPOINT       3
+  #define CDC_TX_ENDPOINT       4
+  #define CDC_ACM_SIZE          16
+  #define CDC_RX_SIZE           64
+  #define CDC_TX_SIZE           64
+  #define KEYBOARD_INTERFACE    2	// Keyboard
+  #define KEYBOARD_ENDPOINT     1
+  #define KEYBOARD_SIZE         8
+  #define KEYBOARD_INTERVAL     1
+  #define MOUSE_INTERFACE       3	// Mouse
+  #define MOUSE_ENDPOINT        5
+  #define MOUSE_SIZE            8
+  #define MOUSE_INTERVAL        2
+  #define JOYSTICK_INTERFACE    4	// Joystick
+  #define JOYSTICK_ENDPOINT     6
+  #define JOYSTICK_SIZE         16
+  #define JOYSTICK_INTERVAL     1
+  #define KEYBOARD_DESC_OFFSET	(9+8 + 9+5+5+4+5+7+9+7+7 + 9)
+  #define MOUSE_DESC_OFFSET	(9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9)
+  #define JOYSTICK_DESC_OFFSET	(9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9)
+  #define CONFIG_DESC_SIZE	(9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9+9+7)
+  #define ENDPOINT1_CONFIG	ENDPOINT_TRANSIMIT_ONLY
+  #define ENDPOINT2_CONFIG	ENDPOINT_TRANSIMIT_ONLY
+  #define ENDPOINT3_CONFIG	ENDPOINT_RECEIVE_ONLY
+  #define ENDPOINT4_CONFIG	ENDPOINT_TRANSIMIT_ONLY
+  #define ENDPOINT5_CONFIG	ENDPOINT_TRANSIMIT_ONLY
+  #define ENDPOINT6_CONFIG	ENDPOINT_TRANSIMIT_ONLY
+
+#elif defined(USB_MIDI)
+  #define VENDOR_ID		0x16C0
+  #define PRODUCT_ID		0x0485
+  #define MANUFACTURER_NAME	{'T','e','e','n','s','y','d','u','i','n','o'}
+  #define MANUFACTURER_NAME_LEN	11
+  #define PRODUCT_NAME		{'T','e','e','n','s','y',' ','M','I','D','I'}
+  #define PRODUCT_NAME_LEN	11
+  #define EP0_SIZE		64
+  #define NUM_ENDPOINTS         4
+  #define NUM_USB_BUFFERS	16
+  #define NUM_INTERFACE		2
+  #define SEREMU_INTERFACE      1	// Serial emulation
+  #define SEREMU_TX_ENDPOINT    1
+  #define SEREMU_TX_SIZE        64
+  #define SEREMU_TX_INTERVAL    1
+  #define SEREMU_RX_ENDPOINT    2
+  #define SEREMU_RX_SIZE        32
+  #define SEREMU_RX_INTERVAL    2
+  #define MIDI_INTERFACE        0	// MIDI
+  #define MIDI_TX_ENDPOINT      3
+  #define MIDI_TX_SIZE          64
+  #define MIDI_RX_ENDPOINT      4
+  #define MIDI_RX_SIZE          64
+  #define SEREMU_DESC_OFFSET	(9 + 9+7+6+6+9+9+9+5+9+5 + 9)
+  #define CONFIG_DESC_SIZE	(9 + 9+7+6+6+9+9+9+5+9+5 + 9+9+7+7)
+  #define ENDPOINT1_CONFIG	ENDPOINT_TRANSIMIT_ONLY
+  #define ENDPOINT2_CONFIG	ENDPOINT_RECEIVE_ONLY
+  #define ENDPOINT3_CONFIG	ENDPOINT_TRANSIMIT_ONLY
+  #define ENDPOINT4_CONFIG	ENDPOINT_RECEIVE_ONLY
+
+#elif defined(USB_RAWHID)
+  #define VENDOR_ID		0x16C0
+  #define PRODUCT_ID		0x0486
+  #define RAWHID_USAGE_PAGE	0xFFAB  // recommended: 0xFF00 to 0xFFFF
+  #define RAWHID_USAGE		0x0200  // recommended: 0x0100 to 0xFFFF
+  #define MANUFACTURER_NAME	{'T','e','e','n','s','y','d','u','i','n','o'}
+  #define MANUFACTURER_NAME_LEN	11
+  #define PRODUCT_NAME		{'T','e','e','n','s','y','d','u','i','n','o',' ','R','a','w','H','I','D'}
+  #define PRODUCT_NAME_LEN	18
+  #define EP0_SIZE		64
+  #define NUM_ENDPOINTS         6
+  #define NUM_USB_BUFFERS	12
+  #define NUM_INTERFACE		2
+  #define RAWHID_INTERFACE      0	// RawHID
+  #define RAWHID_TX_ENDPOINT    3
+  #define RAWHID_TX_SIZE        64
+  #define RAWHID_TX_INTERVAL    1
+  #define RAWHID_RX_ENDPOINT    4
+  #define RAWHID_RX_SIZE        64
+  #define RAWHID_RX_INTERVAL    1
+  #define SEREMU_INTERFACE      1	// Serial emulation
+  #define SEREMU_TX_ENDPOINT    1
+  #define SEREMU_TX_SIZE        64
+  #define SEREMU_TX_INTERVAL    1
+  #define SEREMU_RX_ENDPOINT    2
+  #define SEREMU_RX_SIZE        32
+  #define SEREMU_RX_INTERVAL    2
+  #define RAWHID_DESC_OFFSET	(9 + 9)
+  #define SEREMU_DESC_OFFSET	(9 + 9+9+7+7 + 9)
+  #define CONFIG_DESC_SIZE	(9 + 9+9+7+7 + 9+9+7+7)
+  #define ENDPOINT1_CONFIG	ENDPOINT_TRANSIMIT_ONLY
+  #define ENDPOINT2_CONFIG	ENDPOINT_RECEIVE_ONLY
+  #define ENDPOINT3_CONFIG	ENDPOINT_TRANSIMIT_ONLY
+  #define ENDPOINT4_CONFIG	ENDPOINT_RECEIVE_ONLY
+
+#elif defined(USB_FLIGHTSIM)
+  #define VENDOR_ID		0x16C0
+  #define PRODUCT_ID		0x0488
+  #define MANUFACTURER_NAME	{'T','e','e','n','s','y','d','u','i','n','o'}
+  #define MANUFACTURER_NAME_LEN	11
+  #define PRODUCT_NAME		{'T','e','e','n','s','y',' ','F','l','i','g','h','t',' ','S','i','m',' ','C','o','n','t','r','o','l','s'}
+  #define PRODUCT_NAME_LEN	26
+  #define EP0_SIZE		64
+  #define NUM_ENDPOINTS         4
+  #define NUM_USB_BUFFERS	20
+  #define NUM_INTERFACE		2
+  #define FLIGHTSIM_INTERFACE	0	// Flight Sim Control
+  #define FLIGHTSIM_TX_ENDPOINT	3
+  #define FLIGHTSIM_TX_SIZE	64
+  #define FLIGHTSIM_TX_INTERVAL	1
+  #define FLIGHTSIM_RX_ENDPOINT	4
+  #define FLIGHTSIM_RX_SIZE	64
+  #define FLIGHTSIM_RX_INTERVAL	1
+  #define SEREMU_INTERFACE      1	// Serial emulation
+  #define SEREMU_TX_ENDPOINT    1
+  #define SEREMU_TX_SIZE        64
+  #define SEREMU_TX_INTERVAL    1
+  #define SEREMU_RX_ENDPOINT    2
+  #define SEREMU_RX_SIZE        32
+  #define SEREMU_RX_INTERVAL    2
+  #define FLIGHTSIM_DESC_OFFSET	(9 + 9)
+  #define SEREMU_DESC_OFFSET	(9 + 9+9+7+7 + 9)
+  #define CONFIG_DESC_SIZE	(9 + 9+9+7+7 + 9+9+7+7)
+  #define ENDPOINT1_CONFIG	ENDPOINT_TRANSIMIT_ONLY
+  #define ENDPOINT2_CONFIG	ENDPOINT_RECEIVE_ONLY
+  #define ENDPOINT3_CONFIG	ENDPOINT_TRANSIMIT_ONLY
+  #define ENDPOINT4_CONFIG	ENDPOINT_RECEIVE_ONLY
+
+#endif
+
+// NUM_ENDPOINTS = number of non-zero endpoints (0 to 15)
+extern const uint8_t usb_endpoint_config_table[NUM_ENDPOINTS];
+
+typedef struct {
+	uint16_t	wValue;
+	uint16_t	wIndex;
+	const uint8_t	*addr;
+	uint16_t	length;
+} usb_descriptor_list_t;
+
+extern const usb_descriptor_list_t usb_descriptor_list[];
+
+
+#endif
diff --git a/teensy3/usb_dev.c b/teensy3/usb_dev.c
new file mode 100644
index 0000000000000000000000000000000000000000..af99e9136a98fa64f1863c4caa333a50238f3a26
--- /dev/null
+++ b/teensy3/usb_dev.c
@@ -0,0 +1,968 @@
+/* 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 "HardwareSerial.h"
+#include "usb_dev.h"
+#include "usb_mem.h"
+
+// buffer descriptor table
+
+typedef struct {
+	uint32_t desc;
+	void * addr;
+} bdt_t;
+
+__attribute__ ((section(".usbdescriptortable"), used))
+static bdt_t table[(NUM_ENDPOINTS+1)*4];
+
+static usb_packet_t *rx_first[NUM_ENDPOINTS];
+static usb_packet_t *rx_last[NUM_ENDPOINTS];
+static usb_packet_t *tx_first[NUM_ENDPOINTS];
+static usb_packet_t *tx_last[NUM_ENDPOINTS];
+uint16_t usb_rx_byte_count_data[NUM_ENDPOINTS];
+
+static uint8_t tx_state[NUM_ENDPOINTS];
+#define TX_STATE_BOTH_FREE_EVEN_FIRST	0
+#define TX_STATE_BOTH_FREE_ODD_FIRST	1
+#define TX_STATE_EVEN_FREE		2
+#define TX_STATE_ODD_FREE		3
+#define TX_STATE_NONE_FREE_EVEN_FIRST	4
+#define TX_STATE_NONE_FREE_ODD_FIRST	5
+
+#define BDT_OWN		0x80
+#define BDT_DATA1	0x40
+#define BDT_DATA0	0x00
+#define BDT_DTS		0x08
+#define BDT_STALL	0x04
+#define BDT_PID(n)	(((n) >> 2) & 15)
+
+#define BDT_DESC(count, data)	(BDT_OWN | BDT_DTS \
+				| ((data) ? BDT_DATA1 : BDT_DATA0) \
+				| ((count) << 16))
+
+#define TX   1
+#define RX   0
+#define ODD  1
+#define EVEN 0
+#define DATA0 0
+#define DATA1 1
+#define index(endpoint, tx, odd) (((endpoint) << 2) | ((tx) << 1) | (odd))
+#define stat2bufferdescriptor(stat) (table + ((stat) >> 2))
+
+
+static union {
+ struct {
+  union {
+   struct {
+	uint8_t bmRequestType;
+	uint8_t bRequest;
+   };
+	uint16_t wRequestAndType;
+  };
+	uint16_t wValue;
+	uint16_t wIndex;
+	uint16_t wLength;
+ };
+ struct {
+	uint32_t word1;
+	uint32_t word2;
+ };
+} setup;
+
+
+#define GET_STATUS		0
+#define CLEAR_FEATURE		1
+#define SET_FEATURE		3
+#define SET_ADDRESS		5
+#define GET_DESCRIPTOR		6
+#define SET_DESCRIPTOR		7
+#define GET_CONFIGURATION	8
+#define SET_CONFIGURATION	9
+#define GET_INTERFACE		10
+#define SET_INTERFACE		11
+#define SYNCH_FRAME		12
+
+// SETUP always uses a DATA0 PID for the data field of the SETUP transaction.
+// transactions in the data phase start with DATA1 and toggle (figure 8-12, USB1.1)
+// Status stage uses a DATA1 PID.
+
+static uint8_t ep0_rx0_buf[EP0_SIZE] __attribute__ ((aligned (4)));
+static uint8_t ep0_rx1_buf[EP0_SIZE] __attribute__ ((aligned (4)));
+static const uint8_t *ep0_tx_ptr = NULL;
+static uint16_t ep0_tx_len;
+static uint8_t ep0_tx_bdt_bank = 0;
+static uint8_t ep0_tx_data_toggle = 0;
+uint8_t usb_rx_memory_needed = 0;
+
+volatile uint8_t usb_configuration = 0;
+volatile uint8_t usb_reboot_timer = 0;
+
+
+static void endpoint0_stall(void)
+{
+	USB0_ENDPT0 = USB_ENDPT_EPSTALL | USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK;
+}
+
+
+static void endpoint0_transmit(const void *data, uint32_t len)
+{
+#if 0
+	serial_print("tx0:");
+	serial_phex32((uint32_t)data);
+	serial_print(",");
+	serial_phex16(len);
+	serial_print(ep0_tx_bdt_bank ? ", odd" : ", even");
+	serial_print(ep0_tx_data_toggle ? ", d1\n" : ", d0\n");
+#endif
+	table[index(0, TX, ep0_tx_bdt_bank)].addr = (void *)data;
+	table[index(0, TX, ep0_tx_bdt_bank)].desc = BDT_DESC(len, ep0_tx_data_toggle);
+	ep0_tx_data_toggle ^= 1;
+	ep0_tx_bdt_bank ^= 1;
+}
+
+static uint8_t reply_buffer[8];
+
+static void usb_setup(void)
+{
+	const uint8_t *data = NULL;
+	uint32_t datalen = 0;
+	const usb_descriptor_list_t *list;
+	uint32_t size;
+	volatile uint8_t *reg;
+	uint8_t epconf;
+	const uint8_t *cfg;
+	int i;
+
+	switch (setup.wRequestAndType) {
+	  case 0x0500: // SET_ADDRESS
+		break;
+	  case 0x0900: // SET_CONFIGURATION
+		//serial_print("configure\n");
+		usb_configuration = setup.wValue;
+		reg = &USB0_ENDPT1;
+		cfg = usb_endpoint_config_table;
+		// clear all BDT entries, free any allocated memory...
+		for (i=4; i <= NUM_ENDPOINTS*4; i++) {
+			if (table[i].desc & BDT_OWN) {
+				usb_free((usb_packet_t *)((uint8_t *)(table[i].addr) - 8));
+			}
+		}
+		// free all queued packets
+		for (i=0; i < NUM_ENDPOINTS; i++) {
+			usb_packet_t *p, *n;
+			p = rx_first[i];
+			while (p) {
+				n = p->next;
+				usb_free(p);
+				p = n;
+			}
+			rx_first[i] = NULL;
+			rx_last[i] = NULL;
+			p = tx_first[i];
+			while (p) {
+				n = p->next;
+				usb_free(p);
+				p = n;
+			}
+			tx_first[i] = NULL;
+			tx_last[i] = NULL;
+			usb_rx_byte_count_data[i] = 0;
+			switch (tx_state[i]) {
+			  case TX_STATE_EVEN_FREE:
+			  case TX_STATE_NONE_FREE_EVEN_FIRST:
+				tx_state[i] = TX_STATE_BOTH_FREE_EVEN_FIRST;
+				break;
+			  case TX_STATE_ODD_FREE:
+			  case TX_STATE_NONE_FREE_ODD_FIRST:
+				tx_state[i] = TX_STATE_BOTH_FREE_ODD_FIRST;
+				break;
+			  default:
+				break;
+			}
+		}
+		usb_rx_memory_needed = 0;
+		for (i=1; i <= NUM_ENDPOINTS; i++) {
+			epconf = *cfg++;
+			*reg = epconf;
+			reg += 4;
+			if (epconf & USB_ENDPT_EPRXEN) {
+				usb_packet_t *p;
+				p = usb_malloc();
+				if (p) {
+					table[index(i, RX, EVEN)].addr = p->buf;
+					table[index(i, RX, EVEN)].desc = BDT_DESC(64, 0);
+				} else {
+					table[index(i, RX, EVEN)].desc = 0;
+					usb_rx_memory_needed++;
+				}
+				p = usb_malloc();
+				if (p) {
+					table[index(i, RX, ODD)].addr = p->buf;
+					table[index(i, RX, ODD)].desc = BDT_DESC(64, 1);
+				} else {
+					table[index(i, RX, ODD)].desc = 0;
+					usb_rx_memory_needed++;
+				}
+			}
+			table[index(i, TX, EVEN)].desc = 0;
+			table[index(i, TX, ODD)].desc = 0;
+		}
+		break;
+	  case 0x0880: // GET_CONFIGURATION
+		reply_buffer[0] = usb_configuration;
+		datalen = 1;
+		data = reply_buffer;
+		break;
+	  case 0x0080: // GET_STATUS (device)
+		reply_buffer[0] = 0;
+		reply_buffer[1] = 0;
+		datalen = 2;
+		data = reply_buffer;
+		break;
+	  case 0x0082: // GET_STATUS (endpoint)
+		if (setup.wIndex > NUM_ENDPOINTS) {
+			// TODO: do we need to handle IN vs OUT here?
+			endpoint0_stall();
+			return;
+		}
+		reply_buffer[0] = 0;
+		reply_buffer[1] = 0;
+		if (*(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4) & 0x02) reply_buffer[0] = 1;
+		data = reply_buffer;
+		datalen = 2;
+		break;
+	  case 0x0102: // CLEAR_FEATURE (endpoint)
+		i = setup.wIndex & 0x7F;
+		if (i > NUM_ENDPOINTS || setup.wValue != 0) {
+			// TODO: do we need to handle IN vs OUT here?
+			endpoint0_stall();
+			return;
+		}
+		(*(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4)) &= ~0x02;
+		// TODO: do we need to clear the data toggle here?
+		break;
+	  case 0x0302: // SET_FEATURE (endpoint)
+		i = setup.wIndex & 0x7F;
+		if (i > NUM_ENDPOINTS || setup.wValue != 0) {
+			// TODO: do we need to handle IN vs OUT here?
+			endpoint0_stall();
+			return;
+		}
+		(*(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4)) |= 0x02;
+		// TODO: do we need to clear the data toggle here?
+		break;
+	  case 0x0680: // GET_DESCRIPTOR
+	  case 0x0681:
+		//serial_print("desc:");
+		//serial_phex16(setup.wValue);
+		//serial_print("\n");
+		for (list = usb_descriptor_list; 1; list++) {
+			if (list->addr == NULL) break;
+			//if (setup.wValue == list->wValue && 
+			//(setup.wIndex == list->wIndex) || ((setup.wValue >> 8) == 3)) {
+			if (setup.wValue == list->wValue && setup.wIndex == list->wIndex) {
+				data = list->addr;
+				if ((setup.wValue >> 8) == 3) {
+					// for string descriptors, use the descriptor's
+					// length field, allowing runtime configured
+					// length.
+					datalen = *(list->addr);
+				} else {
+					datalen = list->length;
+				}
+#if 0
+				serial_print("Desc found, ");
+				serial_phex32((uint32_t)data);
+				serial_print(",");
+				serial_phex16(datalen);
+				serial_print(",");
+				serial_phex(data[0]);
+				serial_phex(data[1]);
+				serial_phex(data[2]);
+				serial_phex(data[3]);
+				serial_phex(data[4]);
+				serial_phex(data[5]);
+				serial_print("\n");
+#endif
+				goto send;
+			}
+		}
+		//serial_print("desc: not found\n");
+		endpoint0_stall();
+		return;
+#if defined(CDC_STATUS_INTERFACE)
+	  case 0x2221: // CDC_SET_CONTROL_LINE_STATE
+		usb_cdc_line_rtsdtr = setup.wValue;
+		//serial_print("set control line state\n");
+		break;
+	  case 0x2021: // CDC_SET_LINE_CODING
+		//serial_print("set coding, waiting...\n");
+		return;
+#endif
+
+// TODO: this does not work... why?
+#if defined(SEREMU_INTERFACE) || defined(KEYBOARD_INTERFACE)
+	  case 0x0921: // HID SET_REPORT
+		//serial_print(":)\n");
+		return;
+	  case 0x0A21: // HID SET_IDLE
+		break;
+	  // case 0xC940:
+#endif
+	  default:
+		endpoint0_stall();
+		return;
+	}
+	send:
+	//serial_print("setup send ");
+	//serial_phex32(data);
+	//serial_print(",");
+	//serial_phex16(datalen);
+	//serial_print("\n");
+
+	if (datalen > setup.wLength) datalen = setup.wLength;
+	size = datalen;
+	if (size > EP0_SIZE) size = EP0_SIZE;
+	endpoint0_transmit(data, size);
+	data += size;
+	datalen -= size;
+	if (datalen == 0 && size < EP0_SIZE) return;
+
+	size = datalen;
+	if (size > EP0_SIZE) size = EP0_SIZE;
+	endpoint0_transmit(data, size);
+	data += size;
+	datalen -= size;
+	if (datalen == 0 && size < EP0_SIZE) return;
+
+	ep0_tx_ptr = data;
+	ep0_tx_len = datalen;
+}
+
+
+
+//A bulk endpoint's toggle sequence is initialized to DATA0 when the endpoint
+//experiences any configuration event (configuration events are explained in
+//Sections 9.1.1.5 and 9.4.5).
+
+//Configuring a device or changing an alternate setting causes all of the status
+//and configuration values associated with endpoints in the affected interfaces
+//to be set to their default values. This includes setting the data toggle of
+//any endpoint using data toggles to the value DATA0.
+
+//For endpoints using data toggle, regardless of whether an endpoint has the
+//Halt feature set, a ClearFeature(ENDPOINT_HALT) request always results in the
+//data toggle being reinitialized to DATA0.
+
+
+
+// #define stat2bufferdescriptor(stat) (table + ((stat) >> 2))
+
+static void usb_control(uint32_t stat)
+{
+	bdt_t *b;
+	uint32_t pid, size;
+	uint8_t *buf;
+	const uint8_t *data;
+
+	b = stat2bufferdescriptor(stat);
+	pid = BDT_PID(b->desc);
+	//count = b->desc >> 16;
+	buf = b->addr;
+	//serial_print("pid:");
+	//serial_phex(pid);
+	//serial_print(", count:");
+	//serial_phex(count);
+	//serial_print("\n");
+
+	switch (pid) {
+	case 0x0D: // Setup received from host
+		//serial_print("PID=Setup\n");
+		//if (count != 8) ; // panic?
+		// grab the 8 byte setup info
+		setup.word1 = *(uint32_t *)(buf);
+		setup.word2 = *(uint32_t *)(buf + 4);
+
+		// give the buffer back
+		b->desc = BDT_DESC(EP0_SIZE, DATA1);
+		//table[index(0, RX, EVEN)].desc = BDT_DESC(EP0_SIZE, 1);
+		//table[index(0, RX, ODD)].desc = BDT_DESC(EP0_SIZE, 1);
+
+		// clear any leftover pending IN transactions
+		ep0_tx_ptr = NULL;
+		if (ep0_tx_data_toggle) {
+		}
+		//if (table[index(0, TX, EVEN)].desc & 0x80) {
+			//serial_print("leftover tx even\n");
+		//}
+		//if (table[index(0, TX, ODD)].desc & 0x80) {
+			//serial_print("leftover tx odd\n");
+		//}
+		table[index(0, TX, EVEN)].desc = 0;
+		table[index(0, TX, ODD)].desc = 0;
+		// first IN after Setup is always DATA1
+		ep0_tx_data_toggle = 1;
+
+#if 0
+		serial_print("bmRequestType:");
+		serial_phex(setup.bmRequestType);
+		serial_print(", bRequest:");
+		serial_phex(setup.bRequest);
+		serial_print(", wValue:");
+		serial_phex16(setup.wValue);
+		serial_print(", wIndex:");
+		serial_phex16(setup.wIndex);
+		serial_print(", len:");
+		serial_phex16(setup.wLength);
+		serial_print("\n");
+#endif
+		// actually "do" the setup request
+		usb_setup();
+		// unfreeze the USB, now that we're ready
+		USB0_CTL = USB_CTL_USBENSOFEN; // clear TXSUSPENDTOKENBUSY bit
+		break;
+	case 0x01:  // OUT transaction received from host
+	case 0x02:
+		//serial_print("PID=OUT\n");
+#ifdef CDC_STATUS_INTERFACE
+		if (setup.wRequestAndType == 0x2021 /*CDC_SET_LINE_CODING*/) {
+			int i;
+			uint8_t *dst = (uint8_t *)usb_cdc_line_coding;
+			//serial_print("set line coding ");
+			for (i=0; i<7; i++) {
+				//serial_phex(*buf);
+				*dst++ = *buf++;
+			}
+			//serial_phex32(usb_cdc_line_coding[0]);
+			//serial_print("\n");
+			if (usb_cdc_line_coding[0] == 134) usb_reboot_timer = 15;
+			endpoint0_transmit(NULL, 0);
+		}
+#endif
+#ifdef KEYBOARD_INTERFACE
+		if (setup.word1 == 0x02000921 && setup.word2 == ((1<<16)|KEYBOARD_INTERFACE)) {
+			keyboard_leds = buf[0];
+			endpoint0_transmit(NULL, 0);
+		}
+#endif
+#ifdef SEREMU_INTERFACE
+		if (setup.word1 == 0x03000921 && setup.word2 == ((4<<16)|SEREMU_INTERFACE)
+		  && buf[0] == 0xA9 && buf[1] == 0x45 && buf[2] == 0xC2 && buf[3] == 0x6B) {
+			usb_reboot_timer = 5;
+			endpoint0_transmit(NULL, 0);
+		}
+#endif
+		// give the buffer back
+		b->desc = BDT_DESC(EP0_SIZE, DATA1);
+		break;
+
+	case 0x09: // IN transaction completed to host
+		//serial_print("PID=IN:");
+		//serial_phex(stat);
+		//serial_print("\n");
+
+		// send remaining data, if any...
+		data = ep0_tx_ptr;
+		if (data) {
+			size = ep0_tx_len;
+			if (size > EP0_SIZE) size = EP0_SIZE;
+			endpoint0_transmit(data, size);
+			data += size;
+			ep0_tx_len -= size;
+			ep0_tx_ptr = (ep0_tx_len > 0 || size == EP0_SIZE) ? data : NULL;
+		}
+
+		if (setup.bRequest == 5 && setup.bmRequestType == 0) {
+			setup.bRequest = 0;
+			//serial_print("set address: ");
+			//serial_phex16(setup.wValue);
+			//serial_print("\n");
+			USB0_ADDR = setup.wValue;
+		}
+
+		break;
+	//default:
+		//serial_print("PID=unknown:");
+		//serial_phex(pid);
+		//serial_print("\n");
+	}
+	USB0_CTL = USB_CTL_USBENSOFEN; // clear TXSUSPENDTOKENBUSY bit
+}
+
+
+
+
+
+
+usb_packet_t *usb_rx(uint32_t endpoint)
+{
+	usb_packet_t *ret;
+	endpoint--;
+	if (endpoint >= NUM_ENDPOINTS) return NULL;
+	__disable_irq();
+	ret = rx_first[endpoint];
+	if (ret) rx_first[endpoint] = ret->next;
+	usb_rx_byte_count_data[endpoint] -= ret->len;
+	__enable_irq();
+	//serial_print("rx, epidx=");
+	//serial_phex(endpoint);
+	//serial_print(", packet=");
+	//serial_phex32(ret);
+	//serial_print("\n");
+	return ret;
+}
+
+static uint32_t usb_queue_byte_count(const usb_packet_t *p)
+{
+	uint32_t count=0;
+
+	__disable_irq();
+	for ( ; p; p = p->next) {
+		count += p->len;
+	}
+	__enable_irq();
+	return count;
+}
+
+// TODO: make this an inline function...
+/*
+uint32_t usb_rx_byte_count(uint32_t endpoint)
+{
+	endpoint--;
+	if (endpoint >= NUM_ENDPOINTS) return 0;
+	return usb_rx_byte_count_data[endpoint];
+	//return usb_queue_byte_count(rx_first[endpoint]);
+}
+*/
+
+uint32_t usb_tx_byte_count(uint32_t endpoint)
+{
+	endpoint--;
+	if (endpoint >= NUM_ENDPOINTS) return 0;
+	return usb_queue_byte_count(tx_first[endpoint]);
+}
+
+uint32_t usb_tx_packet_count(uint32_t endpoint)
+{
+	const usb_packet_t *p;
+	uint32_t count=0;
+
+	endpoint--;
+	if (endpoint >= NUM_ENDPOINTS) return 0;
+	p = tx_first[endpoint];
+	__disable_irq();
+	for ( ; p; p = p->next) count++;
+	__enable_irq();
+	return count;
+}
+
+
+// Called from usb_free, but only when usb_rx_memory_needed > 0, indicating
+// receive endpoints are starving for memory.  The intention is to give
+// endpoints needing receive memory priority over the user's code, which is
+// likely calling usb_malloc to obtain memory for transmitting.  When the
+// user is creating data very quickly, their consumption could starve reception
+// without this prioritization.  The packet buffer (input) is assigned to the
+// first endpoint needing memory.
+//
+void usb_rx_memory(usb_packet_t *packet)
+{
+	unsigned int i;
+	const uint8_t *cfg;
+
+	cfg = usb_endpoint_config_table;
+	//serial_print("rx_mem:");
+	__disable_irq();
+	for (i=1; i <= NUM_ENDPOINTS; i++) {
+		if (*cfg++ & USB_ENDPT_EPRXEN) {
+			if (table[index(i, RX, EVEN)].desc == 0) {
+				table[index(i, RX, EVEN)].addr = packet->buf;
+				table[index(i, RX, EVEN)].desc = BDT_DESC(64, 0);
+				usb_rx_memory_needed--;
+				__enable_irq();
+				//serial_phex(i);
+				//serial_print(",even\n");
+				return;
+			}
+			if (table[index(i, RX, ODD)].desc == 0) {
+				table[index(i, RX, ODD)].addr = packet->buf;
+				table[index(i, RX, ODD)].desc = BDT_DESC(64, 1);
+				usb_rx_memory_needed--;
+				__enable_irq();
+				//serial_phex(i);
+				//serial_print(",odd\n");
+				return;
+			}
+		}
+	}
+	__enable_irq();
+	// we should never reach this point.  If we get here, it means
+	// usb_rx_memory_needed was set greater than zero, but no memory
+	// was actually needed.  
+	usb_rx_memory_needed = 0;
+	usb_free(packet);
+	return;
+}
+
+//#define index(endpoint, tx, odd) (((endpoint) << 2) | ((tx) << 1) | (odd))
+//#define stat2bufferdescriptor(stat) (table + ((stat) >> 2))
+
+void usb_tx(uint32_t endpoint, usb_packet_t *packet)
+{
+	bdt_t *b = &table[index(endpoint, TX, EVEN)];
+	uint8_t next;
+
+	endpoint--;
+	if (endpoint >= NUM_ENDPOINTS) return;
+	__disable_irq();
+	//serial_print("txstate=");
+	//serial_phex(tx_state[endpoint]);
+	//serial_print("\n");
+	switch (tx_state[endpoint]) {
+	  case TX_STATE_BOTH_FREE_EVEN_FIRST:
+		next = TX_STATE_ODD_FREE;
+		break;
+	  case TX_STATE_BOTH_FREE_ODD_FIRST:
+		b++;
+		next = TX_STATE_EVEN_FREE;
+		break;
+	  case TX_STATE_EVEN_FREE:
+		next = TX_STATE_NONE_FREE_ODD_FIRST;
+		break;
+	  case TX_STATE_ODD_FREE:
+		b++;
+		next = TX_STATE_NONE_FREE_EVEN_FIRST;
+		break;
+	  default:
+		if (tx_first[endpoint] == NULL) {
+			tx_first[endpoint] = packet;
+		} else {
+			tx_last[endpoint]->next = packet;
+		}
+		tx_last[endpoint] = packet;
+		__enable_irq();
+		return;
+	}
+	tx_state[endpoint] = next;
+	b->addr = packet->buf;
+	b->desc = BDT_DESC(packet->len, ((uint32_t)b & 8) ? DATA1 : DATA0);
+	__enable_irq();
+}
+
+
+
+
+
+
+void _reboot_Teensyduino_(void)
+{
+	// TODO: initialize R0 with a code....
+	asm volatile("bkpt");
+}
+
+
+
+void usb_isr(void)
+{
+	uint8_t status, stat, t;
+
+	//serial_print("isr");
+	//status = USB0_ISTAT;
+	//serial_phex(status);
+	//serial_print("\n");
+	restart:
+	status = USB0_ISTAT;
+
+	if ((status & USB_INTEN_SOFTOKEN /* 04 */ )) {
+		if (usb_configuration) {
+			t = usb_reboot_timer;
+			if (t) {
+				usb_reboot_timer = --t;
+				if (!t) _reboot_Teensyduino_();
+			}
+#ifdef CDC_DATA_INTERFACE
+			t = usb_cdc_transmit_flush_timer;
+			if (t) {
+				usb_cdc_transmit_flush_timer = --t;
+				if (t == 0) usb_serial_flush_callback();
+			}
+#endif
+#ifdef SEREMU_INTERFACE
+			t = usb_seremu_transmit_flush_timer;
+			if (t) {
+				usb_seremu_transmit_flush_timer = --t;
+				if (t == 0) usb_seremu_flush_callback();
+			}
+#endif
+#ifdef MIDI_INTERFACE
+                        usb_midi_flush_output();
+#endif
+#ifdef FLIGHTSIM_INTERFACE
+			usb_flightsim_flush_callback();
+#endif
+		}
+		USB0_ISTAT = USB_INTEN_SOFTOKEN;
+	}
+
+	if ((status & USB_ISTAT_TOKDNE /* 08 */ )) {
+		uint8_t endpoint;
+		stat = USB0_STAT;
+		//serial_print("token: ep=");
+		//serial_phex(stat >> 4);
+		//serial_print(stat & 0x08 ? ",tx" : ",rx");
+		//serial_print(stat & 0x04 ? ",odd\n" : ",even\n");
+		endpoint = stat >> 4;
+		if (endpoint == 0) {
+			usb_control(stat);
+		} else {
+			bdt_t *b = stat2bufferdescriptor(stat);
+			usb_packet_t *packet = (usb_packet_t *)((uint8_t *)(b->addr) - 8);
+#if 0
+			serial_print("ep:");
+			serial_phex(endpoint);
+			serial_print(", pid:");
+			serial_phex(BDT_PID(b->desc));
+			serial_print(((uint32_t)b & 8) ? ", odd" : ", even");
+			serial_print(", count:");
+			serial_phex(b->desc >> 16);
+			serial_print("\n");
+#endif
+			endpoint--;	// endpoint is index to zero-based arrays
+
+			if (stat & 0x08) { // transmit
+				usb_free(packet);
+				packet = tx_first[endpoint];
+				if (packet) {
+					//serial_print("tx packet\n");
+					tx_first[endpoint] = packet->next;
+					b->addr = packet->buf;
+					switch (tx_state[endpoint]) {
+					  case TX_STATE_BOTH_FREE_EVEN_FIRST:
+						tx_state[endpoint] = TX_STATE_ODD_FREE;
+						break;
+					  case TX_STATE_BOTH_FREE_ODD_FIRST:
+						tx_state[endpoint] = TX_STATE_EVEN_FREE;
+						break;
+					  case TX_STATE_EVEN_FREE:
+						tx_state[endpoint] = TX_STATE_NONE_FREE_ODD_FIRST;
+						break;
+					  case TX_STATE_ODD_FREE:
+						tx_state[endpoint] = TX_STATE_NONE_FREE_EVEN_FIRST;
+						break;
+					  default:
+						break;
+					}
+					b->desc = BDT_DESC(packet->len, ((uint32_t)b & 8) ? DATA1 : DATA0);
+				} else {
+					//serial_print("tx no packet\n");
+					switch (tx_state[endpoint]) {
+					  case TX_STATE_BOTH_FREE_EVEN_FIRST:
+					  case TX_STATE_BOTH_FREE_ODD_FIRST:
+						break;
+					  case TX_STATE_EVEN_FREE:
+						tx_state[endpoint] = TX_STATE_BOTH_FREE_EVEN_FIRST;
+						break;
+					  case TX_STATE_ODD_FREE:
+						tx_state[endpoint] = TX_STATE_BOTH_FREE_ODD_FIRST;
+						break;
+					  default:
+						tx_state[endpoint] = ((uint32_t)b & 8) ?
+						  TX_STATE_ODD_FREE : TX_STATE_EVEN_FREE;
+						break;
+					}
+				}
+			} else { // receive
+				packet->len = b->desc >> 16;
+				if (packet->len > 0) {
+					packet->index = 0;
+					packet->next = NULL;
+					if (rx_first[endpoint] == NULL) {
+						//serial_print("rx 1st, epidx=");
+						//serial_phex(endpoint);
+						//serial_print(", packet=");
+						//serial_phex32((uint32_t)packet);
+						//serial_print("\n");
+						rx_first[endpoint] = packet;
+					} else {
+						//serial_print("rx Nth, epidx=");
+						//serial_phex(endpoint);
+						//serial_print(", packet=");
+						//serial_phex32((uint32_t)packet);
+						//serial_print("\n");
+						rx_last[endpoint]->next = packet;
+					}
+					rx_last[endpoint] = packet;
+					usb_rx_byte_count_data[endpoint] += packet->len;
+					// TODO: implement a per-endpoint maximum # of allocated packets
+					// so a flood of incoming data on 1 endpoint doesn't starve
+					// the others if the user isn't reading it regularly
+					packet = usb_malloc();
+					if (packet) {
+						b->addr = packet->buf;
+						b->desc = BDT_DESC(64, ((uint32_t)b & 8) ? DATA1 : DATA0);
+					} else {
+						//serial_print("starving ");
+						//serial_phex(endpoint + 1);
+						//serial_print(((uint32_t)b & 8) ? ",odd\n" : ",even\n");
+						b->desc = 0;
+						usb_rx_memory_needed++;
+					}
+				} else {
+					b->desc = BDT_DESC(64, ((uint32_t)b & 8) ? DATA1 : DATA0);
+				}
+			}
+
+
+
+
+		}
+		USB0_ISTAT = USB_ISTAT_TOKDNE;
+		goto restart;
+	}
+
+
+
+	if (status & USB_ISTAT_USBRST /* 01 */ ) {
+		//serial_print("reset\n");
+
+		// initialize BDT toggle bits
+		USB0_CTL = USB_CTL_ODDRST;
+		ep0_tx_bdt_bank = 0;
+
+		// set up buffers to receive Setup and OUT packets
+		table[index(0, RX, EVEN)].desc = BDT_DESC(EP0_SIZE, 0);
+		table[index(0, RX, EVEN)].addr = ep0_rx0_buf;
+		table[index(0, RX, ODD)].desc = BDT_DESC(EP0_SIZE, 0);
+		table[index(0, RX, ODD)].addr = ep0_rx1_buf;
+		table[index(0, TX, EVEN)].desc = 0;
+		table[index(0, TX, ODD)].desc = 0;
+		
+		// activate endpoint 0
+		USB0_ENDPT0 = USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK;
+
+		// clear all ending interrupts
+		USB0_ERRSTAT = 0xFF;
+		USB0_ISTAT = 0xFF;
+
+		// set the address to zero during enumeration
+		USB0_ADDR = 0;
+
+		// enable other interrupts
+		USB0_ERREN = 0xFF;
+		USB0_INTEN = USB_INTEN_TOKDNEEN |
+			USB_INTEN_SOFTOKEN |
+			USB_INTEN_STALLEN |
+			USB_INTEN_ERROREN |
+			USB_INTEN_USBRSTEN |
+			USB_INTEN_SLEEPEN;
+
+		// is this necessary?
+		USB0_CTL = USB_CTL_USBENSOFEN;
+		return;
+	}
+
+
+	if ((status & USB_ISTAT_STALL /* 80 */ )) {
+		//serial_print("stall:\n");
+		USB0_ENDPT0 = USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK;
+		USB0_ISTAT = USB_ISTAT_STALL;
+	}
+	if ((status & USB_ISTAT_ERROR /* 02 */ )) {
+		uint8_t err = USB0_ERRSTAT;
+		USB0_ERRSTAT = err;
+		//serial_print("err:");
+		//serial_phex(err);
+		//serial_print("\n");
+		USB0_ISTAT = USB_ISTAT_ERROR;
+	}
+
+	if ((status & USB_ISTAT_SLEEP /* 10 */ )) {
+		//serial_print("sleep\n");
+		USB0_ISTAT = USB_ISTAT_SLEEP;
+	}
+
+}
+
+
+
+void usb_init(void)
+{
+	int i;
+
+	//serial_begin(BAUD2DIV(115200));
+	//serial_print("usb_init\n");
+
+	usb_init_serialnumber();
+
+	for (i=0; i <= NUM_ENDPOINTS*4; i++) {
+		table[i].desc = 0;
+		table[i].addr = 0;
+	}
+
+	// this basically follows the flowchart in the Kinetis
+	// Quick Reference User Guide, Rev. 1, 03/2012, page 141
+
+	// assume 48 MHz clock already running
+	// SIM - enable clock
+	SIM_SCGC4 |= SIM_SCGC4_USBOTG;
+
+	// reset USB module
+	USB0_USBTRC0 = USB_USBTRC_USBRESET;
+	while ((USB0_USBTRC0 & USB_USBTRC_USBRESET) != 0) ; // wait for reset to end
+
+	// set desc table base addr
+	USB0_BDTPAGE1 = ((uint32_t)table) >> 8;
+	USB0_BDTPAGE2 = ((uint32_t)table) >> 16;
+	USB0_BDTPAGE3 = ((uint32_t)table) >> 24;
+
+	// clear all ISR flags
+	USB0_ISTAT = 0xFF;
+	USB0_ERRSTAT = 0xFF;
+	USB0_OTGISTAT = 0xFF;
+
+	USB0_USBTRC0 |= 0x40; // undocumented bit
+
+	// enable USB
+	USB0_CTL = USB_CTL_USBENSOFEN;
+	USB0_USBCTRL = 0;
+
+	// enable reset interrupt
+	USB0_INTEN = USB_INTEN_USBRSTEN;
+
+	// enable interrupt in NVIC...
+	NVIC_ENABLE_IRQ(IRQ_USBOTG);
+
+	// enable d+ pullup
+	USB0_CONTROL = USB_CONTROL_DPPULLUPNONOTG;
+}
+
+
+
diff --git a/teensy3/usb_dev.h b/teensy3/usb_dev.h
new file mode 100644
index 0000000000000000000000000000000000000000..eca9775524c9e84d1a821f01d8f463f5a44ffa05
--- /dev/null
+++ b/teensy3/usb_dev.h
@@ -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 _usb_dev_h_
+#define _usb_dev_h_
+
+// This header is NOT meant to be included when compiling
+// user sketches in Arduino.  The low-level functions
+// provided by usb_dev.c are meant to be called only by
+// code which provides higher-level interfaces to the user.
+
+#include "usb_mem.h"
+#include "usb_desc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void usb_init(void);
+void usb_init_serialnumber(void);
+void usb_isr(void);
+usb_packet_t *usb_rx(uint32_t endpoint);
+uint32_t usb_tx_byte_count(uint32_t endpoint);
+uint32_t usb_tx_packet_count(uint32_t endpoint);
+void usb_tx(uint32_t endpoint, usb_packet_t *packet);
+void usb_tx_isr(uint32_t endpoint, usb_packet_t *packet);
+
+extern volatile uint8_t usb_configuration;
+
+extern uint16_t usb_rx_byte_count_data[NUM_ENDPOINTS];
+static inline uint32_t usb_rx_byte_count(uint32_t endpoint) __attribute__((always_inline));
+static inline uint32_t usb_rx_byte_count(uint32_t endpoint)
+{
+        endpoint--;
+        if (endpoint >= NUM_ENDPOINTS) return 0;
+        return usb_rx_byte_count_data[endpoint];
+}
+
+#ifdef CDC_DATA_INTERFACE
+extern uint32_t usb_cdc_line_coding[2];
+extern volatile uint8_t usb_cdc_line_rtsdtr;
+extern volatile uint8_t usb_cdc_transmit_flush_timer;
+extern void usb_serial_flush_callback(void);
+#endif
+
+#ifdef SEREMU_INTERFACE
+extern volatile uint8_t usb_seremu_transmit_flush_timer;
+extern void usb_seremu_flush_callback(void);
+#endif
+
+#ifdef KEYBOARD_INTERFACE
+extern uint8_t keyboard_modifier_keys;
+extern uint8_t keyboard_keys[6];
+extern uint8_t keyboard_protocol;
+extern uint8_t keyboard_idle_config;
+extern uint8_t keyboard_idle_count;
+extern volatile uint8_t keyboard_leds;
+#endif
+
+#ifdef MIDI_INTERFACE
+extern void usb_midi_flush_output(void);
+#endif
+
+#ifdef FLIGHTSIM_INTERFACE
+extern void usb_flightsim_flush_callback(void);
+#endif
+
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif
diff --git a/teensy3/usb_flightsim.cpp b/teensy3/usb_flightsim.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b02fc9e496c6c1ab4ee371cafa612e17d4f1f34d
--- /dev/null
+++ b/teensy3/usb_flightsim.cpp
@@ -0,0 +1,367 @@
+/* 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 "usb_dev.h"
+#include "usb_flightsim.h"
+#include "core_pins.h" // for yield(), millis()
+#include <string.h>    // for memcpy()
+
+#ifdef FLIGHTSIM_INTERFACE // defined by usb_dev.h -> usb_desc.h
+
+FlightSimCommand * FlightSimCommand::first = NULL;
+FlightSimCommand * FlightSimCommand::last = NULL;
+FlightSimInteger * FlightSimInteger::first = NULL;
+FlightSimInteger * FlightSimInteger::last = NULL;
+FlightSimFloat * FlightSimFloat::first = NULL;
+FlightSimFloat * FlightSimFloat::last = NULL;
+
+uint8_t FlightSimClass::enabled = 0;
+uint8_t FlightSimClass::request_id_messages = 0;
+unsigned long FlightSimClass::frameCount = 0;
+elapsedMillis FlightSimClass::enableTimeout;
+
+static unsigned int unassigned_id = 1;  // TODO: move into FlightSimClass
+
+
+FlightSimCommand::FlightSimCommand()
+{
+	id = unassigned_id++;
+	if (!first) {
+		first = this;
+	} else {
+		last->next = this;
+	}
+	last = this;
+	name = NULL;
+	next = NULL;
+	FlightSimClass::request_id_messages = 1;
+}
+
+void FlightSimCommand::identify(void)
+{
+	uint8_t len, buf[6];
+
+	if (!FlightSim.enabled || !name) return;
+	len = strlen((const char *)name);
+	buf[0] = len + 6;
+	buf[1] = 1;
+	buf[2] = id;
+	buf[3] = id >> 8;
+	buf[4] = 0;
+	buf[5] = 0;
+	FlightSimClass::xmit(buf, 6, name, len);
+}
+
+void FlightSimCommand::sendcmd(uint8_t n)
+{
+	uint8_t buf[4];
+
+	if (!FlightSim.enabled || !name) return;
+	buf[0] = 4;
+	buf[1] = n;
+	buf[2] = id;
+	buf[3] = id >> 8;
+	FlightSimClass::xmit(buf, 4, NULL, 0);
+}
+
+
+FlightSimInteger::FlightSimInteger()
+{
+	id = unassigned_id++;
+	if (!first) {
+		first = this;
+	} else {
+		last->next = this;
+	}
+	last = this;
+	name = NULL;
+	next = NULL;
+	value = 0;
+	change_callback = NULL;
+	FlightSimClass::request_id_messages = 1;
+}
+
+void FlightSimInteger::identify(void)
+{
+	uint8_t len, buf[6];
+
+	if (!FlightSim.enabled || !name) return;
+	len = strlen((const char *)name);
+	buf[0] = len + 6;
+	buf[1] = 1;
+	buf[2] = id;
+	buf[3] = id >> 8;
+	buf[4] = 1;
+	buf[5] = 0;
+	FlightSimClass::xmit(buf, 6, name, len);
+}
+
+void FlightSimInteger::write(long val)
+{
+	uint8_t buf[6];
+
+	value = val;
+	if (!FlightSim.enabled || !name) return; // TODO: mark as dirty
+	buf[0] = 10;
+	buf[1] = 2;
+	buf[2] = id;
+	buf[3] = id >> 8;
+	buf[4] = 1;
+	buf[5] = 0;
+	FlightSimClass::xmit(buf, 6, (uint8_t *)&value, 4);
+}
+
+void FlightSimInteger::update(long val)
+{
+	value = val;
+	if (change_callback) (*change_callback)(val);
+}
+
+FlightSimInteger * FlightSimInteger::find(unsigned int n)
+{
+	for (FlightSimInteger *p = first; p; p = p->next) {
+		if (p->id == n) return p;
+	}
+	return NULL;
+}
+
+
+
+
+FlightSimFloat::FlightSimFloat()
+{
+	id = unassigned_id++;
+	if (!first) {
+		first = this;
+	} else {
+		last->next = this;
+	}
+	last = this;
+	name = NULL;
+	next = NULL;
+	value = 0;
+	change_callback = NULL;
+	FlightSimClass::request_id_messages = 1;
+}
+
+void FlightSimFloat::identify(void)
+{
+	uint8_t len, buf[6];
+
+	if (!FlightSim.enabled || !name) return;
+	len = strlen((const char *)name);
+	buf[0] = len + 6;
+	buf[1] = 1;
+	buf[2] = id;
+	buf[3] = id >> 8;
+	buf[4] = 2;
+	buf[5] = 0;
+	FlightSimClass::xmit(buf, 6, name, len);
+}
+
+void FlightSimFloat::write(float val)
+{
+	uint8_t buf[6];
+
+	value = val;
+	if (!FlightSim.enabled || !name) return; // TODO: mark as dirty
+	buf[0] = 10;
+	buf[1] = 2;
+	buf[2] = id;
+	buf[3] = id >> 8;
+	buf[4] = 2;
+	buf[5] = 0;
+	FlightSimClass::xmit(buf, 6, (uint8_t *)&value, 4);
+}
+
+void FlightSimFloat::update(float val)
+{
+	value = val;
+	if (change_callback) (*change_callback)(val);
+}
+
+FlightSimFloat * FlightSimFloat::find(unsigned int n)
+{
+	for (FlightSimFloat *p = first; p; p = p->next) {
+		if (p->id == n) return p;
+	}
+	return NULL;
+}
+
+
+
+
+
+
+FlightSimClass::FlightSimClass()
+{
+}
+
+void FlightSimClass::update(void)
+{
+	uint8_t len, maxlen, type, *p, *end;
+	usb_packet_t *rx_packet;
+	uint16_t id;
+
+	while (1) {
+		if (!usb_configuration) break;
+		rx_packet = usb_rx(FLIGHTSIM_RX_ENDPOINT);
+		if (!rx_packet) break;
+		p = rx_packet->buf;
+		end = p + 64;
+		maxlen = 64;
+		do {
+			len = p[0];
+			if (len < 2 || len > maxlen) break;
+			switch (p[1]) {
+			  case 0x02: // write data
+				if (len < 10) break;
+				id = p[2] | (p[3] << 8);
+				type = p[4];
+				if (type == 1) {
+					FlightSimInteger *item = FlightSimInteger::find(id);
+					if (!item) break;
+					item->update(*(long *)(p + 6));
+				} else if (type == 2) {
+					FlightSimFloat *item = FlightSimFloat::find(id);
+					if (!item) break;
+					item->update(*(float *)(p + 6));
+				}
+				break;
+			  case 0x03: // enable/disable
+				if (len < 4) break;
+				switch (p[2]) {
+				  case 1:
+					request_id_messages = 1;
+				  case 2:
+					enable();
+					frameCount++;
+					break;
+				  case 3:
+					disable();
+				}
+			}
+			p += len;
+			maxlen -= len;
+		} while (p < end);
+		usb_free(rx_packet);
+	}
+	if (enabled && request_id_messages) {
+		request_id_messages = 0;
+		for (FlightSimCommand *p = FlightSimCommand::first; p; p = p->next) {
+			p->identify();
+		}
+		for (FlightSimInteger *p = FlightSimInteger::first; p; p = p->next) {
+			p->identify();
+			// TODO: send any dirty data
+		}
+		for (FlightSimFloat *p = FlightSimFloat::first; p; p = p->next) {
+			p->identify();
+			// TODO: send any dirty data
+		}
+	}
+}
+
+
+bool FlightSimClass::isEnabled(void)
+{
+        if (!usb_configuration) return false;
+        if (!enabled) return false;
+	if (enableTimeout > 1500) return false;
+        return true;
+}
+
+
+// Maximum number of transmit packets to queue so we don't starve other endpoints for memory
+#define TX_PACKET_LIMIT 8
+
+static usb_packet_t *tx_packet=NULL;
+static volatile uint8_t tx_noautoflush=0;
+
+void FlightSimClass::xmit(const void *p1, uint8_t n1, const void *p2, uint8_t n2)
+{
+	uint8_t total;
+
+	total = n1 + n2;
+	if (total > FLIGHTSIM_TX_SIZE) return;
+	if (!enabled || !usb_configuration) return;
+	tx_noautoflush = 1;
+	if (tx_packet) {
+		if (total <= FLIGHTSIM_TX_SIZE - tx_packet->index) goto send;
+		for (int i = tx_packet->index; i < FLIGHTSIM_TX_SIZE; i++) {
+			tx_packet->buf[i] = 0;
+		}
+		tx_packet->len = FLIGHTSIM_TX_SIZE;
+		usb_tx(FLIGHTSIM_TX_ENDPOINT, tx_packet);
+		tx_packet = NULL;
+	}
+	while (1) {
+		if (usb_tx_packet_count(FLIGHTSIM_TX_ENDPOINT) < TX_PACKET_LIMIT) {
+			tx_packet = usb_malloc();
+			if (tx_packet) break;
+		}
+		if (!enabled || !usb_configuration) {
+			tx_noautoflush = 0;
+			return;
+		}
+		tx_noautoflush = 0;
+		yield();
+		tx_noautoflush = 1;
+	}
+send:
+	memcpy(tx_packet->buf + tx_packet->index, p1, n1);
+	tx_packet->index += n1;
+	if (n2 > 0) {
+		memcpy(tx_packet->buf + tx_packet->index, p2, n2);
+		tx_packet->index += n2;
+	}
+	if (tx_packet->index >= FLIGHTSIM_TX_SIZE) {
+		tx_packet->len = FLIGHTSIM_TX_SIZE;
+		usb_tx(FLIGHTSIM_TX_ENDPOINT, tx_packet);
+		tx_packet = NULL;
+	}
+	tx_noautoflush = 0;
+}
+
+
+extern "C" {
+void usb_flightsim_flush_callback(void)
+{
+	if (tx_noautoflush || !tx_packet || tx_packet->index == 0) return;
+	for (int i=tx_packet->index; i < FLIGHTSIM_TX_ENDPOINT; i++) {
+		tx_packet->buf[i] = 0;
+	}
+	tx_packet->len = FLIGHTSIM_TX_SIZE;
+	usb_tx(FLIGHTSIM_TX_ENDPOINT, tx_packet);
+	tx_packet = NULL;
+}
+}
+
+#endif // FLIGHTSIM_INTERFACE
diff --git a/teensy3/usb_flightsim.h b/teensy3/usb_flightsim.h
new file mode 100644
index 0000000000000000000000000000000000000000..8ac115f26170cf0f76ef6ccc6ad637c4745c776f
--- /dev/null
+++ b/teensy3/usb_flightsim.h
@@ -0,0 +1,185 @@
+/* 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 USBflightsim_h_
+#define USBflightsim_h_
+
+#if defined(USB_FLIGHTSIM) && defined(__cplusplus)
+
+#include <inttypes.h>
+#include "elapsedMillis.h"
+
+class FlightSimClass;
+class FlightSimCommand;
+class FlightSimInteger;
+
+class _XpRefStr_;
+#define XPlaneRef(str) ((const _XpRefStr_ *)(str))
+
+class FlightSimClass
+{
+public:
+	FlightSimClass();
+	static void update(void);
+	static bool isEnabled(void);
+	static unsigned long getFrameCount(void) { return frameCount; }
+private:
+	static uint8_t request_id_messages;
+	static uint8_t enabled;
+	static elapsedMillis enableTimeout;
+	static unsigned long frameCount;
+	static void enable(void) { enabled = 1; enableTimeout = 0; }
+	static void disable(void) { enabled = 0; }
+	static void xmit(const void *p1, uint8_t n1, const void *p2, uint8_t n2);
+	friend class FlightSimCommand;
+	friend class FlightSimInteger;
+	friend class FlightSimFloat;
+};
+
+
+class FlightSimCommand
+{
+public:
+	FlightSimCommand();
+	void assign(const _XpRefStr_ *s) { name = s; if (FlightSimClass::enabled) identify(); }
+	FlightSimCommand & operator = (const _XpRefStr_ *s) { assign(s); return *this; }
+	void begin(void) { sendcmd(4); }
+	void end(void) { sendcmd(5); }
+	FlightSimCommand & operator = (int n) { sendcmd((n) ? 4 : 5); return *this; }
+	void once(void) { sendcmd(6); }
+	void identify(void);
+private:
+	unsigned int id;
+	const _XpRefStr_ *name;
+	void sendcmd(uint8_t n);
+	FlightSimCommand *next;
+	static FlightSimCommand *first;
+	static FlightSimCommand *last;
+	friend class FlightSimClass;
+};
+
+
+class FlightSimInteger
+{
+public:
+	FlightSimInteger();
+	void assign(const _XpRefStr_ *s) { name = s; if (FlightSimClass::enabled) identify(); }
+	FlightSimInteger & operator = (const _XpRefStr_ *s) { assign(s); return *this; }
+	void write(long val);
+	FlightSimInteger & operator = (char n) { write((long)n); return *this; }
+	FlightSimInteger & operator = (int n) { write((long)n); return *this; }
+	FlightSimInteger & operator = (long n) { write(n); return *this; }
+	FlightSimInteger & operator = (unsigned char n) { write((long)n); return *this; }
+	FlightSimInteger & operator = (unsigned int n) { write((long)n); return *this; }
+	FlightSimInteger & operator = (unsigned long n) { write((long)n); return *this; }
+	FlightSimInteger & operator = (float n) { write((long)n); return *this; }
+	FlightSimInteger & operator = (double n) { write((long)n); return *this; }
+	long read(void) const { return value; }
+	operator long () const { return value; }
+	void identify(void);
+	void update(long val);
+	static FlightSimInteger * find(unsigned int n);
+	void onChange(void (*fptr)(long)) { change_callback = fptr; }
+	// TODO: math operators....  + - * / % ++ --
+private:
+	unsigned int id;
+	const _XpRefStr_ *name;
+	long value;
+	void (*change_callback)(long);
+	FlightSimInteger *next;
+	static FlightSimInteger *first;
+	static FlightSimInteger *last;
+	friend class FlightSimClass;
+};
+
+
+class FlightSimFloat
+{
+public:
+	FlightSimFloat();
+	void assign(const _XpRefStr_ *s) { name = s; if (FlightSimClass::enabled) identify(); }
+	FlightSimFloat & operator = (const _XpRefStr_ *s) { assign(s); return *this; }
+	void write(float val);
+	FlightSimFloat & operator = (char n) { write((float)n); return *this; }
+	FlightSimFloat & operator = (int n) { write((float)n); return *this; }
+	FlightSimFloat & operator = (long n) { write((float)n); return *this; }
+	FlightSimFloat & operator = (unsigned char n) { write((float)n); return *this; }
+	FlightSimFloat & operator = (unsigned int n) { write((float)n); return *this; }
+	FlightSimFloat & operator = (unsigned long n) { write((float)n); return *this; }
+	FlightSimFloat & operator = (float n) { write(n); return *this; }
+	FlightSimFloat & operator = (double n) { write((float)n); return *this; }
+	float read(void) const { return value; }
+	operator float () const { return value; }
+	void identify(void);
+	void update(float val);
+	static FlightSimFloat * find(unsigned int n);
+	void onChange(void (*fptr)(float)) { change_callback = fptr; }
+	// TODO: math operators....  + - * / % ++ --
+private:
+	unsigned int id;
+	const _XpRefStr_ *name;
+	float value;
+	void (*change_callback)(float);
+	FlightSimFloat *next;
+	static FlightSimFloat *first;
+	static FlightSimFloat *last;
+	friend class FlightSimClass;
+};
+
+
+class FlightSimElapsedFrames
+{
+private:
+	unsigned long count;
+public:
+	FlightSimElapsedFrames(void) { count = FlightSimClass::getFrameCount(); }
+	FlightSimElapsedFrames(unsigned long val) { count = FlightSimClass::getFrameCount() - val; }
+	FlightSimElapsedFrames(const FlightSimElapsedFrames &orig) { count = orig.count; }
+	operator unsigned long () const { return FlightSimClass::getFrameCount() - count; }
+	FlightSimElapsedFrames & operator = (const FlightSimElapsedFrames &rhs) { count = rhs.count; return *this; }
+	FlightSimElapsedFrames & operator = (unsigned long val) { count = FlightSimClass::getFrameCount() - val; return *this; }
+	FlightSimElapsedFrames & operator -= (unsigned long val)    { count += val; return *this; }
+	FlightSimElapsedFrames & operator += (unsigned long val)    { count -= val; return *this; }
+	FlightSimElapsedFrames operator - (int val) const           { FlightSimElapsedFrames r(*this); r.count += val; return r; }
+	FlightSimElapsedFrames operator - (unsigned int val) const  { FlightSimElapsedFrames r(*this); r.count += val; return r; }
+	FlightSimElapsedFrames operator - (long val) const          { FlightSimElapsedFrames r(*this); r.count += val; return r; }
+	FlightSimElapsedFrames operator - (unsigned long val) const { FlightSimElapsedFrames r(*this); r.count += val; return r; }
+	FlightSimElapsedFrames operator + (int val) const           { FlightSimElapsedFrames r(*this); r.count -= val; return r; }
+	FlightSimElapsedFrames operator + (unsigned int val) const  { FlightSimElapsedFrames r(*this); r.count -= val; return r; }
+	FlightSimElapsedFrames operator + (long val) const          { FlightSimElapsedFrames r(*this); r.count -= val; return r; }
+	FlightSimElapsedFrames operator + (unsigned long val) const { FlightSimElapsedFrames r(*this); r.count -= val; return r; }
+};
+
+
+extern FlightSimClass FlightSim;
+
+
+#endif
+#endif
diff --git a/teensy3/usb_inst.cpp b/teensy3/usb_inst.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dc340eea0f337c13a303e20873e26d58c4c6238d
--- /dev/null
+++ b/teensy3/usb_inst.cpp
@@ -0,0 +1,67 @@
+/* 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 "WProgram.h"
+
+#ifdef USB_SERIAL
+usb_serial_class Serial;
+#endif
+
+#ifdef USB_HID
+usb_keyboard_class Keyboard;
+usb_mouse_class Mouse;
+usb_joystick_class Joystick;
+uint8_t usb_joystick_class::manual_mode = 0;
+usb_seremu_class Serial;
+#endif
+
+#ifdef USB_SERIAL_HID
+usb_serial_class Serial;
+usb_keyboard_class Keyboard;
+usb_mouse_class Mouse;
+usb_joystick_class Joystick;
+uint8_t usb_joystick_class::manual_mode = 0;
+#endif
+
+#ifdef USB_MIDI
+usb_midi_class usbMIDI;
+usb_seremu_class Serial;
+#endif
+
+#ifdef USB_RAWHID
+usb_rawhid_class RawHID;
+usb_seremu_class Serial;
+#endif
+
+#ifdef USB_FLIGHTSIM
+FlightSimClass FlightSim;
+usb_seremu_class Serial;
+#endif
+
diff --git a/teensy3/usb_joystick.c b/teensy3/usb_joystick.c
new file mode 100644
index 0000000000000000000000000000000000000000..78818b20280d15c1cc5b4d904eedacc7bd8ef5e8
--- /dev/null
+++ b/teensy3/usb_joystick.c
@@ -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 "usb_dev.h"
+#include "usb_joystick.h"
+#include "core_pins.h" // for yield()
+#include "HardwareSerial.h"
+#include <string.h> // for memcpy()
+
+#ifdef JOYSTICK_INTERFACE // defined by usb_dev.h -> usb_desc.h
+
+
+uint32_t usb_joystick_data[3];
+
+
+// Maximum number of transmit packets to queue so we don't starve other endpoints for memory
+#define TX_PACKET_LIMIT 3
+
+static uint8_t transmit_previous_timeout=0;
+
+// When the PC isn't listening, how long do we wait before discarding data?
+#define TX_TIMEOUT_MSEC 30
+
+#if F_CPU == 96000000
+  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596)
+#elif F_CPU == 48000000
+  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428)
+#elif F_CPU == 24000000
+  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262)
+#endif
+
+
+
+
+int usb_joystick_send(void)
+{
+        uint32_t wait_count=0;
+        usb_packet_t *tx_packet;
+
+	//serial_print("send");
+	//serial_print("\n");
+        while (1) {
+                if (!usb_configuration) {
+			//serial_print("error1\n");
+                        return -1;
+                }
+                if (usb_tx_packet_count(JOYSTICK_ENDPOINT) < TX_PACKET_LIMIT) {
+                        tx_packet = usb_malloc();
+                        if (tx_packet) break;
+                }
+                if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) {
+                        transmit_previous_timeout = 1;
+			//serial_print("error2\n");
+                        return -1;
+                }
+                yield();
+        }
+	transmit_previous_timeout = 0;
+	memcpy(tx_packet->buf, usb_joystick_data, 12);
+        tx_packet->len = 12;
+        usb_tx(JOYSTICK_ENDPOINT, tx_packet);
+	//serial_print("ok\n");
+        return 0;
+}
+
+
+
+
+#endif // JOYSTICK_INTERFACE
diff --git a/teensy3/usb_joystick.h b/teensy3/usb_joystick.h
new file mode 100644
index 0000000000000000000000000000000000000000..12bb0d3f6e3a56e89796912965859137167649ca
--- /dev/null
+++ b/teensy3/usb_joystick.h
@@ -0,0 +1,134 @@
+/* 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 USBjoystick_h_
+#define USBjoystick_h_
+
+#if defined(USB_HID) || defined(USB_SERIAL_HID)
+
+#include <inttypes.h>
+
+// C language implementation
+#ifdef __cplusplus
+extern "C" {
+#endif
+int usb_joystick_send(void);
+extern uint32_t usb_joystick_data[3];
+#ifdef __cplusplus
+}
+#endif
+
+// C++ interface
+#ifdef __cplusplus
+class usb_joystick_class
+{
+        public:
+        void begin(void) { }
+        void end(void) { }
+	void button(uint8_t button, bool val) {
+		if (--button >= 32) return;
+		if (val) usb_joystick_data[0] |= (1 << button);
+		else usb_joystick_data[0] &= ~(1 << button);
+		if (!manual_mode) usb_joystick_send();
+	}
+	void X(unsigned int val) {
+		if (val > 1023) val = 1023;
+		usb_joystick_data[1] = (usb_joystick_data[1] & 0xFFFFC00F) | (val << 4);
+		if (!manual_mode) usb_joystick_send();
+	}
+	void Y(unsigned int val) {
+		if (val > 1023) val = 1023;
+		usb_joystick_data[1] = (usb_joystick_data[1] & 0xFF003FFF) | (val << 14);
+		if (!manual_mode) usb_joystick_send();
+	}
+	void position(unsigned int x, unsigned int y) {
+		if (x > 1023) x = 1023;
+		if (y > 1023) y = 1023;
+		usb_joystick_data[1] = (usb_joystick_data[1] & 0xFFF00000)
+			| (x << 4) | (y << 14);
+		if (!manual_mode) usb_joystick_send();
+	}
+	void Z(unsigned int val) {
+		if (val > 1023) val = 1023;
+		usb_joystick_data[1] = (usb_joystick_data[1] & 0x00FFFFFF) | (val << 24);
+		usb_joystick_data[2] = (usb_joystick_data[2] & 0xFFFFFFFC) | (val >> 8);
+		if (!manual_mode) usb_joystick_send();
+	}
+	void Zrotate(unsigned int val) {
+		if (val > 1023) val = 1023;
+		usb_joystick_data[2] = (usb_joystick_data[2] & 0xFFFFF003) | (val << 2);
+		if (!manual_mode) usb_joystick_send();
+	}
+	void sliderLeft(unsigned int val) {
+		if (val > 1023) val = 1023;
+		usb_joystick_data[2] = (usb_joystick_data[2] & 0xFFC00FFF) | (val << 12);
+		if (!manual_mode) usb_joystick_send();
+	}
+	void sliderRight(unsigned int val) {
+		if (val > 1023) val = 1023;
+		usb_joystick_data[2] = (usb_joystick_data[2] & 0x003FFFFF) | (val << 22);
+		if (!manual_mode) usb_joystick_send();
+	}
+	void slider(unsigned int val) {
+		if (val > 1023) val = 1023;
+		usb_joystick_data[2] = (usb_joystick_data[2] & 0x00000FFF)
+			| (val << 12) | (val << 22);
+		if (!manual_mode) usb_joystick_send();
+	}
+        inline void hat(int dir) {
+                uint32_t val;
+                if (dir < 0) val = 15;
+                else if (dir < 23) val = 0;
+                else if (dir < 68) val = 1;
+                else if (dir < 113) val = 2;
+                else if (dir < 158) val = 3;
+                else if (dir < 203) val = 4;
+                else if (dir < 245) val = 5;
+                else if (dir < 293) val = 6;
+                else if (dir < 338) val = 7;
+		usb_joystick_data[1] = (usb_joystick_data[1] & 0xFFFFFFF0) | val;
+                if (!manual_mode) usb_joystick_send();
+        }
+	void useManualSend(bool mode) {
+		manual_mode = mode;
+	}
+	void send_now(void) {
+		usb_joystick_send();
+	}
+	private:
+	static uint8_t manual_mode;
+};
+extern usb_joystick_class Joystick;
+
+#endif // __cplusplus
+
+#endif // USB_HID || USB_SERIAL_HID
+#endif // USBjoystick_h_
+
diff --git a/teensy3/usb_keyboard.c b/teensy3/usb_keyboard.c
new file mode 100644
index 0000000000000000000000000000000000000000..90913c121e0c0c3bc348ea407d78a82d79affe71
--- /dev/null
+++ b/teensy3/usb_keyboard.c
@@ -0,0 +1,480 @@
+/* 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 "usb_dev.h"
+#include "usb_keyboard.h"
+#include "core_pins.h" // for yield()
+#include "keylayouts.h"
+//#include "HardwareSerial.h"
+#include <string.h> // for memcpy()
+
+#ifdef KEYBOARD_INTERFACE // defined by usb_dev.h -> usb_desc.h
+
+
+// which modifier keys are currently pressed
+// 1=left ctrl,	   2=left shift,   4=left alt,	  8=left gui
+// 16=right ctrl, 32=right shift, 64=right alt, 128=right gui
+uint8_t keyboard_modifier_keys=0;
+
+// which keys are currently pressed, up to 6 keys may be down at once
+uint8_t keyboard_keys[6]={0,0,0,0,0,0};
+
+// protocol setting from the host.  We use exactly the same report
+// either way, so this variable only stores the setting since we
+// are required to be able to report which setting is in use.
+uint8_t keyboard_protocol=1;
+
+// the idle configuration, how often we send the report to the
+// host (ms * 4) even when it hasn't changed
+uint8_t keyboard_idle_config=125;
+
+// count until idle timeout
+uint8_t keyboard_idle_count=0;
+
+// 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana
+volatile uint8_t keyboard_leds=0;
+
+
+
+static KEYCODE_TYPE unicode_to_keycode(uint16_t cpoint);
+static void write_key(KEYCODE_TYPE keycode);
+static uint8_t keycode_to_modifier(KEYCODE_TYPE keycode);
+static uint8_t keycode_to_key(KEYCODE_TYPE keycode);
+static void usb_keyboard_press_key(uint8_t key, uint8_t modifier);
+static void usb_keyboard_release_key(uint8_t key, uint8_t modifier);
+#ifdef DEADKEYS_MASK
+static KEYCODE_TYPE deadkey_to_keycode(KEYCODE_TYPE keycode);
+#endif
+
+
+
+// Step #1, decode UTF8 to Unicode code points
+//
+void usb_keyboard_write(uint8_t c)
+{
+	static int utf8_state=0;
+	static uint16_t unicode_wchar=0;
+
+	if (c < 0x80) {
+		// single byte encoded, 0x00 to 0x7F
+		utf8_state = 0;
+		usb_keyboard_write_unicode(c);
+	} else if (c < 0xC0) {
+		// 2nd, 3rd or 4th byte, 0x80 to 0xBF
+		c &= 0x3F;
+		if (utf8_state == 1) {
+			utf8_state = 0;
+			usb_keyboard_write_unicode(unicode_wchar | c);
+		} else if (utf8_state == 2) {
+			unicode_wchar |= ((uint16_t)c << 6);
+			utf8_state = 1;
+		}
+	} else if (c < 0xE0) {
+		// begin 2 byte sequence, 0xC2 to 0xDF
+		// or illegal 2 byte sequence, 0xC0 to 0xC1
+		unicode_wchar = (uint16_t)(c & 0x1F) << 6;
+		utf8_state = 1;
+	} else if (c < 0xF0) {
+		// begin 3 byte sequence, 0xE0 to 0xEF
+		unicode_wchar = (uint16_t)(c & 0x0F) << 12;
+		utf8_state = 2;
+	} else {
+		// begin 4 byte sequence (not supported), 0xF0 to 0xF4
+		// or illegal, 0xF5 to 0xFF
+		utf8_state = 255;
+	}
+}
+
+
+// Step #2: translate Unicode code point to keystroke sequence
+//
+static KEYCODE_TYPE unicode_to_keycode(uint16_t cpoint)
+{
+	// Unicode code points beyond U+FFFF are not supported
+	// technically this input should probably be called UCS-2
+	if (cpoint < 32) {
+		if (cpoint == 10) return KEY_ENTER & 0x3FFF;
+		if (cpoint == 11) return KEY_TAB & 0x3FFF;
+		return 0;
+	}
+	if (cpoint < 128) {
+		return keycodes_ascii[cpoint - 0x20];
+	}
+	#ifdef ISO_8859_1_A0
+	if (cpoint >= 0xA0 && cpoint < 0x100) {
+		return keycodes_iso_8859_1[cpoint - 0xA0];
+	}
+	#endif
+	//#ifdef UNICODE_20AC
+	//if (cpoint == 0x20AC) return UNICODE_20AC & 0x3FFF;
+	//#endif
+	#ifdef KEYCODE_EXTRA00
+	if (cpoint == UNICODE_EXTRA00) return KEYCODE_EXTRA00 & 0x3FFF;
+	#endif
+	#ifdef KEYCODE_EXTRA01
+	if (cpoint == UNICODE_EXTRA01) return KEYCODE_EXTRA01 & 0x3FFF;
+	#endif
+	#ifdef KEYCODE_EXTRA02
+	if (cpoint == UNICODE_EXTRA02) return KEYCODE_EXTRA02 & 0x3FFF;
+	#endif
+	#ifdef KEYCODE_EXTRA03
+	if (cpoint == UNICODE_EXTRA03) return KEYCODE_EXTRA03 & 0x3FFF;
+	#endif
+	#ifdef KEYCODE_EXTRA04
+	if (cpoint == UNICODE_EXTRA04) return KEYCODE_EXTRA04 & 0x3FFF;
+	#endif
+	#ifdef KEYCODE_EXTRA05
+	if (cpoint == UNICODE_EXTRA05) return KEYCODE_EXTRA05 & 0x3FFF;
+	#endif
+	#ifdef KEYCODE_EXTRA06
+	if (cpoint == UNICODE_EXTRA06) return KEYCODE_EXTRA06 & 0x3FFF;
+	#endif
+	#ifdef KEYCODE_EXTRA07
+	if (cpoint == UNICODE_EXTRA07) return KEYCODE_EXTRA07 & 0x3FFF;
+	#endif
+	#ifdef KEYCODE_EXTRA08
+	if (cpoint == UNICODE_EXTRA08) return KEYCODE_EXTRA08 & 0x3FFF;
+	#endif
+	#ifdef KEYCODE_EXTRA09
+	if (cpoint == UNICODE_EXTRA09) return KEYCODE_EXTRA09 & 0x3FFF;
+	#endif
+	return 0;
+}
+
+// Step #3: execute keystroke sequence
+//
+#ifdef DEADKEYS_MASK
+static KEYCODE_TYPE deadkey_to_keycode(KEYCODE_TYPE keycode)
+{
+	keycode &= DEADKEYS_MASK;
+	if (keycode == 0) return 0;
+	#ifdef ACUTE_ACCENT_BITS
+	if (keycode == ACUTE_ACCENT_BITS) return DEADKEY_ACUTE_ACCENT;
+	#endif
+	#ifdef CEDILLA_BITS
+	if (keycode == CEDILLA_BITS) return DEADKEY_CEDILLA;
+	#endif
+	#ifdef CIRCUMFLEX_BITS
+	if (keycode == CIRCUMFLEX_BITS) return DEADKEY_CIRCUMFLEX;
+	#endif
+	#ifdef DIAERESIS_BITS
+	if (keycode == DIAERESIS_BITS) return DEADKEY_DIAERESIS;
+	#endif
+	#ifdef GRAVE_ACCENT_BITS
+	if (keycode == GRAVE_ACCENT_BITS) return DEADKEY_GRAVE_ACCENT;
+	#endif
+	#ifdef TILDE_BITS
+	if (keycode == TILDE_BITS) return DEADKEY_TILDE;
+	#endif
+	#ifdef RING_ABOVE_BITS
+	if (keycode == RING_ABOVE_BITS) return DEADKEY_RING_ABOVE;
+	#endif
+	return 0;
+}
+#endif
+
+void usb_keyboard_write_unicode(uint16_t cpoint)
+{
+	KEYCODE_TYPE keycode;
+	#ifdef DEADKEYS_MASK
+	KEYCODE_TYPE deadkeycode;
+	#endif
+
+	keycode = unicode_to_keycode(cpoint);
+	if (keycode) {
+		#ifdef DEADKEYS_MASK
+		KEYCODE_TYPE deadkeycode = deadkey_to_keycode(keycode);
+		if (deadkeycode) write_key(deadkeycode);
+		#endif
+		write_key(keycode);
+	}
+}
+
+
+// Step #4: do each keystroke
+//
+static void write_key(KEYCODE_TYPE keycode)
+{
+/*
+	uint8_t key, modifier=0;
+
+	#ifdef SHIFT_MASK
+	if (keycode & SHIFT_MASK) modifier |= MODIFIERKEY_SHIFT;
+	#endif
+	#ifdef ALTGR_MASK
+	if (keycode & ALTGR_MASK) modifier |= MODIFIERKEY_RIGHT_ALT;
+	#endif
+	#ifdef RCTRL_MASK
+	if (keycode & RCTRL_MASK) modifier |= MODIFIERKEY_RIGHT_CTRL;
+	#endif
+	key = keycode & 0x3F;
+	#ifdef KEY_NON_US_100
+	if (key == KEY_NON_US_100) key = 100;
+	#endif
+	usb_keyboard_press(key, modifier);
+*/
+	usb_keyboard_press(keycode_to_key(keycode), keycode_to_modifier(keycode));
+}
+
+static uint8_t keycode_to_modifier(KEYCODE_TYPE keycode)
+{
+	uint8_t modifier=0;
+
+	#ifdef SHIFT_MASK
+	if (keycode & SHIFT_MASK) modifier |= MODIFIERKEY_SHIFT;
+	#endif
+	#ifdef ALTGR_MASK
+	if (keycode & ALTGR_MASK) modifier |= MODIFIERKEY_RIGHT_ALT;
+	#endif
+	#ifdef RCTRL_MASK
+	if (keycode & RCTRL_MASK) modifier |= MODIFIERKEY_RIGHT_CTRL;
+	#endif
+	return modifier;
+}
+
+static uint8_t keycode_to_key(KEYCODE_TYPE keycode)
+{
+	uint8_t key = keycode & 0x3F;
+	#ifdef KEY_NON_US_100
+	if (key == KEY_NON_US_100) key = 100;
+	#endif
+	return key;
+}
+
+
+
+void usb_keyboard_press_keycode(uint16_t n)
+{
+	uint8_t key, mod, msb, modrestore=0;
+	KEYCODE_TYPE keycode;
+	#ifdef DEADKEYS_MASK
+	KEYCODE_TYPE deadkeycode;
+	#endif
+
+	msb = n >> 8;
+	if (msb >= 0xC2 && msb <= 0xDF) {
+		n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6);
+	} else
+	if (msb == 0x80) {
+		usb_keyboard_press_key(0, n);
+		return;
+	} else
+	if (msb == 0x40) {
+		usb_keyboard_press_key(n, 0);
+		return;
+	}
+	keycode = unicode_to_keycode(n);
+	if (!keycode) return;
+	#ifdef DEADKEYS_MASK
+	deadkeycode = deadkey_to_keycode(keycode);
+	if (deadkeycode) {
+		modrestore = keyboard_modifier_keys;
+		if (modrestore) {
+			keyboard_modifier_keys = 0;
+			send_now();
+		}
+		// TODO: test if operating systems recognize
+		// deadkey sequences when other keys are held
+		mod = keycode_to_modifier(deadkeycode);
+		key = keycode_to_key(deadkeycode);
+		usb_keyboard_press_key(key, mod);
+		usb_keyboard_release_key(key, mod);
+	}
+	#endif
+	mod = keycode_to_modifier(keycode);
+	key = keycode_to_key(keycode);
+	usb_keyboard_press_key(key, mod | modrestore);
+}
+
+
+void usb_keyboard_release_keycode(uint16_t n)
+{
+	uint8_t key, mod, msb;
+
+	msb = n >> 8;
+	if (msb >= 0xC2 && msb <= 0xDF) {
+		n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6);
+	} else
+	if (msb == 0x80) {
+		usb_keyboard_release_key(0, n);
+		return;
+	} else
+	if (msb == 0x40) {
+		usb_keyboard_release_key(n, 0);
+		return;
+	}
+	KEYCODE_TYPE keycode = unicode_to_keycode(n);
+	if (!keycode) return;
+	mod = keycode_to_modifier(keycode);
+	key = keycode_to_key(keycode);
+	usb_keyboard_release_key(key, mod);
+}
+
+
+static void usb_keyboard_press_key(uint8_t key, uint8_t modifier)
+{
+	int i, send_required = 0;
+
+	if (modifier) {
+		if ((keyboard_modifier_keys & modifier) != modifier) {
+			keyboard_modifier_keys |= modifier;
+			send_required = 1;
+		}
+	}
+	if (key) {
+		for (i=0; i < 6; i++) {
+			if (keyboard_keys[i] == key) goto end;
+		}
+		for (i=0; i < 6; i++) {
+			if (keyboard_keys[i] == 0) {
+				keyboard_keys[i] = key;
+				send_required = 1;
+				goto end;
+			}
+		}
+	}
+	end:
+	if (send_required) usb_keyboard_send();
+}
+
+
+static void usb_keyboard_release_key(uint8_t key, uint8_t modifier)
+{
+	int i, send_required = 0;
+
+	if (modifier) {
+		if ((keyboard_modifier_keys & modifier) != 0) {
+			keyboard_modifier_keys &= ~modifier;
+			send_required = 1;
+		}
+	}
+	if (key) {
+		for (i=0; i < 6; i++) {
+			if (keyboard_keys[i] == key) {
+				keyboard_keys[i] = 0;
+				send_required = 1;
+			}
+		}
+	}
+	if (send_required) usb_keyboard_send();
+}
+
+void usb_keyboard_release_all(void)
+{
+	uint8_t i, anybits;
+
+	anybits = keyboard_modifier_keys;
+	keyboard_modifier_keys = 0;
+	for (i=0; i < 6; i++) {
+		anybits |= keyboard_keys[i];
+		keyboard_keys[i] = 0;
+	}
+	if (anybits) usb_keyboard_send();
+}
+
+
+int usb_keyboard_press(uint8_t key, uint8_t modifier)
+{
+	int r;
+	keyboard_modifier_keys = modifier;
+	keyboard_keys[0] = key;
+	keyboard_keys[1] = 0;
+	keyboard_keys[2] = 0;
+	keyboard_keys[3] = 0;
+	keyboard_keys[4] = 0;
+	keyboard_keys[5] = 0;
+	r = usb_keyboard_send();
+	if (r) return r;
+	keyboard_modifier_keys = 0;
+	keyboard_keys[0] = 0;
+	return usb_keyboard_send();
+}
+
+
+// Maximum number of transmit packets to queue so we don't starve other endpoints for memory
+#define TX_PACKET_LIMIT 4
+
+static uint8_t transmit_previous_timeout=0;
+
+// When the PC isn't listening, how long do we wait before discarding data?
+#define TX_TIMEOUT_MSEC 50
+
+#if F_CPU == 96000000
+  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596)
+#elif F_CPU == 48000000
+  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428)
+#elif F_CPU == 24000000
+  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262)
+#endif
+
+
+// send the contents of keyboard_keys and keyboard_modifier_keys
+int usb_keyboard_send(void)
+{
+#if 0
+	serial_print("Send:");
+	serial_phex(keyboard_modifier_keys);
+	serial_phex(keyboard_keys[0]);
+	serial_phex(keyboard_keys[1]);
+	serial_phex(keyboard_keys[2]);
+	serial_phex(keyboard_keys[3]);
+	serial_phex(keyboard_keys[4]);
+	serial_phex(keyboard_keys[5]);
+	serial_print("\n");
+#endif
+#if 1
+	uint32_t wait_count=0;
+	usb_packet_t *tx_packet;
+
+	while (1) {
+		if (!usb_configuration) {
+			return -1;
+		}
+		if (usb_tx_packet_count(KEYBOARD_ENDPOINT) < TX_PACKET_LIMIT) {
+			tx_packet = usb_malloc();
+			if (tx_packet) break;
+		}
+		if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) {
+			transmit_previous_timeout = 1;
+			return -1;
+		}
+		yield();
+	}
+	*(tx_packet->buf) = keyboard_modifier_keys;
+	*(tx_packet->buf + 1) = 0;
+	memcpy(tx_packet->buf + 2, keyboard_keys, 6);
+	tx_packet->len = 8;
+	usb_tx(KEYBOARD_ENDPOINT, tx_packet);
+#endif
+	return 0;
+}
+
+
+#endif // KEYBOARD_INTERFACE
diff --git a/teensy3/usb_keyboard.h b/teensy3/usb_keyboard.h
new file mode 100644
index 0000000000000000000000000000000000000000..b8d28c7df814e4def7b758fe094fed79a1c4b988
--- /dev/null
+++ b/teensy3/usb_keyboard.h
@@ -0,0 +1,97 @@
+/* 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 USBkeyboard_h_
+#define USBkeyboard_h_
+
+#include "keylayouts.h"
+
+#if defined(USB_HID) || defined(USB_SERIAL_HID)
+
+#include <inttypes.h>
+
+// C language implementation
+#ifdef __cplusplus
+extern "C" {
+#endif
+void usb_keyboard_write(uint8_t c);
+void usb_keyboard_write_unicode(uint16_t cpoint);
+void usb_keyboard_press_keycode(uint16_t n);
+void usb_keyboard_release_keycode(uint16_t n);
+void usb_keyboard_release_all(void);
+int usb_keyboard_press(uint8_t key, uint8_t modifier);
+int usb_keyboard_send(void);
+extern uint8_t keyboard_modifier_keys;
+extern uint8_t keyboard_keys[6];
+extern uint8_t keyboard_protocol;
+extern uint8_t keyboard_idle_config;
+extern uint8_t keyboard_idle_count;
+extern volatile uint8_t keyboard_leds;
+#ifdef __cplusplus
+}
+#endif
+
+
+
+// C++ interface
+#ifdef __cplusplus
+#include "Stream.h"
+class usb_keyboard_class : public Print
+{
+public:
+	void begin(void) { }
+	void end(void) { }
+	virtual size_t write(uint8_t c) { usb_keyboard_write(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); }
+	using Print::write;
+	void write_unicode(uint16_t n) { usb_keyboard_write_unicode(n); }
+	void set_modifier(uint8_t c) { keyboard_modifier_keys = c; }
+	void set_key1(uint8_t c) { keyboard_keys[0] = c; }
+	void set_key2(uint8_t c) { keyboard_keys[1] = c; }
+	void set_key3(uint8_t c) { keyboard_keys[2] = c; }
+	void set_key4(uint8_t c) { keyboard_keys[3] = c; }
+	void set_key5(uint8_t c) { keyboard_keys[4] = c; }
+	void set_key6(uint8_t c) { keyboard_keys[5] = c; }
+	void set_media(uint8_t c) { }
+	void send_now(void) { usb_keyboard_send(); }
+	void press(uint16_t n) { usb_keyboard_press_keycode(n); }
+	void release(uint16_t n) { usb_keyboard_release_keycode(n); }
+	void releaseAll(void);
+};
+
+extern usb_keyboard_class Keyboard;
+
+#endif // __cplusplus
+
+#endif // USB_HID || USB_SERIAL_HID
+#endif // USBkeyboard_h_
diff --git a/teensy3/usb_mem.c b/teensy3/usb_mem.c
new file mode 100644
index 0000000000000000000000000000000000000000..c6e902a80d96de843c941551be7c926294d9fac1
--- /dev/null
+++ b/teensy3/usb_mem.c
@@ -0,0 +1,106 @@
+/* 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 "HardwareSerial.h"
+#include "usb_dev.h"
+#include "usb_mem.h"
+
+__attribute__ ((section(".usbbuffers"), used))
+unsigned char usb_buffer_memory[NUM_USB_BUFFERS * sizeof(usb_packet_t)];
+
+static uint32_t usb_buffer_available = 0xFFFFFFFF;
+
+// use bitmask and CLZ instruction to implement fast free list
+// http://www.archivum.info/gnu.gcc.help/2006-08/00148/Re-GCC-Inline-Assembly.html
+// http://gcc.gnu.org/ml/gcc/2012-06/msg00015.html
+// __builtin_clz()
+
+usb_packet_t * usb_malloc(void)
+{
+	unsigned int n, avail;
+	uint8_t *p;
+
+	__disable_irq();
+	avail = usb_buffer_available;
+	n = __builtin_clz(avail); // clz = count leading zeros
+	if (n >= NUM_USB_BUFFERS) {
+		__enable_irq();
+		return NULL;
+	}
+	//serial_print("malloc:");
+	//serial_phex(n);
+	//serial_print("\n");
+
+	usb_buffer_available = avail & ~(0x80000000 >> n);
+	__enable_irq();
+	p = usb_buffer_memory + (n * sizeof(usb_packet_t));
+	//serial_print("malloc:");
+	//serial_phex32((int)p);
+	//serial_print("\n");
+	*(uint32_t *)p = 0;
+	*(uint32_t *)(p + 4) = 0;
+	return (usb_packet_t *)p;
+}
+
+// for the receive endpoints to request memory
+extern uint8_t usb_rx_memory_needed;
+extern void usb_rx_memory(usb_packet_t *packet);
+
+void usb_free(usb_packet_t *p)
+{
+	unsigned int n, mask;
+
+	//serial_print("free:");
+	n = ((uint8_t *)p - usb_buffer_memory) / sizeof(usb_packet_t);
+	if (n >= NUM_USB_BUFFERS) return;
+	//serial_phex(n);
+	//serial_print("\n");
+
+	// if any endpoints are starving for memory to receive
+	// packets, give this memory to them immediately!
+	if (usb_rx_memory_needed && usb_configuration) {
+		//serial_print("give to rx:");
+		//serial_phex32((int)p);
+		//serial_print("\n");
+		usb_rx_memory(p);
+		return;
+	}
+
+	mask = (0x80000000 >> n);
+	__disable_irq();
+	usb_buffer_available |= mask;
+	__enable_irq();
+
+	//serial_print("free:");
+	//serial_phex32((int)p);
+	//serial_print("\n");
+}
+
diff --git a/teensy3/usb_mem.h b/teensy3/usb_mem.h
new file mode 100644
index 0000000000000000000000000000000000000000..5e50bf84dbd68162d60df89a92e0604368fd0ce2
--- /dev/null
+++ b/teensy3/usb_mem.h
@@ -0,0 +1,55 @@
+/* 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 _usb_mem_h_
+#define _usb_mem_h_
+
+#include <stdint.h>
+
+typedef struct usb_packet_struct {
+	uint16_t len;
+	uint16_t index;
+	struct usb_packet_struct *next;
+	uint8_t buf[64];
+} usb_packet_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+usb_packet_t * usb_malloc(void);
+void usb_free(usb_packet_t *p);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/teensy3/usb_midi.c b/teensy3/usb_midi.c
new file mode 100644
index 0000000000000000000000000000000000000000..b14869778f689b7dc6ded7b278f7554548ec8bc4
--- /dev/null
+++ b/teensy3/usb_midi.c
@@ -0,0 +1,264 @@
+/* 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 "usb_dev.h"
+#include "usb_midi.h"
+#include "core_pins.h" // for yield()
+#include "HardwareSerial.h"
+
+#ifdef MIDI_INTERFACE // defined by usb_dev.h -> usb_desc.h
+
+
+uint8_t usb_midi_msg_channel;
+uint8_t usb_midi_msg_type;
+uint8_t usb_midi_msg_data1;
+uint8_t usb_midi_msg_data2;
+uint8_t usb_midi_msg_sysex[USB_MIDI_SYSEX_MAX];
+uint8_t usb_midi_msg_sysex_len;
+void (*usb_midi_handleNoteOff)(uint8_t ch, uint8_t note, uint8_t vel) = NULL;
+void (*usb_midi_handleNoteOn)(uint8_t ch, uint8_t note, uint8_t vel) = NULL;
+void (*usb_midi_handleVelocityChange)(uint8_t ch, uint8_t note, uint8_t vel) = NULL;
+void (*usb_midi_handleControlChange)(uint8_t ch, uint8_t control, uint8_t value) = NULL;
+void (*usb_midi_handleProgramChange)(uint8_t ch, uint8_t program) = NULL;
+void (*usb_midi_handleAfterTouch)(uint8_t ch, uint8_t pressure) = NULL;
+void (*usb_midi_handlePitchChange)(uint8_t ch, int pitch) = NULL;
+void (*usb_midi_handleRealTimeSystem)(uint8_t rtb) = NULL;
+
+// Maximum number of transmit packets to queue so we don't starve other endpoints for memory
+#define TX_PACKET_LIMIT 6
+static usb_packet_t *rx_packet=NULL;
+static usb_packet_t *tx_packet=NULL;
+static uint8_t transmit_previous_timeout=0;
+static uint8_t tx_noautoflush=0;
+
+
+// When the PC isn't listening, how long do we wait before discarding data?
+#define TX_TIMEOUT_MSEC 40
+
+#if F_CPU == 96000000
+  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596)
+#elif F_CPU == 48000000
+  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428)
+#elif F_CPU == 24000000
+  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262)
+#endif
+
+
+void usb_midi_write_packed(uint32_t n)
+{
+	uint32_t index, wait_count=0;
+
+	tx_noautoflush = 1;
+	if (!tx_packet) {
+        	while (1) {
+                	if (!usb_configuration) {
+				//serial_print("error1\n");
+                        	return;
+                	}
+                	if (usb_tx_packet_count(MIDI_TX_ENDPOINT) < TX_PACKET_LIMIT) {
+                        	tx_packet = usb_malloc();
+                        	if (tx_packet) break;
+                	}
+                	if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) {
+                        	transmit_previous_timeout = 1;
+				//serial_print("error2\n");
+                        	return;
+                	}
+                	yield();
+        	}
+	}
+	transmit_previous_timeout = 0;
+	index = tx_packet->index;
+	*((uint32_t *)(tx_packet->buf) + index++) = n;
+	if (index < MIDI_TX_SIZE/4) {
+		tx_packet->index = index;
+	} else {
+		tx_packet->len = MIDI_TX_SIZE;
+		usb_tx(MIDI_TX_ENDPOINT, tx_packet);
+		tx_packet = usb_malloc();
+	}
+	tx_noautoflush = 0;
+}
+
+void usb_midi_send_sysex(const uint8_t *data, uint32_t length)
+{
+        // TODO: MIDI 2.5 lib automatically adds start and stop bytes
+        while (length > 3) {
+                usb_midi_write_packed(0x04 | (data[0] << 8) | (data[1] << 16) | (data[2] << 24));
+                data += 3;
+                length -= 3;
+        }
+        if (length == 3) {
+                usb_midi_write_packed(0x07 | (data[0] << 8) | (data[1] << 16) | (data[2] << 24));
+        } else if (length == 2) {
+                usb_midi_write_packed(0x06 | (data[0] << 8) | (data[1] << 16));
+        } else if (length == 1) {
+                usb_midi_write_packed(0x05 | (data[0] << 8));
+        }
+}
+
+void usb_midi_flush_output(void)
+{
+	if (tx_noautoflush == 0 && tx_packet && tx_packet->index > 0) {
+		tx_packet->len = tx_packet->index * 4;
+		usb_tx(MIDI_TX_ENDPOINT, tx_packet);
+		tx_packet = usb_malloc();
+	}
+}
+
+void static sysex_byte(uint8_t b)
+{
+	if (usb_midi_msg_sysex_len < USB_MIDI_SYSEX_MAX) {
+		usb_midi_msg_sysex[usb_midi_msg_sysex_len++] = b;
+	}
+}
+
+
+int usb_midi_read(uint32_t channel)
+{
+	uint32_t n, index, ch, type1, type2;
+
+	if (!rx_packet) {
+		if (!usb_configuration) return 0;
+		rx_packet = usb_rx(MIDI_RX_ENDPOINT);
+		if (!rx_packet) return 0;
+		if (rx_packet->len == 0) {
+			usb_free(rx_packet);
+			rx_packet = NULL;
+			return 0;
+		}
+	}
+	index = rx_packet->index;
+	n = *(uint32_t *)(rx_packet->buf + index);
+	//serial_print("midi rx, n=");
+	//serial_phex32(n);
+	//serial_print("\n");
+	index += 4;
+	if (index < rx_packet->len) {
+		rx_packet->index = index;
+	} else {
+		usb_free(rx_packet);
+		rx_packet = usb_rx(MIDI_RX_ENDPOINT);
+	}
+	type1 = n & 15;
+	type2 = (n >> 12) & 15;
+	ch = ((n >> 8) & 15) + 1;
+	if (type1 >= 0x08 && type1 <= 0x0E) {
+		if (channel && channel != ch) {
+			// ignore other channels when user wants single channel read
+			return 0;
+		}
+		if (type1 == 0x08 && type2 == 0x08) {
+			usb_midi_msg_type = 0;			// 0 = Note off
+			if (usb_midi_handleNoteOff)
+				(*usb_midi_handleNoteOff)(ch, (n >> 16), (n >> 24));
+		} else
+		if (type1 == 0x09 && type2 == 0x09) {
+			if ((n >> 24) > 0) {
+				usb_midi_msg_type = 1;		// 1 = Note on
+				if (usb_midi_handleNoteOn)
+					(*usb_midi_handleNoteOn)(ch, (n >> 16), (n >> 24));
+			} else {
+				usb_midi_msg_type = 0;		// 0 = Note off
+				if (usb_midi_handleNoteOff)
+					(*usb_midi_handleNoteOff)(ch, (n >> 16), (n >> 24));
+			}
+		} else
+		if (type1 == 0x0A && type2 == 0x0A) {
+			usb_midi_msg_type = 2;			// 2 = Poly Pressure
+			if (usb_midi_handleVelocityChange)
+				(*usb_midi_handleVelocityChange)(ch, (n >> 16), (n >> 24));
+		} else
+		if (type1 == 0x0B && type2 == 0x0B) {
+			usb_midi_msg_type = 3;			// 3 = Control Change
+			if (usb_midi_handleControlChange)
+				(*usb_midi_handleControlChange)(ch, (n >> 16), (n >> 24));
+		} else
+		if (type1 == 0x0C && type2 == 0x0C) {
+			usb_midi_msg_type = 4;			// 4 = Program Change
+			if (usb_midi_handleProgramChange)
+				(*usb_midi_handleProgramChange)(ch, (n >> 16));
+		} else
+		if (type1 == 0x0D && type2 == 0x0D) {
+			usb_midi_msg_type = 5;			// 5 = After Touch
+			if (usb_midi_handleAfterTouch)
+				(*usb_midi_handleAfterTouch)(ch, (n >> 16));
+		} else
+		if (type1 == 0x0E && type2 == 0x0E) {
+			usb_midi_msg_type = 6;			// 6 = Pitch Bend
+			if (usb_midi_handlePitchChange)
+				(*usb_midi_handlePitchChange)(ch,
+				  ((n >> 16) & 0x7F) | ((n >> 17) & 0x3F80));
+		} else {
+			return 0;
+		}
+		return_message:
+		usb_midi_msg_channel = ch;
+		usb_midi_msg_data1 = (n >> 16);
+		usb_midi_msg_data2 = (n >> 24);
+		return 1;
+	}
+	if (type1 == 0x04) {
+		sysex_byte(n >> 8);
+		sysex_byte(n >> 16);
+		sysex_byte(n >> 24);
+		return 0;
+	}
+	if (type1 >= 0x05 && type1 <= 0x07) {
+		sysex_byte(n >> 8);
+		if (type1 >= 0x06) sysex_byte(n >> 16);
+		if (type1 == 0x07) sysex_byte(n >> 24);
+		usb_midi_msg_data1 = usb_midi_msg_sysex_len;
+		usb_midi_msg_sysex_len = 0;
+		usb_midi_msg_type = 7;				// 7 = Sys Ex
+		return 1;
+	}
+	if (type1 == 0x0F) {
+		// TODO: does this need to be a full MIDI parser?
+		// What software actually uses this message type in practice?
+		if (usb_midi_msg_sysex_len > 0) {
+			// From David Sorlien, dsorlien at gmail.com, http://axe4live.wordpress.com
+			// OSX sometimes uses Single Byte Unparsed to
+			// send bytes in the middle of a SYSEX message.
+			sysex_byte(n >> 8);
+		} else {
+			// From Sebastian Tomczak, seb.tomczak at gmail.com
+			// http://little-scale.blogspot.com/2011/08/usb-midi-game-boy-sync-for-16.html
+			usb_midi_msg_type = 8;
+			if (usb_midi_handleRealTimeSystem)
+				(*usb_midi_handleRealTimeSystem)(n >> 8);
+			goto return_message;
+		}
+	}
+	return 0;
+}
+
+
+#endif // MIDI_INTERFACE
diff --git a/teensy3/usb_midi.h b/teensy3/usb_midi.h
new file mode 100644
index 0000000000000000000000000000000000000000..d1b24f15d0923b634e995354f6c4958add46ef4a
--- /dev/null
+++ b/teensy3/usb_midi.h
@@ -0,0 +1,180 @@
+/* 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 USBmidi_h_
+#define USBmidi_h_
+
+#if defined(USB_MIDI)
+
+#include <inttypes.h>
+
+/*
+These were originally meant to allow programs written for
+Francois Best's MIDI library to be easily used with
+Teensy's usbMIDI which implements the same API.  However,
+the MIDI library definitions have changed, so these names
+now conflict.  They've never been documented (the PJRC web
+page documents usbMIDI.getType() in numbers) so they are
+now commented out so usbMIDI and the MIDI library can be
+used together without conflict.
+#define NoteOff 0
+#define NoteOn 1
+#define AfterTouchPoly 2
+#define ControlChange 3
+#define ProgramChange 4
+#define AfterTouchChannel 5
+#define PitchBend 6
+#define SystemExclusive 7
+*/
+
+#define USB_MIDI_SYSEX_MAX 60  // maximum sysex length we can receive
+
+// C language implementation
+#ifdef __cplusplus
+extern "C" {
+#endif
+void usb_midi_write_packed(uint32_t n);
+void usb_midi_send_sysex(const uint8_t *data, uint32_t length);
+void usb_midi_flush_output(void);
+int usb_midi_read(uint32_t channel);
+extern uint8_t usb_midi_msg_channel;
+extern uint8_t usb_midi_msg_type;
+extern uint8_t usb_midi_msg_data1;
+extern uint8_t usb_midi_msg_data2;
+extern uint8_t usb_midi_msg_sysex[USB_MIDI_SYSEX_MAX];
+extern uint8_t usb_midi_msg_sysex_len;
+extern void (*usb_midi_handleNoteOff)(uint8_t ch, uint8_t note, uint8_t vel);
+extern void (*usb_midi_handleNoteOn)(uint8_t ch, uint8_t note, uint8_t vel);
+extern void (*usb_midi_handleVelocityChange)(uint8_t ch, uint8_t note, uint8_t vel);
+extern void (*usb_midi_handleControlChange)(uint8_t ch, uint8_t control, uint8_t value);
+extern void (*usb_midi_handleProgramChange)(uint8_t ch, uint8_t program);
+extern void (*usb_midi_handleAfterTouch)(uint8_t ch, uint8_t pressure);
+extern void (*usb_midi_handlePitchChange)(uint8_t ch, int pitch);
+extern void (*usb_midi_handleRealTimeSystem)(uint8_t rtb);
+
+#ifdef __cplusplus
+}
+#endif
+
+// C++ interface
+#ifdef __cplusplus
+class usb_midi_class
+{
+        public:
+        void begin(void) { }
+        void end(void) { }
+        void sendNoteOff(uint32_t note, uint32_t velocity, uint32_t channel) __attribute__((always_inline)) {
+		usb_midi_write_packed(0x8008 | (((channel - 1) & 0x0F) << 8)
+		  | ((note & 0x7F) << 16) | ((velocity & 0x7F) << 24));
+	}
+        void sendNoteOn(uint32_t note, uint32_t velocity, uint32_t channel) __attribute__((always_inline)) {
+		usb_midi_write_packed(0x9009 | (((channel - 1) & 0x0F) << 8)
+		  | ((note & 0x7F) << 16) | ((velocity & 0x7F) << 24));
+	}
+        void sendPolyPressure(uint32_t note, uint32_t pressure, uint32_t channel) __attribute__((always_inline)) {
+		usb_midi_write_packed(0xA00A | (((channel - 1) & 0x0F) << 8)
+		  | ((note & 0x7F) << 16) | ((pressure & 0x7F) << 24));
+	}
+        void sendControlChange(uint32_t control, uint32_t value, uint32_t channel) __attribute__((always_inline)) {
+		usb_midi_write_packed(0xB00B | (((channel - 1) & 0x0F) << 8)
+		  | ((control & 0x7F) << 16) | ((value & 0x7F) << 24));
+	}
+        void sendProgramChange(uint32_t program, uint32_t channel) __attribute__((always_inline)) {
+		usb_midi_write_packed(0xC00C | (((channel - 1) & 0x0F) << 8)
+		  | ((program & 0x7F) << 16));
+	}
+        void sendAfterTouch(uint32_t pressure, uint32_t channel) __attribute__((always_inline)) {
+		usb_midi_write_packed(0xD00D | (((channel - 1) & 0x0F) << 8)
+		  | ((pressure & 0x7F) << 16));
+	}
+        void sendPitchBend(uint32_t value, uint32_t channel) __attribute__((always_inline)) {
+		usb_midi_write_packed(0xE00E | (((channel - 1) & 0x0F) << 8)
+		  | ((value & 0x7F) << 16) | ((value & 0x3F80) << 17));
+	}
+        void sendSysEx(uint32_t length, const uint8_t *data) {
+		usb_midi_send_sysex(data, length);
+	}
+        void send_now(void) {
+		usb_midi_flush_output();
+	}
+        uint8_t analog2velocity(uint16_t val, uint8_t range);
+        bool read(uint8_t channel=0) {
+		return usb_midi_read(channel);
+	}
+        inline uint8_t getType(void) {
+                return usb_midi_msg_type;
+        };
+        inline uint8_t getChannel(void) {
+                return usb_midi_msg_channel;
+        };
+        inline uint8_t getData1(void) {
+                return usb_midi_msg_data1;
+        };
+        inline uint8_t getData2(void) {
+                return usb_midi_msg_data2;
+        };
+        inline uint8_t * getSysExArray(void) {
+                return usb_midi_msg_sysex;
+        };
+        inline void setHandleNoteOff(void (*fptr)(uint8_t channel, uint8_t note, uint8_t velocity)) {
+                usb_midi_handleNoteOff = fptr;
+        };
+        inline void setHandleNoteOn(void (*fptr)(uint8_t channel, uint8_t note, uint8_t velocity)) {
+                usb_midi_handleNoteOn = fptr;
+        };
+        inline void setHandleVelocityChange(void (*fptr)(uint8_t channel, uint8_t note, uint8_t velocity)) {
+                usb_midi_handleVelocityChange = fptr;
+        };
+        inline void setHandleControlChange(void (*fptr)(uint8_t channel, uint8_t control, uint8_t value)) {
+                usb_midi_handleControlChange = fptr;
+        };
+        inline void setHandleProgramChange(void (*fptr)(uint8_t channel, uint8_t program)) {
+                usb_midi_handleProgramChange = fptr;
+        };
+        inline void setHandleAfterTouch(void (*fptr)(uint8_t channel, uint8_t pressure)) {
+                usb_midi_handleAfterTouch = fptr;
+        };
+        inline void setHandlePitchChange(void (*fptr)(uint8_t channel, int pitch)) {
+                usb_midi_handlePitchChange = fptr;
+        };
+        inline void setHandleRealTimeSystem(void (*fptr)(uint8_t realtimebyte)) {
+                usb_midi_handleRealTimeSystem = fptr;
+        };
+	private:
+};
+
+extern usb_midi_class usbMIDI;
+
+
+#endif // __cplusplus
+
+#endif // USB_MIDI
+#endif // USBmidi_h_
+
diff --git a/teensy3/usb_mouse.c b/teensy3/usb_mouse.c
new file mode 100644
index 0000000000000000000000000000000000000000..ee1b944660e7e0103e57b67f50ddf897597b8d6d
--- /dev/null
+++ b/teensy3/usb_mouse.c
@@ -0,0 +1,117 @@
+/* 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 "usb_dev.h"
+#include "usb_mouse.h"
+#include "core_pins.h" // for yield()
+#include "HardwareSerial.h"
+#include <string.h> // for memcpy()
+
+#ifdef MOUSE_INTERFACE // defined by usb_dev.h -> usb_desc.h
+
+// which buttons are currently pressed
+uint8_t usb_mouse_buttons_state=0;
+
+// protocol setting from the host.  We use exactly the same report
+// either way, so this variable only stores the setting since we
+// are required to be able to report which setting is in use.
+uint8_t usb_mouse_protocol=1;
+
+
+// Set the mouse buttons.  To create a "click", 2 calls are needed,
+// one to push the button down and the second to release it
+int usb_mouse_buttons(uint8_t left, uint8_t middle, uint8_t right)
+{
+        uint8_t mask=0;
+
+        if (left) mask |= 1;
+        if (middle) mask |= 4;
+        if (right) mask |= 2;
+        usb_mouse_buttons_state = mask;
+        return usb_mouse_move(0, 0, 0);
+}
+
+
+// Maximum number of transmit packets to queue so we don't starve other endpoints for memory
+#define TX_PACKET_LIMIT 3
+
+static uint8_t transmit_previous_timeout=0;
+
+// When the PC isn't listening, how long do we wait before discarding data?
+#define TX_TIMEOUT_MSEC 30
+
+#if F_CPU == 96000000
+  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596)
+#elif F_CPU == 48000000
+  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428)
+#elif F_CPU == 24000000
+  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262)
+#endif
+
+
+// Move the mouse.  x, y and wheel are -127 to 127.  Use 0 for no movement.
+int usb_mouse_move(int8_t x, int8_t y, int8_t wheel)
+{
+        uint32_t wait_count=0;
+        usb_packet_t *tx_packet;
+
+	//serial_print("move");
+	//serial_print("\n");
+        if (x == -128) x = -127;
+        if (y == -128) y = -127;
+        if (wheel == -128) wheel = -127;
+
+        while (1) {
+                if (!usb_configuration) {
+                        return -1;
+                }
+                if (usb_tx_packet_count(MOUSE_ENDPOINT) < TX_PACKET_LIMIT) {
+                        tx_packet = usb_malloc();
+                        if (tx_packet) break;
+                }
+                if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) {
+                        transmit_previous_timeout = 1;
+                        return -1;
+                }
+                yield();
+        }
+	transmit_previous_timeout = 0;
+	*(tx_packet->buf) = usb_mouse_buttons_state;
+	*(tx_packet->buf + 1) = x;
+	*(tx_packet->buf + 2) = y;
+	*(tx_packet->buf + 3) = wheel;
+	tx_packet->len = 4;
+	usb_tx(MOUSE_ENDPOINT, tx_packet);
+        return 0;
+}
+
+
+
+#endif // MOUSE_INTERFACE
diff --git a/teensy3/usb_mouse.h b/teensy3/usb_mouse.h
new file mode 100644
index 0000000000000000000000000000000000000000..0c913522d6126eed6867f446df8bfdf227f23db9
--- /dev/null
+++ b/teensy3/usb_mouse.h
@@ -0,0 +1,98 @@
+/* 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 USBmouse_h_
+#define USBmouse_h_
+
+#if defined(USB_HID) || defined(USB_SERIAL_HID)
+
+#include <inttypes.h>
+
+// C language implementation
+#ifdef __cplusplus
+extern "C" {
+#endif
+int usb_mouse_buttons(uint8_t left, uint8_t middle, uint8_t right);
+int usb_mouse_move(int8_t x, int8_t y, int8_t wheel);
+extern uint8_t usb_mouse_buttons_state;
+extern uint8_t usb_mouse_protocol;
+#ifdef __cplusplus
+}
+#endif
+
+
+#define MOUSE_LEFT 1
+#define MOUSE_MIDDLE 4
+#define MOUSE_RIGHT 2
+#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)
+
+// C++ interface
+#ifdef __cplusplus
+class usb_mouse_class
+{
+        public:
+        void begin(void) { }
+        void end(void) { }
+        void move(int8_t x, int8_t y, int8_t wheel=0) { usb_mouse_move(x, y, wheel); }
+        void click(uint8_t b = MOUSE_LEFT) {
+		usb_mouse_buttons_state = b;
+		usb_mouse_move(0, 0, 0);
+		usb_mouse_buttons_state = 0;
+		usb_mouse_move(0, 0, 0);
+	}
+        void scroll(int8_t wheel) { usb_mouse_move(0, 0, wheel); }
+        void set_buttons(uint8_t left, uint8_t middle=0, uint8_t right=0) {
+		usb_mouse_buttons(left, middle, right);
+	}
+        void press(uint8_t b = MOUSE_LEFT) {
+		uint8_t buttons = usb_mouse_buttons_state | (b & MOUSE_ALL);
+		if (buttons != usb_mouse_buttons_state) {
+			usb_mouse_buttons_state = buttons;
+			usb_mouse_move(0, 0, 0);
+		}
+	}
+        void release(uint8_t b = MOUSE_LEFT) {
+		uint8_t buttons = usb_mouse_buttons_state & ~(b & MOUSE_ALL);
+		if (buttons != usb_mouse_buttons_state) {
+			usb_mouse_buttons_state = buttons;
+			usb_mouse_move(0, 0, 0);
+		}
+	}
+        bool isPressed(uint8_t b = MOUSE_ALL) {
+		return ((usb_mouse_buttons_state & (b & MOUSE_ALL)) != 0);
+	}
+};
+extern usb_mouse_class Mouse;
+
+#endif // __cplusplus
+
+#endif // USB_HID || USB_SERIAL_HID
+#endif // USBmouse_h_
+
diff --git a/teensy3/usb_names.h b/teensy3/usb_names.h
new file mode 100644
index 0000000000000000000000000000000000000000..0df3215133acc94e5ea76b63d3d5b6070505785c
--- /dev/null
+++ b/teensy3/usb_names.h
@@ -0,0 +1,57 @@
+/* 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 _usb_names_h_
+#define _usb_names_h_
+
+// These definitions are intended to allow users to override the default
+// USB manufacturer, product and serial number strings.
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct usb_string_descriptor_struct {
+	uint8_t bLength;
+	uint8_t bDescriptorType;
+	uint16_t wString[];
+};
+
+extern struct usb_string_descriptor_struct usb_string_manufacturer_name;
+extern struct usb_string_descriptor_struct usb_string_product_name;
+extern struct usb_string_descriptor_struct usb_string_serial_number;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/teensy3/usb_rawhid.c b/teensy3/usb_rawhid.c
new file mode 100644
index 0000000000000000000000000000000000000000..03210bb0a0e8f2131ce1826341ef45ec05a34dab
--- /dev/null
+++ b/teensy3/usb_rawhid.c
@@ -0,0 +1,88 @@
+/* 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 "usb_dev.h"
+#include "usb_rawhid.h"
+#include "core_pins.h" // for yield(), millis()
+#include <string.h>    // for memcpy()
+//#include "HardwareSerial.h"
+
+#ifdef RAWHID_INTERFACE // defined by usb_dev.h -> usb_desc.h
+
+int usb_rawhid_recv(void *buffer, uint32_t timeout)
+{
+	usb_packet_t *rx_packet;
+	uint32_t begin = millis();
+
+	while (1) {
+		if (!usb_configuration) return -1;
+		rx_packet = usb_rx(RAWHID_RX_ENDPOINT);
+		if (rx_packet) break;
+		if (millis() - begin > timeout || !timeout) return 0;
+		yield();
+	}
+	memcpy(buffer, rx_packet->buf, RAWHID_RX_SIZE);
+	usb_free(rx_packet);
+	return RAWHID_RX_SIZE;
+}
+
+int usb_rawhid_available(void)
+{
+	uint32_t count;
+
+	if (!usb_configuration) return 0;
+	count = usb_rx_byte_count(RAWHID_RX_ENDPOINT);
+	return count;
+}
+
+// Maximum number of transmit packets to queue so we don't starve other endpoints for memory
+#define TX_PACKET_LIMIT 4
+
+int usb_rawhid_send(const void *buffer, uint32_t timeout)
+{
+	usb_packet_t *tx_packet;
+	uint32_t begin = millis();
+
+	while (1) {
+		if (!usb_configuration) return -1;
+		if (usb_tx_packet_count(RAWHID_TX_ENDPOINT) < TX_PACKET_LIMIT) {
+			tx_packet = usb_malloc();
+			if (tx_packet) break;
+		}
+		if (millis() - begin > timeout) return 0;
+		yield();
+	}
+	memcpy(tx_packet->buf, buffer, RAWHID_TX_SIZE);
+	tx_packet->len = RAWHID_TX_SIZE;
+	usb_tx(RAWHID_TX_ENDPOINT, tx_packet);
+	return RAWHID_TX_SIZE;
+}
+
+#endif // RAWHID_INTERFACE
diff --git a/teensy3/usb_rawhid.h b/teensy3/usb_rawhid.h
new file mode 100644
index 0000000000000000000000000000000000000000..d5fd5d8a13be67b3103cdd57f8b3052813a67531
--- /dev/null
+++ b/teensy3/usb_rawhid.h
@@ -0,0 +1,65 @@
+/* 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 USBrawhid_h_
+#define USBrawhid_h_
+
+#if defined(USB_RAWHID)
+
+#include <inttypes.h>
+
+// C language implementation
+#ifdef __cplusplus
+extern "C" {
+#endif
+int usb_rawhid_recv(void *buffer, uint32_t timeout);
+int usb_rawhid_available(void);
+int usb_rawhid_send(const void *buffer, uint32_t timeout);
+#ifdef __cplusplus
+}
+#endif
+
+
+// C++ interface
+#ifdef __cplusplus
+class usb_rawhid_class
+{
+public:
+	int available(void) {return usb_rawhid_available(); }
+	int recv(void *buffer, uint16_t timeout) { return usb_rawhid_recv(buffer, timeout); }
+	int send(const void *buffer, uint16_t timeout) { return usb_rawhid_send(buffer, timeout); }
+};
+
+extern usb_rawhid_class RawHID;
+
+#endif // __cplusplus
+
+#endif // USB_HID
+#endif // USBrawhid_h_
diff --git a/teensy3/usb_seremu.c b/teensy3/usb_seremu.c
new file mode 100644
index 0000000000000000000000000000000000000000..e4781e883e36715bd2af6305dac8d77eb4083501
--- /dev/null
+++ b/teensy3/usb_seremu.c
@@ -0,0 +1,249 @@
+/* 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 "usb_dev.h"
+#include "usb_seremu.h"
+#include "core_pins.h" // for yield()
+//#include "HardwareSerial.h"
+
+#ifdef SEREMU_INTERFACE // defined by usb_dev.h -> usb_desc.h
+
+volatile uint8_t usb_seremu_transmit_flush_timer=0;
+
+static usb_packet_t *rx_packet=NULL;
+static usb_packet_t *tx_packet=NULL;
+static volatile uint8_t tx_noautoflush=0;
+
+#define TRANSMIT_FLUSH_TIMEOUT	5   /* in milliseconds */
+
+
+// get the next character, or -1 if nothing received
+int usb_seremu_getchar(void)
+{
+	unsigned int i;
+	int c;
+
+	while (1) {
+		if (!usb_configuration) return -1;
+		if (!rx_packet) rx_packet = usb_rx(SEREMU_RX_ENDPOINT);
+		if (!rx_packet) return -1;
+		i = rx_packet->index;
+		c = rx_packet->buf[i++];
+		if (c) {
+			if (i >= rx_packet->len) {
+				usb_free(rx_packet);
+				rx_packet = NULL;
+			} else {
+				rx_packet->index = i;
+			}
+			return c;
+		}
+		usb_free(rx_packet);
+		rx_packet = NULL;
+	}
+}
+
+// peek at the next character, or -1 if nothing received
+int usb_seremu_peekchar(void)
+{
+	int c;
+
+	while (1) {
+		if (!usb_configuration) return -1;
+		if (!rx_packet) rx_packet = usb_rx(SEREMU_RX_ENDPOINT);
+		if (!rx_packet) return -1;
+		c = rx_packet->buf[rx_packet->index];
+		if (c) return c;
+		usb_free(rx_packet);
+		rx_packet = NULL;
+	}
+}
+
+// number of bytes available in the receive buffer
+int usb_seremu_available(void)
+{
+	int i, len, count;
+
+	if (!rx_packet) {
+		if (usb_configuration) rx_packet = usb_rx(SEREMU_RX_ENDPOINT);
+		if (!rx_packet) return 0;
+	}
+	len = rx_packet->len;
+	i = rx_packet->index;
+	count = 0;
+	for (i = rx_packet->index; i < len; i++) {
+		if (rx_packet->buf[i] == 0) break;
+		count++;
+	}
+	if (count == 0) {
+		usb_free(rx_packet);
+		rx_packet = NULL;
+	}
+	return count;
+}
+
+
+// discard any buffered input
+void usb_seremu_flush_input(void)
+{
+	usb_packet_t *rx;
+
+	if (!usb_configuration) return;
+	if (rx_packet) {
+		usb_free(rx_packet);
+		rx_packet = NULL;
+	}
+	while (1) {
+		rx = usb_rx(SEREMU_RX_ENDPOINT);
+		if (!rx) break;
+		usb_free(rx);
+	}
+}
+
+
+
+// Maximum number of transmit packets to queue so we don't starve other endpoints for memory
+#define TX_PACKET_LIMIT 6
+
+// When the PC isn't listening, how long do we wait before discarding data?  If this is
+// too short, we risk losing data during the stalls that are common with ordinary desktop
+// software.  If it's too long, we stall the user's program when no software is running.
+#define TX_TIMEOUT_MSEC 30
+
+#if F_CPU == 96000000
+  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596)
+#elif F_CPU == 48000000
+  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428)
+#elif F_CPU == 24000000
+  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262)
+#endif
+
+// When we've suffered the transmit timeout, don't wait again until the computer
+// begins accepting data.  If no software is running to receive, we'll just discard
+// data as rapidly as Serial.print() can generate it, until there's something to
+// actually receive it.
+static uint8_t transmit_previous_timeout=0;
+
+
+// transmit a character.  0 returned on success, -1 on error
+int usb_seremu_putchar(uint8_t c)
+{
+	return usb_seremu_write(&c, 1);
+}
+
+
+int usb_seremu_write(const void *buffer, uint32_t size)
+{
+#if 1
+	uint32_t len;
+	uint32_t wait_count;
+	const uint8_t *src = (const uint8_t *)buffer;
+	uint8_t *dest;
+
+	tx_noautoflush = 1;
+	while (size > 0) {
+		if (!tx_packet) {
+			wait_count = 0;
+			while (1) {
+				if (!usb_configuration) {
+					tx_noautoflush = 0;
+					return -1;
+				}
+				if (usb_tx_packet_count(SEREMU_TX_ENDPOINT) < TX_PACKET_LIMIT) {
+					tx_noautoflush = 1;
+					tx_packet = usb_malloc();
+					if (tx_packet) break;
+				}
+				if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) {
+					transmit_previous_timeout = 1;
+					tx_noautoflush = 0;
+					return -1;
+				}
+				tx_noautoflush = 0;
+				yield();
+				tx_noautoflush = 1;
+			}
+		}
+		transmit_previous_timeout = 0;
+		len = SEREMU_TX_SIZE - tx_packet->index;
+		if (len > size) len = size;
+		dest = tx_packet->buf + tx_packet->index;
+		tx_packet->index += len;
+		size -= len;
+		while (len-- > 0) *dest++ = *src++;
+		if (tx_packet->index < SEREMU_TX_SIZE) {
+			usb_seremu_transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
+		} else {
+			tx_packet->len = SEREMU_TX_SIZE;
+			usb_seremu_transmit_flush_timer = 0;
+			usb_tx(SEREMU_TX_ENDPOINT, tx_packet);
+			tx_packet = NULL;
+		}
+	}
+	tx_noautoflush = 0;
+	return 0;
+#endif
+}
+
+void usb_seremu_flush_output(void)
+{
+	int i;
+
+	if (!usb_configuration) return;
+	//serial_print("usb_serial_flush_output\n");
+	if (tx_packet && tx_packet->index > 0) {
+		usb_seremu_transmit_flush_timer = 0;
+		for (i = tx_packet->index; i < SEREMU_TX_SIZE; i++) {
+			tx_packet->buf[i] = 0;
+		}
+		tx_packet->len = SEREMU_TX_SIZE;
+		usb_tx(SEREMU_TX_ENDPOINT, tx_packet);
+		tx_packet = NULL;
+	}
+	// while (usb_tx_byte_count(SEREMU_TX_ENDPOINT) > 0) ; // wait
+}
+
+void usb_seremu_flush_callback(void)
+{
+	int i;
+	//serial_print("C");
+	if (tx_noautoflush) return;
+	//serial_print("usb_flush_callback \n");
+	for (i = tx_packet->index; i < SEREMU_TX_SIZE; i++) {
+		tx_packet->buf[i] = 0;
+	}
+	tx_packet->len = SEREMU_TX_SIZE;
+	usb_tx(SEREMU_TX_ENDPOINT, tx_packet);
+	tx_packet = NULL;
+	//serial_print("usb_flush_callback end\n");
+}
+
+#endif // SEREMU_INTERFACE
diff --git a/teensy3/usb_seremu.h b/teensy3/usb_seremu.h
new file mode 100644
index 0000000000000000000000000000000000000000..f3679c5cf935b55465bbfde66e55139e987ce57f
--- /dev/null
+++ b/teensy3/usb_seremu.h
@@ -0,0 +1,91 @@
+/* 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 USBseremu_h_
+#define USBseremu_h_
+
+#if defined(USB_HID) || defined(USB_MIDI) || defined(USB_RAWHID) || defined(USB_FLIGHTSIM)
+
+#include <inttypes.h>
+
+// C language implementation
+#ifdef __cplusplus
+extern "C" {
+#endif
+int usb_seremu_getchar(void);
+int usb_seremu_peekchar(void);
+int usb_seremu_available(void);
+void usb_seremu_flush_input(void);
+int usb_seremu_putchar(uint8_t c);
+int usb_seremu_write(const void *buffer, uint32_t size);
+void usb_seremu_flush_output(void);
+void usb_seremu_flush_callback(void);
+extern volatile uint8_t usb_seremu_transmit_flush_timer;
+extern volatile uint8_t usb_configuration;
+#ifdef __cplusplus
+}
+#endif
+
+
+// C++ interface
+#ifdef __cplusplus
+#include "Stream.h"
+class usb_seremu_class : public Stream
+{
+public:
+        void begin(long) { /* TODO: call a function that tries to wait for enumeration */ };
+        void end() { /* TODO: flush output and shut down USB port */ };
+        virtual int available() { return usb_seremu_available(); }
+        virtual int read() { return usb_seremu_getchar(); }
+        virtual int peek() { return usb_seremu_peekchar(); }
+        virtual void flush() { usb_seremu_flush_output(); }
+        virtual size_t write(uint8_t c) { return usb_seremu_putchar(c); }
+        virtual size_t write(const uint8_t *buffer, size_t size) { return usb_seremu_write(buffer, size); }
+        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); }
+	using Print::write;
+        void send_now(void) { usb_seremu_flush_output(); };
+        uint32_t baud(void) { return 9600; }
+        uint8_t stopbits(void) { return 1; }
+        uint8_t paritytype(void) { return 0; }
+        uint8_t numbits(void) { return 8; }
+        uint8_t dtr(void) { return 1; }
+        uint8_t rts(void) { return 1; }
+        operator bool() { return usb_configuration; }
+};
+
+extern usb_seremu_class Serial;
+
+#endif // __cplusplus
+
+#endif // USB_HID
+#endif // USBseremu_h_
diff --git a/teensy3/usb_serial.c b/teensy3/usb_serial.c
new file mode 100644
index 0000000000000000000000000000000000000000..7b66d2b98db3a3edec0ec4755201f62b6e8c2236
--- /dev/null
+++ b/teensy3/usb_serial.c
@@ -0,0 +1,265 @@
+/* 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 "usb_dev.h"
+#include "usb_serial.h"
+#include "core_pins.h" // for yield()
+//#include "HardwareSerial.h"
+#include <string.h> // for memcpy()
+
+// defined by usb_dev.h -> usb_desc.h
+#if defined(CDC_STATUS_INTERFACE) && defined(CDC_DATA_INTERFACE)
+
+uint32_t usb_cdc_line_coding[2];
+volatile uint8_t usb_cdc_line_rtsdtr=0;
+volatile uint8_t usb_cdc_transmit_flush_timer=0;
+
+static usb_packet_t *rx_packet=NULL;
+static usb_packet_t *tx_packet=NULL;
+static volatile uint8_t tx_noautoflush=0;
+
+#define TRANSMIT_FLUSH_TIMEOUT	5   /* in milliseconds */
+
+// get the next character, or -1 if nothing received
+int usb_serial_getchar(void)
+{
+	unsigned int i;
+	int c;
+
+	if (!rx_packet) {
+		if (!usb_configuration) return -1;
+		rx_packet = usb_rx(CDC_RX_ENDPOINT);
+		if (!rx_packet) return -1;
+	}
+	i = rx_packet->index;
+	c = rx_packet->buf[i++];
+	if (i >= rx_packet->len) {
+		usb_free(rx_packet);
+		rx_packet = NULL;
+	} else {
+		rx_packet->index = i;
+	}
+	return c;
+}
+
+// peek at the next character, or -1 if nothing received
+int usb_serial_peekchar(void)
+{
+	if (!rx_packet) {
+		if (!usb_configuration) return -1;
+		rx_packet = usb_rx(CDC_RX_ENDPOINT);
+		if (!rx_packet) return -1;
+	}
+	if (!rx_packet) return -1;
+	return rx_packet->buf[rx_packet->index];
+}
+
+// number of bytes available in the receive buffer
+int usb_serial_available(void)
+{
+	int count;
+	count = usb_rx_byte_count(CDC_RX_ENDPOINT);
+	if (rx_packet) count += rx_packet->len - rx_packet->index;
+	return count;
+}
+
+// read a block of bytes to a buffer
+int usb_serial_read(void *buffer, uint32_t size)
+{
+	uint8_t *p = (uint8_t *)buffer;
+	uint32_t qty, count=0;
+
+	while (size) {
+		if (!usb_configuration) break;
+		if (!rx_packet) {
+			rx:
+			rx_packet = usb_rx(CDC_RX_ENDPOINT);
+			if (!rx_packet) break;
+			if (rx_packet->len == 0) {
+				usb_free(rx_packet);
+				goto rx;
+			}
+		}
+		qty = rx_packet->len - rx_packet->index;
+		if (qty > size) qty = size;
+		memcpy(p, rx_packet->buf + rx_packet->index, qty);
+		p += qty;
+		count += qty;
+		size -= qty;
+		rx_packet->index += qty;
+		if (rx_packet->index >= rx_packet->len) {
+			usb_free(rx_packet);
+			rx_packet = NULL;
+		}
+	}
+	return count;
+}
+
+// discard any buffered input
+void usb_serial_flush_input(void)
+{
+	usb_packet_t *rx;
+
+	if (!usb_configuration) return;
+	if (rx_packet) {
+		usb_free(rx_packet);
+		rx_packet = NULL;
+	}
+	while (1) {
+		rx = usb_rx(CDC_RX_ENDPOINT);
+		if (!rx) break;
+		usb_free(rx);
+	}
+}
+
+// Maximum number of transmit packets to queue so we don't starve other endpoints for memory
+#define TX_PACKET_LIMIT 8
+
+// When the PC isn't listening, how long do we wait before discarding data?  If this is
+// too short, we risk losing data during the stalls that are common with ordinary desktop
+// software.  If it's too long, we stall the user's program when no software is running.
+#define TX_TIMEOUT_MSEC 70
+
+#if F_CPU == 96000000
+  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596)
+#elif F_CPU == 48000000
+  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428)
+#elif F_CPU == 24000000
+  #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262)
+#endif
+
+// When we've suffered the transmit timeout, don't wait again until the computer
+// begins accepting data.  If no software is running to receive, we'll just discard
+// data as rapidly as Serial.print() can generate it, until there's something to
+// actually receive it.
+static uint8_t transmit_previous_timeout=0;
+
+
+// transmit a character.  0 returned on success, -1 on error
+int usb_serial_putchar(uint8_t c)
+{
+	return usb_serial_write(&c, 1);
+}
+
+
+int usb_serial_write(const void *buffer, uint32_t size)
+{
+	uint32_t len;
+	uint32_t wait_count;
+	const uint8_t *src = (const uint8_t *)buffer;
+	uint8_t *dest;
+
+	tx_noautoflush = 1;
+	while (size > 0) {
+		if (!tx_packet) {
+			wait_count = 0;
+			while (1) {
+				if (!usb_configuration) {
+					tx_noautoflush = 0;
+					return -1;
+				}
+				if (usb_tx_packet_count(CDC_TX_ENDPOINT) < TX_PACKET_LIMIT) {
+					tx_noautoflush = 1;
+					tx_packet = usb_malloc();
+					if (tx_packet) break;
+					tx_noautoflush = 0;
+				}
+				if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) {
+					transmit_previous_timeout = 1;
+					return -1;
+				}
+				yield();
+			}
+		}
+		transmit_previous_timeout = 0;
+		len = CDC_TX_SIZE - tx_packet->index;
+		if (len > size) len = size;
+		dest = tx_packet->buf + tx_packet->index;
+		tx_packet->index += len;
+		size -= len;
+		while (len-- > 0) *dest++ = *src++;
+		if (tx_packet->index >= CDC_TX_SIZE) {
+			tx_packet->len = CDC_TX_SIZE;
+			usb_tx(CDC_TX_ENDPOINT, tx_packet);
+			tx_packet = NULL;
+		}
+		usb_cdc_transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
+	}
+	tx_noautoflush = 0;
+	return 0;
+}
+
+void usb_serial_flush_output(void)
+{
+	if (!usb_configuration) return;
+	tx_noautoflush = 1;
+	if (tx_packet) {
+		usb_cdc_transmit_flush_timer = 0;
+		tx_packet->len = tx_packet->index;
+		usb_tx(CDC_TX_ENDPOINT, tx_packet);
+		tx_packet = NULL;
+	} else {
+		usb_packet_t *tx = usb_malloc();
+		if (tx) {
+			usb_cdc_transmit_flush_timer = 0;
+			usb_tx(CDC_TX_ENDPOINT, tx);
+		} else {
+			usb_cdc_transmit_flush_timer = 1;
+		}
+	}
+	tx_noautoflush = 0;
+}
+
+void usb_serial_flush_callback(void)
+{
+	if (tx_noautoflush) return;
+	if (tx_packet) {
+		tx_packet->len = tx_packet->index;
+		usb_tx(CDC_TX_ENDPOINT, tx_packet);
+		tx_packet = NULL;
+	} else {
+		usb_packet_t *tx = usb_malloc();
+		if (tx) {
+			usb_tx(CDC_TX_ENDPOINT, tx);
+		} else {
+			usb_cdc_transmit_flush_timer = 1;
+		}
+	}
+}
+
+
+
+
+
+
+
+
+
+#endif // CDC_STATUS_INTERFACE && CDC_DATA_INTERFACE
diff --git a/teensy3/usb_serial.h b/teensy3/usb_serial.h
new file mode 100644
index 0000000000000000000000000000000000000000..0b5c0c3048c06313e5863e4911ea3a9e5b8370c9
--- /dev/null
+++ b/teensy3/usb_serial.h
@@ -0,0 +1,107 @@
+/* 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 USBserial_h_
+#define USBserial_h_
+
+#if defined(USB_SERIAL) || defined(USB_SERIAL_HID)
+
+#include <inttypes.h>
+
+// C language implementation
+#ifdef __cplusplus
+extern "C" {
+#endif
+int usb_serial_getchar(void);
+int usb_serial_peekchar(void);
+int usb_serial_available(void);
+int usb_serial_read(void *buffer, uint32_t size);
+void usb_serial_flush_input(void);
+int usb_serial_putchar(uint8_t c);
+int usb_serial_write(const void *buffer, uint32_t size);
+void usb_serial_flush_output(void);
+extern uint32_t usb_cdc_line_coding[2];
+extern volatile uint8_t usb_cdc_line_rtsdtr;
+extern volatile uint8_t usb_cdc_transmit_flush_timer;
+extern volatile uint8_t usb_configuration;
+#ifdef __cplusplus
+}
+#endif
+
+#define USB_SERIAL_DTR  0x01
+#define USB_SERIAL_RTS  0x02
+
+
+// C++ interface
+#ifdef __cplusplus
+#include "Stream.h"
+class usb_serial_class : public Stream
+{
+public:
+        void begin(long) { /* TODO: call a function that tries to wait for enumeration */ };
+        void end() { /* TODO: flush output and shut down USB port */ };
+        virtual int available() { return usb_serial_available(); }
+        virtual int read() { return usb_serial_getchar(); }
+        virtual int peek() { return usb_serial_peekchar(); }
+        virtual void flush() { usb_serial_flush_output(); }  // TODO: actually wait for data to leave USB...
+        virtual size_t write(uint8_t c) { return usb_serial_putchar(c); }
+        virtual size_t write(const uint8_t *buffer, size_t size) { return usb_serial_write(buffer, size); }
+	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); }
+	using Print::write;
+        void send_now(void) { usb_serial_flush_output(); }
+        uint32_t baud(void) { return usb_cdc_line_coding[0]; }
+        uint8_t stopbits(void) { uint8_t b = usb_cdc_line_coding[1]; if (!b) b = 1; return b; }
+        uint8_t paritytype(void) { return usb_cdc_line_coding[1] >> 8; } // 0=none, 1=odd, 2=even
+        uint8_t numbits(void) { return usb_cdc_line_coding[1] >> 16; }
+        uint8_t dtr(void) { return (usb_cdc_line_rtsdtr & USB_SERIAL_DTR) ? 1 : 0; }
+        uint8_t rts(void) { return (usb_cdc_line_rtsdtr & USB_SERIAL_RTS) ? 1 : 0; }
+        operator bool() { return usb_configuration && (usb_cdc_line_rtsdtr & (USB_SERIAL_DTR | USB_SERIAL_RTS)); }
+	size_t readBytes(char *buffer, size_t length) {
+		size_t count=0;
+		unsigned long startMillis = millis();
+		do {
+			count += usb_serial_read(buffer + count, length - count);
+			if (count >= length) return count;
+		} while(millis() - startMillis < _timeout);
+		setReadError();
+		return count;
+	}
+
+};
+
+extern usb_serial_class Serial;
+
+#endif // __cplusplus
+
+#endif // USB_SERIAL || USB_SERIAL_HID
+#endif // USBserial_h_
diff --git a/teensy3/util/atomic.h b/teensy3/util/atomic.h
new file mode 100644
index 0000000000000000000000000000000000000000..01921982751a341a02af3621a75a75ca935d3ff3
--- /dev/null
+++ b/teensy3/util/atomic.h
@@ -0,0 +1,71 @@
+/*
+* This is port of Dean Camera's ATOMIC_BLOCK macros for AVR to ARM Cortex M3 
+* v1.0
+* Mark Pendrith, Nov 27, 2012.
+*
+* From Mark:
+* >When I ported the macros I emailed Dean to ask what attribution would be
+* >appropriate, and here is his response:
+* >
+* >>Mark,
+* >>I think it's great that you've ported the macros; consider them
+* >>public domain, to do with whatever you wish. I hope you find them >useful .
+* >>
+* >>Cheers!
+* >>- Dean 
+*/
+
+#ifdef __arm__ 
+#ifndef _CORTEX_M3_ATOMIC_H_
+#define _CORTEX_M3_ATOMIC_H_
+
+static __inline__ uint32_t __get_primask(void) \
+{ uint32_t primask = 0; \
+  __asm__ volatile ("MRS %[result], PRIMASK\n\t":[result]"=r"(primask)::); \
+  return primask; } // returns 0 if interrupts enabled, 1 if disabled
+
+static __inline__ void __set_primask(uint32_t setval) \
+{ __asm__ volatile ("MSR PRIMASK, %[value]\n\t""dmb\n\t""dsb\n\t""isb\n\t"::[value]"r"(setval):);
+  __asm__ volatile ("" ::: "memory");}
+
+static __inline__ uint32_t __iSeiRetVal(void) \
+{ __asm__ volatile ("CPSIE i\n\t""dmb\n\t""dsb\n\t""isb\n\t"); \
+  __asm__ volatile ("" ::: "memory"); return 1; }   
+
+static __inline__ uint32_t __iCliRetVal(void) \
+{ __asm__ volatile ("CPSID i\n\t""dmb\n\t""dsb\n\t""isb\n\t"); \
+  __asm__ volatile ("" ::: "memory"); return 1; }   
+
+static __inline__ void    __iSeiParam(const uint32_t *__s) \
+{ __asm__ volatile ("CPSIE i\n\t""dmb\n\t""dsb\n\t""isb\n\t"); \
+  __asm__ volatile ("" ::: "memory"); (void)__s; }
+
+static __inline__ void    __iCliParam(const uint32_t *__s) \
+{ __asm__ volatile ("CPSID i\n\t""dmb\n\t""dsb\n\t""isb\n\t"); \
+  __asm__ volatile ("" ::: "memory"); (void)__s; }
+
+static __inline__ void    __iRestore(const  uint32_t *__s) \
+{ __set_primask(*__s); __asm__ volatile ("dmb\n\t""dsb\n\t""isb\n\t"); \
+  __asm__ volatile ("" ::: "memory"); }
+
+
+#define ATOMIC_BLOCK(type) \
+for ( type, __ToDo = __iCliRetVal(); __ToDo ; __ToDo = 0 )
+
+#define ATOMIC_RESTORESTATE \
+uint32_t primask_save __attribute__((__cleanup__(__iRestore)))  = __get_primask()
+
+#define ATOMIC_FORCEON \
+uint32_t primask_save __attribute__((__cleanup__(__iSeiParam))) = 0
+   
+#define NONATOMIC_BLOCK(type) \
+for ( type, __ToDo = __iSeiRetVal(); __ToDo ;  __ToDo = 0 )
+   
+#define NONATOMIC_RESTORESTATE \
+uint32_t primask_save __attribute__((__cleanup__(__iRestore))) = __get_primask()
+
+#define NONATOMIC_FORCEOFF \
+uint32_t primask_save __attribute__((__cleanup__(__iCliParam))) = 0
+
+#endif 
+#endif
diff --git a/teensy3/util/delay.h b/teensy3/util/delay.h
new file mode 100644
index 0000000000000000000000000000000000000000..649885ebada3048a70489b963b18b881bcc0c910
--- /dev/null
+++ b/teensy3/util/delay.h
@@ -0,0 +1,3 @@
+#ifndef _delay_ms
+#define _delay_ms(n) delay(n)
+#endif
diff --git a/teensy3/wiring.h b/teensy3/wiring.h
new file mode 100644
index 0000000000000000000000000000000000000000..8ef6da97ad94c6ba6b3216308ee961406a4f973f
--- /dev/null
+++ b/teensy3/wiring.h
@@ -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 <stdint.h>
+#include <stdlib.h>
+#include "binary.h"
+#include "core_id.h"
+#include "core_pins.h"
+
+#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
+
+#ifndef M_PI
+#define M_PI 3.1415926535897932384626433832795
+#endif
+#ifndef M_SQRT2
+#define M_SQRT2 1.4142135623730950488016887
+#endif
+
+#define SERIAL  0
+#define DISPLAY 1
+
+// 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 sei() __enable_irq()
+#define cli() __disable_irq()
+#define interrupts() __enable_irq()
+#define noInterrupts() __disable_irq()
+
+#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;
+
+uint32_t pulseIn(uint8_t pin, uint8_t state, uint32_t timeout);
+void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, byte val);
+
+//void tone(uint8_t pin, uint16_t frequency, uint32_t duration);
+//void noTone(uint8_t pin);
+
+//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
diff --git a/teensy3/wiring_private.h b/teensy3/wiring_private.h
new file mode 100644
index 0000000000000000000000000000000000000000..85d03c665e8ac12ea086727e472cd347eb7542f4
--- /dev/null
+++ b/teensy3/wiring_private.h
@@ -0,0 +1,20 @@
+#ifndef WiringPrivate_h
+#define WiringPrivate_h
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "wiring.h"
+
+#ifndef cbi
+#define cbi(sfr, bit) ((sfr) &= ~_BV(bit))
+#endif
+#ifndef sbi
+#define sbi(sfr, bit) ((sfr) |= _BV(bit))
+#endif
+
+typedef void (*voidFuncPtr)(void);
+
+#endif
+
+
diff --git a/teensy3/yield.c b/teensy3/yield.c
new file mode 100644
index 0000000000000000000000000000000000000000..06c741a6730808b943df0e0a2e6f3ae75c528b23
--- /dev/null
+++ b/teensy3/yield.c
@@ -0,0 +1,32 @@
+/* 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.
+ */
+
+void yield(void) __attribute__ ((weak));
+void yield(void) {};