Browse Source

First commit, Teensy4 work-in-progress

teensy4-core
PaulStoffregen 6 years ago
parent
commit
e687673ddf
48 changed files with 14996 additions and 2 deletions
  1. +9
    -0
      teensy4/Arduino.h
  2. +16
    -0
      teensy4/Blink.cc
  3. +48
    -0
      teensy4/Client.h
  4. +344
    -0
      teensy4/EventResponder.cpp
  5. +274
    -0
      teensy4/EventResponder.h
  6. +491
    -0
      teensy4/HardwareSerial.h
  7. +125
    -0
      teensy4/IPAddress.h
  8. +113
    -0
      teensy4/IntervalTimer.cpp
  9. +135
    -0
      teensy4/IntervalTimer.h
  10. +38
    -0
      teensy4/Makefile
  11. +132
    -0
      teensy4/Print.h
  12. +42
    -0
      teensy4/Printable.h
  13. +33
    -0
      teensy4/Server.h
  14. +73
    -0
      teensy4/Stream.h
  15. +92
    -0
      teensy4/Udp.h
  16. +168
    -0
      teensy4/WCharacter.h
  17. +106
    -0
      teensy4/WProgram.h
  18. +227
    -0
      teensy4/WString.h
  19. +1
    -0
      teensy4/avr/interrupt.h
  20. +23
    -0
      teensy4/avr/io.h
  21. +131
    -0
      teensy4/avr/pgmspace.h
  22. +26
    -0
      teensy4/avr/power.h
  23. +46
    -0
      teensy4/avr/sleep.h
  24. +21
    -0
      teensy4/avr/wdt.h
  25. +0
    -0
      teensy4/avr_emulation.h
  26. +113
    -0
      teensy4/avr_functions.h
  27. +517
    -0
      teensy4/binary.h
  28. +202
    -0
      teensy4/bootdata.c
  29. +5
    -0
      teensy4/core_id.h
  30. +722
    -0
      teensy4/core_pins.h
  31. +13
    -0
      teensy4/debug/printf.h
  32. +95
    -0
      teensy4/debugprintf.c
  33. +118
    -0
      teensy4/delay.c
  34. +121
    -0
      teensy4/digital.c
  35. +81
    -0
      teensy4/elapsedMillis.h
  36. +162
    -2
      teensy4/imxrt.h
  37. +72
    -0
      teensy4/imxrt.ld
  38. +5789
    -0
      teensy4/keylayouts.h
  39. +175
    -0
      teensy4/pins_arduino.h
  40. +299
    -0
      teensy4/startup.c
  41. +556
    -0
      teensy4/usb.c
  42. +1614
    -0
      teensy4/usb_desc.c
  43. +889
    -0
      teensy4/usb_desc.h
  44. +21
    -0
      teensy4/usb_dev.h
  45. +57
    -0
      teensy4/usb_names.h
  46. +337
    -0
      teensy4/usb_serial.c
  47. +127
    -0
      teensy4/usb_serial.h
  48. +197
    -0
      teensy4/wiring.h

+ 9
- 0
teensy4/Arduino.h View File

@@ -0,0 +1,9 @@
// This header file is in the public domain.

#ifndef Arduino_h
#define Arduino_h

#include "WProgram.h"
#include "pins_arduino.h"

#endif

+ 16
- 0
teensy4/Blink.cc View File

@@ -0,0 +1,16 @@
// Only for testing with the Makefile - not actually part of the core library

#include <Arduino.h>

int led = 13;

void setup() {
pinMode(led, OUTPUT);
}

void loop() {
digitalWrite(led, HIGH);
delay(1000);
digitalWrite(led, LOW);
delay(1000);
}

+ 48
- 0
teensy4/Client.h View File

@@ -0,0 +1,48 @@
/*
Client.h - Base class that provides Client
Copyright (c) 2011 Adrian McEwen. All right reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#if ARDUINO >= 100

#ifndef 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

+ 344
- 0
teensy4/EventResponder.cpp View File

@@ -0,0 +1,344 @@
/* EventResponder - Simple event-based programming for Arduino
* Copyright 2017 Paul Stoffregen
*
* 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.
*/

/* EventResponder is an experimental API, almost certain to
* incompatibly change as it develops. Please understand any
* programs you write now using EventResponder may need to be
* updated as EventResponder develops.
*
* Please post EventResponder post your feedback here:
* https://forum.pjrc.com/threads/44723-Arduino-Events
*/

#include <Arduino.h>
#include "EventResponder.h"

EventResponder * EventResponder::firstYield = nullptr;
EventResponder * EventResponder::lastYield = nullptr;
EventResponder * EventResponder::firstInterrupt = nullptr;
EventResponder * EventResponder::lastInterrupt = nullptr;
bool EventResponder::runningFromYield = false;

// TODO: interrupt disable/enable needed in many places!!!

void EventResponder::triggerEventNotImmediate()
{
bool irq = disableInterrupts();
if (_triggered == false) {
// not already triggered
if (_type == EventTypeYield) {
// normal type, called from yield()
if (firstYield == nullptr) {
_next = nullptr;
_prev = nullptr;
firstYield = this;
lastYield = this;
} else {
_next = nullptr;
_prev = lastYield;
_prev->_next = this;
lastYield = this;
}
} else if (_type == EventTypeInterrupt) {
// interrupt, called from software interrupt
if (firstInterrupt == nullptr) {
_next = nullptr;
_prev = nullptr;
firstInterrupt = this;
lastInterrupt = this;
} else {
_next = nullptr;
_prev = lastInterrupt;
_prev->_next = this;
lastInterrupt = this;
}
SCB_ICSR = SCB_ICSR_PENDSVSET; // set PendSV interrupt
} else {
// detached, easy :-)
}
_triggered = true;
}
enableInterrupts(irq);
}

void pendablesrvreq_isr(void)
{
EventResponder::runFromInterrupt();
}

void EventResponder::runFromInterrupt()
{
while (1) {
bool irq = disableInterrupts();
EventResponder *first = firstInterrupt;
if (first) {
firstInterrupt = first->_next;
if (firstInterrupt) {
firstInterrupt->_prev = nullptr;
} else {
lastInterrupt = nullptr;
}
enableInterrupts(irq);
first->_triggered = false;
(*(first->_function))(*first);
} else {
enableInterrupts(irq);
break;
}
}
}

bool EventResponder::clearEvent()
{
bool ret = false;
bool irq = disableInterrupts();
if (_triggered) {
if (_type == EventTypeYield) {
if (_prev) {
_prev->_next = _next;
} else {
firstYield = _next;
}
if (_next) {
_next->_prev = _prev;
} else {
lastYield = _prev;
}
} else if (_type == EventTypeInterrupt) {
if (_prev) {
_prev->_next = _next;
} else {
firstInterrupt = _next;
}
if (_next) {
_next->_prev = _prev;
} else {
lastInterrupt = _prev;
}
}
_triggered = false;
ret = true;
}
enableInterrupts(irq);
return ret;
}

// this detach must be called with interrupts disabled
void EventResponder::detachNoInterrupts()
{
if (_type == EventTypeYield) {
if (_triggered) {
if (_prev) {
_prev->_next = _next;
} else {
firstYield = _next;
}
if (_next) {
_next->_prev = _prev;
} else {
lastYield = _prev;
}
}
_type = EventTypeDetached;
} else if (_type == EventTypeInterrupt) {
if (_triggered) {
if (_prev) {
_prev->_next = _next;
} else {
firstInterrupt = _next;
}
if (_next) {
_next->_prev = _prev;
} else {
lastInterrupt = _prev;
}
}
_type = EventTypeDetached;
}
}


//-------------------------------------------------------------


MillisTimer * MillisTimer::listWaiting = nullptr;
MillisTimer * MillisTimer::listActive = nullptr;

void MillisTimer::begin(unsigned long milliseconds, EventResponderRef event)
{
if (_state != TimerOff) end();
if (!milliseconds) return;
_event = &event;
_ms = (milliseconds > 2)? milliseconds-2 : 0;
_reload = 0;
addToWaitingList();
}

void MillisTimer::beginRepeating(unsigned long milliseconds, EventResponderRef event)
{
if (_state != TimerOff) end();
if (!milliseconds) return;
_event = &event;
_ms = (milliseconds > 2)? milliseconds-2 : 0;
_reload = milliseconds;
addToWaitingList();
}

void MillisTimer::addToWaitingList()
{
_prev = nullptr;
bool irq = disableTimerInterrupt();
_next = listWaiting;
listWaiting = this; // TODO: use STREX to avoid interrupt disable
_state = TimerWaiting;
enableTimerInterrupt(irq);
}

void MillisTimer::addToActiveList() // only called by runFromTimer()
{
if (listActive == nullptr) {
// list is empty, easy case
_next = nullptr;
_prev = nullptr;
listActive = this;
} else if (_ms < listActive->_ms) {
// this timer triggers before any on the list
_next = listActive;
_prev = nullptr;
listActive->_prev = this;
// Decrement the next items wait time be our wait time as to properly handle waits for all other items...
listActive->_ms -= _ms;
listActive = this;
} else {
// add this timer somewhere after the first already on the list
MillisTimer *timer = listActive;
while (timer->_next) {
_ms -= timer->_ms;
timer = timer->_next;
if (_ms < timer->_ms) {
// found the right place in the middle of list
_next = timer;
_prev = timer->_prev;
timer->_prev = this;
_prev->_next = this;
timer->_ms -= _ms;
_state = TimerActive;
return;
}
}
// add this time at the end of the list
_ms -= timer->_ms;
_next = nullptr;
_prev = timer;
timer->_next = this;
}
_state = TimerActive;
}

void MillisTimer::end()
{
bool irq = disableTimerInterrupt();
TimerStateType s = _state;
if (s == TimerActive) {
if (_next) {
_next->_prev = _prev;
_next->_ms += _ms; // add in the rest of our timing to next entry...
}
if (_prev) {
_prev->_next = _next;
} else {
listActive = _next;
}
_state = TimerOff;
} else if (s == TimerWaiting) {
if (listWaiting == this) {
listWaiting = _next;
} else {
MillisTimer *timer = listWaiting;
while (timer) {
if (timer->_next == this) {
timer->_next = _next;
break;
}
timer = timer->_next;
}
}
_state = TimerOff;
}
enableTimerInterrupt(irq);
}

void MillisTimer::runFromTimer()
{
MillisTimer *timer = listActive;
while (timer) {
if (timer->_ms > 0) {
timer->_ms--;
break;
} else {
MillisTimer *next = timer->_next;
if (next) next->_prev = nullptr;
listActive = next;
timer->_state = TimerOff;
EventResponderRef event = *(timer->_event);
event.triggerEvent(0, timer);
if (timer->_reload) {
timer->_ms = timer->_reload;
timer->addToActiveList();
}
timer = listActive;
}
}
bool irq = disableTimerInterrupt();
MillisTimer *waiting = listWaiting;
listWaiting = nullptr; // TODO: use STREX to avoid interrupt disable
enableTimerInterrupt(irq);
while (waiting) {
MillisTimer *next = waiting->_next;
waiting->addToActiveList();
waiting = next;
}
}

// Long ago you could install your own systick interrupt handler by just
// creating your own systick_isr() function. No longer. But if you
// *really* want to commandeer systick, you can still do so by writing
// your function into the RAM-based vector table.
//
// _VectorsRam[15] = my_systick_function;
//
// However, for long-term portability, use a MillisTimer object to
// generate an event every millisecond, and attach your function to
// its EventResponder. You can attach as a software interrupt, so your
// code will run at lower interrupt priority for better compatibility
// with libraries using mid-to-high priority interrupts.

extern "C" volatile uint32_t systick_millis_count;
void systick_isr(void)
{
systick_millis_count++;
MillisTimer::runFromTimer();
}



+ 274
- 0
teensy4/EventResponder.h View File

@@ -0,0 +1,274 @@
/* EventResponder - Simple event-based programming for Arduino
* Copyright 2017 Paul Stoffregen
*
* 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.
*/

/* EventResponder is an experimental API, almost certain to
* incompatibly change as it develops. Please understand any
* programs you write now using EventResponder may need to be
* updated as EventResponder develops.
*
* Please post your EventResponder feedback here:
* https://forum.pjrc.com/threads/44723-Arduino-Events
*/

#if !defined(EventResponder_h) && defined(__cplusplus)
#define EventResponder_h

#include <Arduino.h>

/* EventResponder lets you control how your program responds to an event.
* Imagine a basketball or football (American soccer) player who gets the
* ball. Usually they will pass to another player who has the best
* opportunity to score. Similarly in Arduino programming, events are
* often triggered within interrupts or other timing sensitive code.
* EventResponder can call your function a short time later, giving you
* the ability to use Arduino functions and libraries which would not
* be safe to use from an interrupt. However, some situations do call
* for the most immediate response, even if doing so is more difficult.
* EventResponder lets you choose how your function will be called,
* without editing the timers or libraries which trigger the events.
*
* Event handling functions called by EventResponder should complete
* their work quickly. Avoid delays or operations which may take
* substantial time. While your function runs, no other event functions
* (attached the same way) are able to run.
*
* If your EventResponder is triggered more than once before your
* function can run, only the last trigger is used. Prior triggering,
* including the status integer and data pointer, are overwritten and
* your function is called only one time, based on the last trigger
* event.
*/

class EventResponder;
typedef EventResponder& EventResponderRef;
typedef void (*EventResponderFunction)(EventResponderRef);
class EventResponder
{
public:
constexpr EventResponder() {
}
~EventResponder() {
detach();
}
enum EventType { // these are not meant for public consumption...
EventTypeDetached = 0, // no function is called
EventTypeYield, // function is called from yield()
EventTypeImmediate, // function is called immediately
EventTypeInterrupt, // function is called from interrupt
EventTypeThread // function is run as a new thread
};

// Attach a function to be called from yield(). This should be the
// default way to use EventResponder. Calls from yield() allow use
// of Arduino libraries, String, Serial, etc.
void attach(EventResponderFunction function, uint8_t priority=128) {
bool irq = disableInterrupts();
detachNoInterrupts();
_function = function;
_type = EventTypeYield;
enableInterrupts(irq);
}

// Attach a function to be called immediately. This provides the
// fastest possible response, but your function must be carefully
// designed.
void attachImmediate(EventResponderFunction function) {
bool irq = disableInterrupts();
detachNoInterrupts();
_function = function;
_type = EventTypeImmediate;
enableInterrupts(irq);
}

// Attach a function to be called from a low priority interrupt.
// Boards not supporting software triggered interrupts will implement
// this as attachImmediate. On ARM and other platforms with software
// interrupts, this allow fast interrupt-based response, but with less
// disruption to other libraries requiring their own interrupts.
void attachInterrupt(EventResponderFunction function, uint8_t priority=128) {
bool irq = disableInterrupts();
detachNoInterrupts();
_function = function;
_type = EventTypeInterrupt;
SCB_SHPR3 |= 0x00FF0000; // configure PendSV, lowest priority
enableInterrupts(irq);
}

// Attach a function to be called as its own thread. Boards not running
// a RTOS or pre-emptive scheduler shall implement this as attach().
void attachThread(EventResponderFunction function, void *param=nullptr) {
attach(function); // for non-RTOS usage, compile as default attach
}

// Do not call any function. The user's program must occasionally check
// whether the event has occurred, or use one of the wait functions.
void detach() {
bool irq = disableInterrupts();
detachNoInterrupts();
enableInterrupts(irq);
}

// Trigger the event. An optional status code and data may be provided.
// The code triggering the event does NOT control which of the above
// response methods will be used.
virtual void triggerEvent(int status=0, void *data=nullptr) {
_status = status;
_data = data;
if (_type == EventTypeImmediate) {
(*_function)(*this);
} else {
triggerEventNotImmediate();
}
}
// Clear an event which has been triggered, but has not yet caused a
// function to be called.
bool clearEvent();

// Get the event's status code. Typically this will indicate if the event was
// triggered due to successful completion, or how much data was successfully
// processed (positive numbers) or an error (negative numbers). The
// exact meaning of this status code depends on the code or library which
// triggers the event.
int getStatus() { return _status; }

// Get the optional data pointer associated with the event. Often this
// will be NULL, or will be the object instance which triggered the event.
// Some libraries may use this to pass data associated with the event.
void * getData() { return _data; }

// An optional "context" may be associated with each EventResponder.
// When more than one EventResponder has the same function attached, these
// may be used to allow the function to obtain extra information needed
// depending on which EventResponder called it.
void setContext(void *context) { _context = context; }
void * getContext() { return _context; }

// Wait for event(s) to occur. These are most likely to be useful when
// used with a scheduler or RTOS.
bool waitForEvent(EventResponderRef event, int timeout);
EventResponder * waitForEvent(EventResponder *list, int listsize, int timeout);

static void runFromYield() {
// First, check if yield was called from an interrupt
// never call normal handler functions from any interrupt context
uint32_t ipsr;
__asm__ volatile("mrs %0, ipsr\n" : "=r" (ipsr)::);
if (ipsr != 0) return;
// Next, check if any events have been triggered
bool irq = disableInterrupts();
EventResponder *first = firstYield;
if (first == nullptr) {
enableInterrupts(irq);
return;
}
// Finally, make sure we're not being recursively called,
// which can happen if the user's function does anything
// that calls yield.
if (runningFromYield) {
enableInterrupts(irq);
return;
}
// Ok, update the runningFromYield flag and process event
runningFromYield = true;
firstYield = first->_next;
if (firstYield) {
firstYield->_prev = nullptr;
} else {
lastYield = nullptr;
}
enableInterrupts(irq);
first->_triggered = false;
(*(first->_function))(*first);
runningFromYield = false;
}
static void runFromInterrupt();
operator bool() { return _triggered; }
protected:
void triggerEventNotImmediate();
void detachNoInterrupts();
int _status = 0;
EventResponderFunction _function = nullptr;
void *_data = nullptr;
void *_context = nullptr;
EventResponder *_next = nullptr;
EventResponder *_prev = nullptr;
EventType _type = EventTypeDetached;
bool _triggered = false;
static EventResponder *firstYield;
static EventResponder *lastYield;
static EventResponder *firstInterrupt;
static EventResponder *lastInterrupt;
static bool runningFromYield;
private:
static bool disableInterrupts() {
uint32_t primask;
__asm__ volatile("mrs %0, primask\n" : "=r" (primask)::);
__disable_irq();
return (primask == 0) ? true : false;
}
static void enableInterrupts(bool doit) {
if (doit) __enable_irq();
}
};

class MillisTimer
{
public:
constexpr MillisTimer() {
}
~MillisTimer() {
end();
}
void begin(unsigned long milliseconds, EventResponderRef event);
void beginRepeating(unsigned long milliseconds, EventResponderRef event);
void end();
static void runFromTimer();
private:
void addToWaitingList();
void addToActiveList();
unsigned long _ms = 0;
unsigned long _reload = 0;
MillisTimer *_next = nullptr;
MillisTimer *_prev = nullptr;
EventResponder *_event = nullptr;
enum TimerStateType {
TimerOff = 0,
TimerWaiting,
TimerActive
};
volatile TimerStateType _state = TimerOff;
static MillisTimer *listWaiting; // single linked list of waiting to start timers
static MillisTimer *listActive; // double linked list of running timers
static bool disableTimerInterrupt() {
uint32_t primask;
__asm__ volatile("mrs %0, primask\n" : "=r" (primask)::);
__disable_irq();
return (primask == 0) ? true : false;
}
static void enableTimerInterrupt(bool doit) {
if (doit) __enable_irq();
}
};

#endif

+ 491
- 0
teensy4/HardwareSerial.h View File

@@ -0,0 +1,491 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2017 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 "imxrt.h"

// Uncomment to enable 9 bit formats. These are default disabled to save memory.
//#define SERIAL_9BIT_SUPPORT
//
// On Windows & Linux, this file is in Arduino's hardware/teensy/avr/cores/teensy3
// folder. The Windows installer puts Arduino in C:\Program Files (x86)\Arduino
// On Macintosh, you must control-click Arduino and select "Show Package Contents", then
// look in Contents/Java/hardware/teensy/avr/cores/teensy3 to find this file.
//
// Teensy 3.x boards support 9 bit mode on all their serial ports
// Teensy LC only supports 9 bit mode on Serial1. Serial2 & Serial3 can't use 9 bits.


#define SERIAL_7E1 0x02
#define SERIAL_7O1 0x03
#define SERIAL_8N1 0x00
#define SERIAL_8E1 0x06
#define SERIAL_8O1 0x07
#define SERIAL_7E1_RXINV 0x12
#define SERIAL_7O1_RXINV 0x13
#define SERIAL_8N1_RXINV 0x10
#define SERIAL_8E1_RXINV 0x16
#define SERIAL_8O1_RXINV 0x17
#define SERIAL_7E1_TXINV 0x22
#define SERIAL_7O1_TXINV 0x23
#define SERIAL_8N1_TXINV 0x20
#define SERIAL_8E1_TXINV 0x26
#define SERIAL_8O1_TXINV 0x27
#define SERIAL_7E1_RXINV_TXINV 0x32
#define SERIAL_7O1_RXINV_TXINV 0x33
#define SERIAL_8N1_RXINV_TXINV 0x30
#define SERIAL_8E1_RXINV_TXINV 0x36
#define SERIAL_8O1_RXINV_TXINV 0x37
#ifdef SERIAL_9BIT_SUPPORT
#define SERIAL_9N1 0x84
#define SERIAL_9E1 0x8E
#define SERIAL_9O1 0x8F
#define SERIAL_9N1_RXINV 0x94
#define SERIAL_9E1_RXINV 0x9E
#define SERIAL_9O1_RXINV 0x9F
#define SERIAL_9N1_TXINV 0xA4
#define SERIAL_9E1_TXINV 0xAE
#define SERIAL_9O1_TXINV 0xAF
#define SERIAL_9N1_RXINV_TXINV 0xB4
#define SERIAL_9E1_RXINV_TXINV 0xBE
#define SERIAL_9O1_RXINV_TXINV 0xBF
#endif
// Teensy LC and 3.5 and 3.6 Uarts have 1/2 bit stop setting
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(KINETISL)
#define SERIAL_2STOP_BITS 0x100
#define SERIAL_8E2 (SERIAL_8E1 | SERIAL_2STOP_BITS)
#define SERIAL_8O2 (SERIAL_8O1 | SERIAL_2STOP_BITS)
#define SERIAL_8E2_RXINV (SERIAL_8E1_RXINV | SERIAL_2STOP_BITS)
#define SERIAL_8O2_RXINV (SERIAL_8O1_RXINV | SERIAL_2STOP_BITS)
#define SERIAL_8E2_TXINV (SERIAL_8E1_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8O2_TXINV (SERIAL_8O1_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8E2_RXINV_TXINV (SERIAL_8E1_RXINV_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8O2_RXINV_TXINV (SERIAL_8O1_RXINV_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8N2 (SERIAL_8N1 | SERIAL_2STOP_BITS)
#define SERIAL_8N2_RXINV (SERIAL_8N1_RXINV | SERIAL_2STOP_BITS)
#define SERIAL_8N2_TXINV (SERIAL_8N1_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8N2_RXINV_TXINV (SERIAL_8N1_RXINV_TXINV | SERIAL_2STOP_BITS)
#else
// for Teensy 3.0-3.2 we can fake 2 stop bits by using 9 bit mode
#define SERIAL_8N2 0x04
#define SERIAL_8N2_RXINV 0x14
#define SERIAL_8N2_TXINV 0x24
#define SERIAL_8N2_RXINV_TXINV 0x34
#endif
// bit0: parity, 0=even, 1=odd
// bit1: parity, 0=disable, 1=enable
// bit2: mode, 1=9bit, 0=8bit
// bit3: mode10: 1=10bit, 0=8bit
// bit4: rxinv, 0=normal, 1=inverted
// bit5: txinv, 0=normal, 1=inverted
// bit6: unused
// bit7: actual data goes into 9th bit


// TODO: replace with proper divisor+oversample calculation
#define BAUD2DIV(baud) (24000000/16/(baud))

/*
#if defined(KINETISK)
#define BAUD2DIV(baud) (((F_CPU * 2) + ((baud) >> 1)) / (baud))
#define BAUD2DIV2(baud) (((F_CPU * 2) + ((baud) >> 1)) / (baud))
#define BAUD2DIV3(baud) (((F_BUS * 2) + ((baud) >> 1)) / (baud))
#elif defined(KINETISL)

#if F_CPU <= 2000000
#define BAUD2DIV(baud) (((F_PLL / 16 ) + ((baud) >> 1)) / (baud))
#elif F_CPU <= 16000000
#define BAUD2DIV(baud) (((F_PLL / (F_PLL / 1000000)) + ((baud) >> 1)) / (baud))
#else
#define BAUD2DIV(baud) (((F_PLL / 2 / 16) + ((baud) >> 1)) / (baud))
#endif

#define BAUD2DIV2(baud) (((F_BUS / 16) + ((baud) >> 1)) / (baud))
#define BAUD2DIV3(baud) (((F_BUS / 16) + ((baud) >> 1)) / (baud))
#endif
*/


// C language implementation
//
#ifdef __cplusplus
extern "C" {
#endif
void serial_begin(uint32_t divisor);
void serial_format(uint32_t format);
void serial_end(void);
void serial_set_transmit_pin(uint8_t pin);
void serial_set_rx(uint8_t pin);
void serial_set_tx(uint8_t pin, uint8_t opendrain);
int serial_set_rts(uint8_t pin);
int serial_set_cts(uint8_t pin);
void serial_putchar(uint32_t c);
void serial_write(const void *buf, unsigned int count);
void serial_flush(void);
int serial_write_buffer_free(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_format(uint32_t format);
void serial2_end(void);
void serial2_set_transmit_pin(uint8_t pin);
void serial2_set_rx(uint8_t pin);
void serial2_set_tx(uint8_t pin, uint8_t opendrain);
int serial2_set_rts(uint8_t pin);
int serial2_set_cts(uint8_t pin);
void serial2_putchar(uint32_t c);
void serial2_write(const void *buf, unsigned int count);
void serial2_flush(void);
int serial2_write_buffer_free(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_format(uint32_t format);
void serial3_end(void);
void serial3_set_transmit_pin(uint8_t pin);
void serial3_set_rx(uint8_t pin);
void serial3_set_tx(uint8_t pin, uint8_t opendrain);
int serial3_set_rts(uint8_t pin);
int serial3_set_cts(uint8_t pin);
void serial3_putchar(uint32_t c);
void serial3_write(const void *buf, unsigned int count);
void serial3_flush(void);
int serial3_write_buffer_free(void);
int serial3_available(void);
int serial3_getchar(void);
int serial3_peek(void);
void serial3_clear(void);

void serial4_begin(uint32_t divisor);
void serial4_format(uint32_t format);
void serial4_end(void);
void serial4_set_transmit_pin(uint8_t pin);
void serial4_set_rx(uint8_t pin);
void serial4_set_tx(uint8_t pin, uint8_t opendrain);
int serial4_set_rts(uint8_t pin);
int serial4_set_cts(uint8_t pin);
void serial4_putchar(uint32_t c);
void serial4_write(const void *buf, unsigned int count);
void serial4_flush(void);
int serial4_write_buffer_free(void);
int serial4_available(void);
int serial4_getchar(void);
int serial4_peek(void);
void serial4_clear(void);

void serial5_begin(uint32_t divisor);
void serial5_format(uint32_t format);
void serial5_end(void);
void serial5_set_transmit_pin(uint8_t pin);
void serial5_set_rx(uint8_t pin);
void serial5_set_tx(uint8_t pin, uint8_t opendrain);
int serial5_set_rts(uint8_t pin);
int serial5_set_cts(uint8_t pin);
void serial5_putchar(uint32_t c);
void serial5_write(const void *buf, unsigned int count);
void serial5_flush(void);
int serial5_write_buffer_free(void);
int serial5_available(void);
int serial5_getchar(void);
int serial5_peek(void);
void serial5_clear(void);

void serial6_begin(uint32_t divisor);
void serial6_format(uint32_t format);
void serial6_end(void);
void serial6_set_transmit_pin(uint8_t pin);
void serial6_set_rx(uint8_t pin);
void serial6_set_tx(uint8_t pin, uint8_t opendrain);
int serial6_set_rts(uint8_t pin);
int serial6_set_cts(uint8_t pin);
void serial6_putchar(uint32_t c);
void serial6_write(const void *buf, unsigned int count);
void serial6_flush(void);
int serial6_write_buffer_free(void);
int serial6_available(void);
int serial6_getchar(void);
int serial6_peek(void);
void serial6_clear(void);

#ifdef __cplusplus
}
#endif


// C++ interface
//
#ifdef __cplusplus
#include "Stream.h"
class HardwareSerial : public Stream
{
public:
constexpr HardwareSerial() {}
virtual void begin(uint32_t baud) { serial_begin(BAUD2DIV(baud)); }
virtual void begin(uint32_t baud, uint32_t format) {
serial_begin(BAUD2DIV(baud));
serial_format(format); }
virtual void end(void) { serial_end(); }
virtual void transmitterEnable(uint8_t pin) { serial_set_transmit_pin(pin); }
virtual void setRX(uint8_t pin) { serial_set_rx(pin); }
virtual void setTX(uint8_t pin, bool opendrain=false) { serial_set_tx(pin, opendrain); }
virtual bool attachRts(uint8_t pin) { return serial_set_rts(pin); }
virtual bool attachCts(uint8_t pin) { return serial_set_cts(pin); }
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(); }
virtual void clear(void) { serial_clear(); }
virtual int availableForWrite(void) { return serial_write_buffer_free(); }
using Print::write;
virtual size_t write(uint8_t c) { serial_putchar(c); return 1; }
virtual size_t write(unsigned long n) { return write((uint8_t)n); }
virtual size_t write(long n) { return write((uint8_t)n); }
virtual size_t write(unsigned int n) { return write((uint8_t)n); }
virtual 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; }
virtual size_t write(const char *str) { size_t len = strlen(str);
serial_write((const uint8_t *)str, len);
return len; }
virtual size_t write9bit(uint32_t c) { serial_putchar(c); return 1; }
operator bool() { return true; }
};
extern HardwareSerial Serial1;
extern void serialEvent1(void);

class HardwareSerial2 : public HardwareSerial
{
public:
constexpr HardwareSerial2() {}
virtual void begin(uint32_t baud) { serial2_begin(BAUD2DIV(baud)); }
virtual void begin(uint32_t baud, uint32_t format) {
serial2_begin(BAUD2DIV(baud));
serial2_format(format); }
virtual void end(void) { serial2_end(); }
virtual void transmitterEnable(uint8_t pin) { serial2_set_transmit_pin(pin); }
virtual void setRX(uint8_t pin) { serial2_set_rx(pin); }
virtual void setTX(uint8_t pin, bool opendrain=false) { serial2_set_tx(pin, opendrain); }
virtual bool attachRts(uint8_t pin) { return serial2_set_rts(pin); }
virtual bool attachCts(uint8_t pin) { return serial2_set_cts(pin); }
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(); }
virtual void clear(void) { serial2_clear(); }
virtual int availableForWrite(void) { return serial2_write_buffer_free(); }
using Print::write;
virtual size_t write(uint8_t c) { serial2_putchar(c); return 1; }
virtual size_t write(unsigned long n) { return write((uint8_t)n); }
virtual size_t write(long n) { return write((uint8_t)n); }
virtual size_t write(unsigned int n) { return write((uint8_t)n); }
virtual 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; }
virtual size_t write(const char *str) { size_t len = strlen(str);
serial2_write((const uint8_t *)str, len);
return len; }
virtual size_t write9bit(uint32_t c) { serial2_putchar(c); return 1; }
operator bool() { return true; }
};
extern HardwareSerial2 Serial2;
extern void serialEvent2(void);

class HardwareSerial3 : public HardwareSerial
{
public:
constexpr HardwareSerial3() {}
virtual void begin(uint32_t baud) { serial3_begin(BAUD2DIV(baud)); }
virtual void begin(uint32_t baud, uint32_t format) {
serial3_begin(BAUD2DIV(baud));
serial3_format(format); }
virtual void end(void) { serial3_end(); }
virtual void transmitterEnable(uint8_t pin) { serial3_set_transmit_pin(pin); }
virtual void setRX(uint8_t pin) { serial3_set_rx(pin); }
virtual void setTX(uint8_t pin, bool opendrain=false) { serial3_set_tx(pin, opendrain); }
virtual bool attachRts(uint8_t pin) { return serial3_set_rts(pin); }
virtual bool attachCts(uint8_t pin) { return serial3_set_cts(pin); }
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(); }
virtual void clear(void) { serial3_clear(); }
virtual int availableForWrite(void) { return serial3_write_buffer_free(); }
using Print::write;
virtual size_t write(uint8_t c) { serial3_putchar(c); return 1; }
virtual size_t write(unsigned long n) { return write((uint8_t)n); }
virtual size_t write(long n) { return write((uint8_t)n); }
virtual size_t write(unsigned int n) { return write((uint8_t)n); }
virtual 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; }
virtual size_t write(const char *str) { size_t len = strlen(str);
serial3_write((const uint8_t *)str, len);
return len; }
virtual size_t write9bit(uint32_t c) { serial3_putchar(c); return 1; }
operator bool() { return true; }
};
extern HardwareSerial3 Serial3;
extern void serialEvent3(void);

class HardwareSerial4 : public HardwareSerial
{
public:
constexpr HardwareSerial4() {}
virtual void begin(uint32_t baud) { serial4_begin(BAUD2DIV(baud)); }
virtual void begin(uint32_t baud, uint32_t format) {
serial4_begin(BAUD2DIV(baud));
serial4_format(format); }
virtual void end(void) { serial4_end(); }
virtual void transmitterEnable(uint8_t pin) { serial4_set_transmit_pin(pin); }
virtual void setRX(uint8_t pin) { serial4_set_rx(pin); }
virtual void setTX(uint8_t pin, bool opendrain=false) { serial4_set_tx(pin, opendrain); }
virtual bool attachRts(uint8_t pin) { return serial4_set_rts(pin); }
virtual bool attachCts(uint8_t pin) { return serial4_set_cts(pin); }
virtual int available(void) { return serial4_available(); }
virtual int peek(void) { return serial4_peek(); }
virtual int read(void) { return serial4_getchar(); }
virtual void flush(void) { serial4_flush(); }
virtual void clear(void) { serial4_clear(); }
virtual int availableForWrite(void) { return serial4_write_buffer_free(); }
using Print::write;
virtual size_t write(uint8_t c) { serial4_putchar(c); return 1; }
virtual size_t write(unsigned long n) { return write((uint8_t)n); }
virtual size_t write(long n) { return write((uint8_t)n); }
virtual size_t write(unsigned int n) { return write((uint8_t)n); }
virtual size_t write(int n) { return write((uint8_t)n); }
virtual size_t write(const uint8_t *buffer, size_t size)
{ serial4_write(buffer, size); return size; }
virtual size_t write(const char *str) { size_t len = strlen(str);
serial4_write((const uint8_t *)str, len);
return len; }
virtual size_t write9bit(uint32_t c) { serial4_putchar(c); return 1; }
operator bool() { return true; }
};
extern HardwareSerial4 Serial4;
extern void serialEvent4(void);

class HardwareSerial5 : public HardwareSerial
{
public:
constexpr HardwareSerial5() {}
virtual void begin(uint32_t baud) { serial5_begin(BAUD2DIV(baud)); }
virtual void begin(uint32_t baud, uint32_t format) {
serial5_begin(BAUD2DIV(baud));
serial5_format(format); }
virtual void end(void) { serial5_end(); }
virtual void transmitterEnable(uint8_t pin) { serial5_set_transmit_pin(pin); }
virtual void setRX(uint8_t pin) { serial5_set_rx(pin); }
virtual void setTX(uint8_t pin, bool opendrain=false) { serial5_set_tx(pin, opendrain); }
virtual bool attachRts(uint8_t pin) { return serial5_set_rts(pin); }
virtual bool attachCts(uint8_t pin) { return serial5_set_cts(pin); }
virtual int available(void) { return serial5_available(); }
virtual int peek(void) { return serial5_peek(); }
virtual int read(void) { return serial5_getchar(); }
virtual void flush(void) { serial5_flush(); }
virtual void clear(void) { serial5_clear(); }
virtual int availableForWrite(void) { return serial5_write_buffer_free(); }
using Print::write;
virtual size_t write(uint8_t c) { serial5_putchar(c); return 1; }
virtual size_t write(unsigned long n) { return write((uint8_t)n); }
virtual size_t write(long n) { return write((uint8_t)n); }
virtual size_t write(unsigned int n) { return write((uint8_t)n); }
virtual size_t write(int n) { return write((uint8_t)n); }
virtual size_t write(const uint8_t *buffer, size_t size)
{ serial5_write(buffer, size); return size; }
virtual size_t write(const char *str) { size_t len = strlen(str);
serial5_write((const uint8_t *)str, len);
return len; }
virtual size_t write9bit(uint32_t c) { serial5_putchar(c); return 1; }
operator bool() { return true; }
};
extern HardwareSerial5 Serial5;
extern void serialEvent5(void);

class HardwareSerial6 : public HardwareSerial
{
public:
constexpr HardwareSerial6() {}
#if defined(__MK66FX1M0__) // For LPUART just pass baud straight in.
virtual void begin(uint32_t baud) { serial6_begin(baud); }
virtual void begin(uint32_t baud, uint32_t format) {
serial6_begin(baud);
serial6_format(format); }
#else
virtual void begin(uint32_t baud) { serial6_begin(BAUD2DIV(baud)); }
virtual void begin(uint32_t baud, uint32_t format) {
serial6_begin(BAUD2DIV(baud));
serial6_format(format); }
#endif
virtual void end(void) { serial6_end(); }
virtual void transmitterEnable(uint8_t pin) { serial6_set_transmit_pin(pin); }
virtual void setRX(uint8_t pin) { serial6_set_rx(pin); }
virtual void setTX(uint8_t pin, bool opendrain=false) { serial6_set_tx(pin, opendrain); }
virtual bool attachRts(uint8_t pin) { return serial6_set_rts(pin); }
virtual bool attachCts(uint8_t pin) { return serial6_set_cts(pin); }
virtual int available(void) { return serial6_available(); }
virtual int peek(void) { return serial6_peek(); }
virtual int read(void) { return serial6_getchar(); }
virtual void flush(void) { serial6_flush(); }
virtual void clear(void) { serial6_clear(); }
virtual int availableForWrite(void) { return serial6_write_buffer_free(); }
using Print::write;
virtual size_t write(uint8_t c) { serial6_putchar(c); return 1; }
virtual size_t write(unsigned long n) { return write((uint8_t)n); }
virtual size_t write(long n) { return write((uint8_t)n); }
virtual size_t write(unsigned int n) { return write((uint8_t)n); }
virtual size_t write(int n) { return write((uint8_t)n); }
virtual size_t write(const uint8_t *buffer, size_t size)
{ serial6_write(buffer, size); return size; }
virtual size_t write(const char *str) { size_t len = strlen(str);
serial6_write((const uint8_t *)str, len);
return len; }
virtual size_t write9bit(uint32_t c) { serial6_putchar(c); return 1; }
operator bool() { return true; }
};
extern HardwareSerial6 Serial6;
extern void serialEvent6(void);




#endif
#endif

+ 125
- 0
teensy4/IPAddress.h View File

@@ -0,0 +1,125 @@
/*
*
* MIT License:
* Copyright (c) 2011 Adrian McEwen
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* adrianm@mcqn.com 1/1/2011
*/

#ifndef IPAddress_h
#define IPAddress_h

#include <Printable.h>
#include <WString.h>

// A class to make it easier to handle and pass around IP addresses

class IPAddress : public Printable {
private:
union {
uint8_t bytes[4]; // IPv4 address
uint32_t dword;
} _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.bytes; };

public:
// Constructors
IPAddress() {
_address.dword = 0;
}
IPAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) {
_address.bytes[0] = b1;
_address.bytes[1] = b2;
_address.bytes[2] = b3;
_address.bytes[3] = b4;
}
IPAddress(uint32_t address) {
_address.dword = address;
}
IPAddress(const uint8_t *address) {
// TODO: use unaligned read on Cortex-M4
_address.bytes[0] = *address++;
_address.bytes[1] = *address++;
_address.bytes[2] = *address++;
_address.bytes[3] = *address++;
}

bool fromString(const char *address);
bool fromString(const String &address) {
return fromString(address.c_str());
}

// 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.dword;
}
bool operator==(const IPAddress& addr) {
return _address.dword == addr._address.dword;
}
bool operator==(const uint8_t* addr) {
// TODO: use unaligned read on Cortex-M4
return (_address.bytes[0] == addr[0]
&& _address.bytes[1] == addr[1]
&& _address.bytes[2] == addr[2]
&& _address.bytes[3] == addr[3]);
}

// Overloaded index operator to allow getting and setting individual octets of the address
uint8_t operator[](int index) const {
return _address.bytes[index];
};
uint8_t& operator[](int index) {
return _address.bytes[index];
};

// Overloaded copy operators to allow initialisation of IPAddress objects from other types
IPAddress& operator=(const uint8_t *address) {
// TODO: use unaligned read on Cortex-M4
_address.bytes[0] = *address++;
_address.bytes[1] = *address++;
_address.bytes[2] = *address++;
_address.bytes[3] = *address++;
return *this;
}
IPAddress& operator=(uint32_t address) {
_address.dword = address;
return *this;
}

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((uint32_t)0);


#endif

+ 113
- 0
teensy4/IntervalTimer.cpp View File

@@ -0,0 +1,113 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2017 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 "IntervalTimer.h"

static void dummy_funct(void);

#define NUM_CHANNELS 4
static void (*funct_table[4])(void) = {dummy_funct, dummy_funct, dummy_funct, dummy_funct};
uint8_t IntervalTimer::nvic_priorites[4] = {255, 255, 255, 255};


bool IntervalTimer::beginCycles(void (*funct)(), uint32_t cycles)
{
#if 0
if (channel) {
channel->TCTRL = 0;
channel->TFLG = 1;
} else {
SIM_SCGC6 |= SIM_SCGC6_PIT;
__asm__ volatile("nop"); // solves timing problem on Teensy 3.5
PIT_MCR = 1;
channel = KINETISK_PIT_CHANNELS;
while (1) {
if (channel->TCTRL == 0) break;
if (++channel >= KINETISK_PIT_CHANNELS + NUM_CHANNELS) {
channel = NULL;
return false;
}
}
}
int index = channel - KINETISK_PIT_CHANNELS;
funct_table[index] = funct;
channel->LDVAL = cycles;
channel->TCTRL = 3;
#if defined(KINETISK)
NVIC_SET_PRIORITY(IRQ_PIT_CH0 + index, nvic_priority);
NVIC_ENABLE_IRQ(IRQ_PIT_CH0 + index);
#elif defined(KINETISL)
nvic_priorites[index] = nvic_priority;
if (nvic_priorites[0] <= nvic_priorites[1]) {
NVIC_SET_PRIORITY(IRQ_PIT, nvic_priorites[0]);
} else {
NVIC_SET_PRIORITY(IRQ_PIT, nvic_priorites[1]);
}
NVIC_ENABLE_IRQ(IRQ_PIT);
#endif
#endif
return true;
}


void IntervalTimer::end() {
#if 0
if (channel) {
int index = channel - KINETISK_PIT_CHANNELS;
// TODO: disable IRQ_PIT, but only if both instances ended
funct_table[index] = dummy_funct;
channel->TCTRL = 0;
nvic_priorites[index] = 255;
if (nvic_priorites[0] <= nvic_priorites[1]) {
NVIC_SET_PRIORITY(IRQ_PIT, nvic_priorites[0]);
} else {
NVIC_SET_PRIORITY(IRQ_PIT, nvic_priorites[1]);
}
channel = 0;
}
#endif
}


void pit_isr() {
if (PIT_TFLG0) {
PIT_TFLG0 = 1;
funct_table[0]();
}
if (PIT_TFLG1) {
PIT_TFLG1 = 1;
funct_table[1]();
}
}

static void dummy_funct(void)
{
}


+ 135
- 0
teensy4/IntervalTimer.h View File

@@ -0,0 +1,135 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2018 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 __INTERVALTIMER_H__
#define __INTERVALTIMER_H__

#include <stddef.h>
#include "imxrt.h"

#ifdef __cplusplus
extern "C" {
#endif

class IntervalTimer {
private:
static const uint32_t MAX_PERIOD = UINT32_MAX / (24000000 / 1000000);
public:
IntervalTimer() {
channel = NULL;
nvic_priority = 128;
}
~IntervalTimer() {
end();
}
bool begin(void (*funct)(), unsigned int microseconds) {
if (microseconds == 0 || microseconds > MAX_PERIOD) return false;
uint32_t cycles = (24000000 / 1000000) * microseconds - 1;
if (cycles < 36) return false;
return beginCycles(funct, cycles);
}
bool begin(void (*funct)(), int microseconds) {
if (microseconds < 0) return false;
return begin(funct, (unsigned int)microseconds);
}
bool begin(void (*funct)(), unsigned long microseconds) {
return begin(funct, (unsigned int)microseconds);
}
bool begin(void (*funct)(), long microseconds) {
return begin(funct, (int)microseconds);
}
bool begin(void (*funct)(), float microseconds) {
if (microseconds <= 0 || microseconds > MAX_PERIOD) return false;
uint32_t cycles = (float)(24000000 / 1000000) * microseconds - 0.5;
if (cycles < 36) return false;
return beginCycles(funct, cycles);
}
bool begin(void (*funct)(), double microseconds) {
return begin(funct, (float)microseconds);
}
void update(unsigned int microseconds) {
if (microseconds == 0 || microseconds > MAX_PERIOD) return;
uint32_t cycles = (24000000 / 1000000) * microseconds - 1;
if (cycles < 36) return;
if (channel) channel->LDVAL = cycles;
}
void update(int microseconds) {
if (microseconds < 0) return;
return update((unsigned int)microseconds);
}
void update(unsigned long microseconds) {
return update((unsigned int)microseconds);
}
void update(long microseconds) {
return update((int)microseconds);
}
void update(float microseconds) {
if (microseconds <= 0 || microseconds > MAX_PERIOD) return;
uint32_t cycles = (float)(24000000 / 1000000) * microseconds - 0.5;
if (cycles < 36) return;
if (channel) channel->LDVAL = cycles;
}
void update(double microseconds) {
return update((float)microseconds);
}
void end();
void priority(uint8_t n) {
nvic_priority = n;
if (channel) {
int index = channel - IMXRT_PIT_CHANNELS;
nvic_priorites[index] = nvic_priority;
if (nvic_priorites[0] <= nvic_priorites[1]) {
NVIC_SET_PRIORITY(IRQ_PIT, nvic_priorites[0]);
} else {
NVIC_SET_PRIORITY(IRQ_PIT, nvic_priorites[1]);
}
}
}
operator IRQ_NUMBER_t() {
if (channel) {
return IRQ_PIT;
}
return (IRQ_NUMBER_t)NVIC_NUM_INTERRUPTS;
}
private:
//#define IMXRT_PIT_CHANNELS ((IMXRT_PIT_CHANNEL_t *)(&(IMXRT_PIT.offset100)))
IMXRT_PIT_CHANNEL_t *channel;
uint8_t nvic_priority;
static uint8_t nvic_priorites[4];
bool beginCycles(void (*funct)(), uint32_t cycles);

};


#ifdef __cplusplus
}
#endif

#endif

+ 38
- 0
teensy4/Makefile View File

@@ -0,0 +1,38 @@
CPUARCH = cortex-m7
DEFS = -DUSB_SERIAL -D__IMXRT1052__ -DTEENSYDUINO=145 -DARDUINO=10808 -DF_CPU=396000000 -DLAYOUT_US_ENGLISH
SECTIONS = -ffunction-sections -fdata-sections
CPPFLAGS = -Wall -g -O2 $(SECTIONS) -mcpu=$(CPUARCH) -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fsingle-precision-constant -I. $(DEFS)
CXXFLAGS = -std=gnu++14 -felide-constructors -fno-exceptions -fno-rtti
LDFLAGS = -Wl,--gc-sections,--print-gc-sections,--print-memory-usage --specs=nano.specs -nostdlib -nostartfiles -Timxrt.ld

C_FILES := $(wildcard *.c)
CPP_FILES := $(wildcard *.cpp)

OBJS := $(C_FILES:.c=.o) $(CPP_FILES:.cpp=.o)

ARDUINOPATH = /home/paul/teensy/arduino-1.8.8
COMPILERPATH = $(abspath $(ARDUINOPATH)/hardware/tools/arm/bin)
CC = $(COMPILERPATH)/arm-none-eabi-gcc
CXX = $(COMPILERPATH)/arm-none-eabi-g++
OBJCOPY = $(COMPILERPATH)/arm-none-eabi-objcopy
OBJDUMP = $(COMPILERPATH)/arm-none-eabi-objdump
SIZE = $(COMPILERPATH)/arm-none-eabi-size
AR = $(COMPILERPATH)/arm-none-eabi-gcc-ar

all: Blink.elf

Blink.elf: Blink.o core.a
$(CC) $(CPPFLAGS) $(LDFLAGS) -o $@ $^ -lm
#$(CC) $(CPPFLAGS) $(LDFLAGS) -o $@ Blink.o $(OBJS) -lm
$(OBJDUMP) -d -S -C $@ > Blink.lst
$(OBJDUMP) -t -C $@ > Blink.sym
$(OBJCOPY) -O ihex -R .eeprom $@ Blink.hex
$(SIZE) $@

core.a: $(OBJS)
$(AR) rcs core.a $(OBJS)


clean:
rm -f *.o *.d core.a *.elf *.lst *.sym *.hex


+ 132
- 0
teensy4/Print.h View File

@@ -0,0 +1,132 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2017 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 <stdarg.h>
#include "core_id.h"
#include "WString.h"
#include "Printable.h"

#define DEC 10
#define HEX 16
#define OCT 8
#define BIN 2

// BYTE was defined in very old versions of Arduino
// maybe this now causes more trouble than it's worth?
//#ifndef BYTE
//#define BYTE 0
//#endif

class __FlashStringHelper;

class Print
{
public:
constexpr 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);
virtual int availableForWrite(void) { return 0; }
virtual void flush() { }
size_t write(const char *buffer, size_t size) { return write((const uint8_t *)buffer, 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); }
int printf(const char *format, ...);
int printf(const __FlashStringHelper *format, ...);
protected:
void setWriteError(int err = 1) { write_error = err; }
private:
char write_error;
size_t printFloat(double n, uint8_t digits);
#ifdef __MKL26Z64__
size_t printNumberDec(unsigned long n, uint8_t sign);
size_t printNumberHex(unsigned long n);
size_t printNumberBin(unsigned long n);
size_t printNumberAny(unsigned long n, uint8_t base);
inline size_t printNumber(unsigned long n, uint8_t base, uint8_t sign) __attribute__((always_inline)) {
// when "base" is a constant (pretty much always), the
// compiler optimizes this to a single function call.
if (base == 0) return write((uint8_t)n);
if (base == 10 || base < 2) return printNumberDec(n, sign);
if (base == 16) return printNumberHex(n);
if (base == 2) return printNumberBin(n);
return printNumberAny(n, base);
}
#else
size_t printNumber(unsigned long n, uint8_t base, uint8_t sign);
#endif
};


#endif

+ 42
- 0
teensy4/Printable.h View File

@@ -0,0 +1,42 @@
/*
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 "new.h"

class Print;

/** The Printable class provides a way for new classes to allow themselves to be printed.
By deriving from Printable and implementing the printTo method, it will then be possible
for users to print out instances of this class by passing them into the usual
Print::print and Print::println methods.
*/
class Printable
{
public:
virtual size_t printTo(Print& p) const = 0;
};


#endif
#endif

+ 33
- 0
teensy4/Server.h View File

@@ -0,0 +1,33 @@
/*
Server.h - Base class that provides Server
Copyright (c) 2011 Adrian McEwen. All right reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#if ARDUINO >= 100

#ifndef server_h
#define server_h

#include "Print.h"

class Server : public Print {
public:
virtual void begin() =0;
};

#endif
#endif

+ 73
- 0
teensy4/Stream.h View File

@@ -0,0 +1,73 @@
/*
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:
constexpr Stream() : _timeout(1000), read_error(0) {}
virtual int available() = 0;
virtual int read() = 0;
virtual int peek() = 0;

void setTimeout(unsigned long timeout);
bool find(const char *target);
bool find(const uint8_t *target) { return find ((const char *)target); }
bool find(const String &target) { return find(target.c_str()); }
bool find(const char *target, size_t length);
bool find(const uint8_t *target, size_t length) { return find ((const char *)target, length); }
bool find(const String &target, size_t length) { return find(target.c_str(), length); }
bool findUntil(const char *target, const char *terminator);
bool findUntil(const uint8_t *target, const char *terminator) { return findUntil((const char *)target, terminator); }
bool findUntil(const String &target, const char *terminator) { return findUntil(target.c_str(), terminator); }
bool findUntil(const char *target, const String &terminator) { return findUntil(target, terminator.c_str()); }
bool findUntil(const String &target, const String &terminator) { return findUntil(target.c_str(), terminator.c_str()); }
bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen);
bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) {return findUntil((const char *)target, targetLen, terminate, termLen); }
bool findUntil(const String &target, size_t targetLen, const char *terminate, size_t termLen);
bool findUntil(const char *target, size_t targetLen, const String &terminate, size_t termLen);
bool findUntil(const String &target, size_t targetLen, const String &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 readBytes(uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
size_t readBytesUntil(char terminator, char *buffer, size_t length);
size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, 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

+ 92
- 0
teensy4/Udp.h View File

@@ -0,0 +1,92 @@
/*
* 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 uint8_t beginMulticast(IPAddress, uint16_t) { return 0; }
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

+ 168
- 0
teensy4/WCharacter.h View File

@@ -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

+ 106
- 0
teensy4/WProgram.h View File

@@ -0,0 +1,106 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2017 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 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))
#define FASTRUN __attribute__ ((section(".fastrun"), noinline, noclone ))

#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 "usb_mtp.h"
//#include "usb_audio.h"
//#include "usb_touch.h"
//#include "usb_undef.h" // do not allow usb_desc.h stuff to leak to user programs

#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
int32_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(unsigned int newseed);

#include "pins_arduino.h"

#endif // __cplusplus


// Fast memcpy
#if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
#ifdef __cplusplus
extern "C" {
extern void *memcpy (void *dst, const void *src, size_t count);
}
#else
extern void *memcpy (void *dst, const void *src, size_t count);
#endif
#endif


#endif // WProgram_h

+ 227
- 0
teensy4/WString.h View File

@@ -0,0 +1,227 @@
/*
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"

// Not needed here, but some libs assume WString.h or Print.h
// gives them PROGMEM and other AVR stuff.
#include "avr/pgmspace.h"

// When compiling programs with this class, the following gcc parameters
// dramatically increase performance and memory (RAM) efficiency, typically
// with little or no increase in code size.
// -felide-constructors
// -std=c++0x

// Brian Cook's "no overhead" Flash String type (message on Dec 14, 2010)
// modified by Mikal Hart for his FlashString library
class __FlashStringHelper;
#ifndef F
#define F(string_literal) ((const __FlashStringHelper *)(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);
#if __cplusplus >= 201103L || defined(__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);
#if __cplusplus >= 201103L || defined(__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);
private:
// allow for "if (s)" without the complications of an operator bool().
// for more information http://www.artima.com/cppsource/safebool.html
typedef void (String::*StringIfHelperType)() const;
void StringIfHelper() const {}
public:
operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; }
};

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

+ 1
- 0
teensy4/avr/interrupt.h View File

@@ -0,0 +1 @@
// This header file is in the public domain.

+ 23
- 0
teensy4/avr/io.h View File

@@ -0,0 +1,23 @@
/* Simple compatibility headers for AVR code used with ARM chips
* Copyright (c) 2015 Paul Stoffregen <paul@pjrc.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 "../avr_emulation.h"

+ 131
- 0
teensy4/avr/pgmspace.h View File

@@ -0,0 +1,131 @@
/* Simple compatibility headers for AVR code used with NXP IMXRT chips
* Copyright (c) 2018 Paul Stoffregen <paul@pjrc.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 __PGMSPACE_H_
#define __PGMSPACE_H_ 1

#include <inttypes.h>

#define PROGMEM __attribute__((section(".progmem")))
#define PGM_P const char *
#define PSTR(str) ({static const char data[] PROGMEM = (str); &data[0];})

#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;
typedef int64_t prog_int64_t;
typedef uint64_t prog_uint64_t;

#define memchr_P(str, c, len) memchr((str), (c), (len))
#define memcmp_P(a, b, n) memcmp((a), (b), (n))
#define memcpy_P(dest, src, num) memcpy((dest), (src), (num))
#define memmem_P(a, alen, b, blen) memmem((a), (alen), (b), (blen))
#define memrchr_P(str, val, len) memrchr((str), (val), (len))
#define strcat_P(dest, src) strcat((dest), (src))
#define strchr_P(str, c) strchr((str), (c))
#define strchrnul_P(str, c) strchrnul((str), (c))
#define strcmp_P(a, b) strcmp((a), (b))
#define strcpy_P(dest, src) strcpy((dest), (src))
#define strcasecmp_P(a, b) strcasecmp((a), (b))
#define strcasestr_P(a, b) strcasestr((a), (b))
#define strlcat_P(dest, src, len) strlcat((dest), (src), (len))
#define strlcpy_P(dest, src, len) strlcpy((dest), (src), (len))
#define strlen_P(s) strlen((const char *)(s))
#define strnlen_P(str, len) strnlen((str), (len))
#define strncmp_P(a, b, n) strncmp((a), (b), (n))
#define strncasecmp_P(a, b, n) strncasecmp((a), (b), (n))
#define strncat_P(a, b, n) strncat((a), (b), (n))
#define strncpy_P(a, b, n) strncpy((a), (b), (n))
#define strpbrk_P(str, chrs) strpbrk((str), (chrs))
#define strrchr_P(str, c) strrchr((str), (c))
#define strsep_P(strp, delim) strsep((strp), (delim))
#define strspn_P(str, chrs) strspn((str), (chrs))
#define strstr_P(a, b) strstr((a), (b))
#define sprintf_P(s, ...) sprintf((s), __VA_ARGS__)
#define vfprintf_P(fp, s, ...) vfprintf((fp), (s), __VA_ARGS__)
#define printf_P(...) printf(__VA_ARGS__)
#define snprintf_P(s, n, ...) snprintf((s), (n), __VA_ARGS__)
#define vsprintf_P(s, ...) vsprintf((s), __VA_ARGS__)
#define vsnprintf_P(s, n, ...) vsnprintf((s), (n), __VA_ARGS__)
#define fprintf_P(fp, ...) fprintf((fp), __VA_ARGS__)
#define strlen_PF(a) strlen((a))
#define strnlen_PF(src, len) strnlen((src), (len))
#define memcpy_PF(dest, src, len) memcpy((dest), (src), (len))
#define strcpy_PF(dest, src) strcpy((dest), (src))
#define strncpy_PF(dest, src, len) strncpy((dest), (src), (len))
#define strcat_PF(dest, src) strcat((dest), (src))
#define strlcat_PF(dest, src, len) strlcat((dest), (src), (len))
#define strncat_PF(dest, src, len) strncat((dest), (src), (len))
#define strcmp_PF(s1, s2) strcmp((s1), (s2))
#define strncmp_PF(s1, s2, n) strncmp((s1), (s2), (n))
#define strcasecmp_PF(s1, s2) strcasecmp((s1), (s2))
#define strncasecmp_PF(s1, s2, n) strncasecmp((s1), (s2), (n))
#define strstr_PF(s1, s2) strstr((s1), (s2))
#define strlcpy_PF(dest, src, n) strlcpy((dest), (src), (n))
#define memcmp_PF(s1, s2, n) memcmp((s1), (s2), (n))


#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#if 0
#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))
#else
#define pgm_read_word(addr) ({ \
typeof(addr) _addr = (addr); \
*(const unsigned short *)(_addr); \
})
#define pgm_read_dword(addr) ({ \
typeof(addr) _addr = (addr); \
*(const unsigned long *)(_addr); \
})
#define pgm_read_float(addr) ({ \
typeof(addr) _addr = (addr); \
*(const float *)(_addr); \
})
#define pgm_read_ptr(addr) ({ \
typeof(addr) _addr = (addr); \
*(void * const *)(_addr); \
})
#endif


#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_ptr_near(addr) pgm_read_ptr(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)
#define pgm_read_ptr_far(addr) pgm_read_ptr(addr)

#endif

+ 26
- 0
teensy4/avr/power.h View File

@@ -0,0 +1,26 @@
/* Simple compatibility headers for AVR code used with ARM chips
* Copyright (c) 2015 Paul Stoffregen <paul@pjrc.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 _AVR_POWER_H_
#define _AVR_POWER_H_ 1

#endif

+ 46
- 0
teensy4/avr/sleep.h View File

@@ -0,0 +1,46 @@
/* Simple compatibility headers for AVR code used with ARM chips
* Copyright (c) 2015 Paul Stoffregen <paul@pjrc.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 _AVR_SLEEP_H_
#define _AVR_SLEEP_H_ 1

#define SLEEP_MODE_IDLE 0
#define SLEEP_MODE_ADC 0
#define SLEEP_MODE_PWR_DOWN 1
#define SLEEP_MODE_PWR_SAVE 1
#define SLEEP_MODE_STANDBY 1
#define SLEEP_MODE_EXT_STANDBY 1

#define set_sleep_mode(mode) // TODO: actually set the mode...
#define sleep_enable()
#define sleep_disable()
#define sleep_cpu() ({__asm__ volatile("wfi");})
#define sleep_bod_disable()
#define sleep_mode() ({__asm__ volatile("wfi");})

// workaround for early versions of Nordic's BLE library
// EIMSK moved to a dummy byte in avr_emulation...
//#if defined(HAL_ACI_TL_H__) && defined(PLATFORM_H__)
//#define EIMSK uint8_t EIMSKworkaround=0; EIMSKworkaround
//#endif

#endif

+ 21
- 0
teensy4/avr/wdt.h View File

@@ -0,0 +1,21 @@
// This header file is in the public domain.

#ifndef _AVR_WDT_H_
#define _AVR_WDT_H_

#define WDTO_15MS 0
#define WDTO_30MS 1
#define WDTO_60MS 2
#define WDTO_120MS 3
#define WDTO_250MS 4
#define WDTO_500MS 5
#define WDTO_1S 6
#define WDTO_2S 7
#define WDTO_4S 8
#define WDTO_8S 9

#define wdt_reset()
#define wdt_enable(timeout)
#define wdt_disable()

#endif

+ 0
- 0
teensy4/avr_emulation.h View File


+ 113
- 0
teensy4/avr_functions.h View File

@@ -0,0 +1,113 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2017 PJRC.COM, LLC.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* 1. The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 2. If the Software is incorporated into a build system that allows
* selection among a list of target devices, then similar target
* devices manufactured by PJRC.COM must be included in the list of
* target devices and selectable in the same manner.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#ifndef _avr_functions_h_
#define _avr_functions_h_

#include <inttypes.h>

#ifdef __cplusplus
extern "C" {
#endif

void eeprom_initialize(void);
uint8_t eeprom_read_byte(const uint8_t *addr) __attribute__ ((pure));
uint16_t eeprom_read_word(const uint16_t *addr) __attribute__ ((pure));
uint32_t eeprom_read_dword(const uint32_t *addr) __attribute__ ((pure));
void eeprom_read_block(void *buf, const void *addr, uint32_t len);
void eeprom_write_byte(uint8_t *addr, uint8_t value);
void eeprom_write_word(uint16_t *addr, uint16_t value);
void eeprom_write_dword(uint32_t *addr, uint32_t value);
void eeprom_write_block(const void *buf, void *addr, uint32_t len);
int eeprom_is_ready(void);
#define eeprom_busy_wait() do {} while (!eeprom_is_ready())

/*
static inline float eeprom_read_float(const float *addr) __attribute__((pure, always_inline, unused));
static inline float eeprom_read_float(const float *addr)
{
union {float f; uint32_t u32;} u;
u.u32 = eeprom_read_dword((const uint32_t *)addr);
return u.f;
}
static inline void eeprom_write_float(float *addr, float value) __attribute__((always_inline, unused));
static inline void eeprom_write_float(float *addr, float value)
{
union {float f; uint32_t u32;} u;
u.f = value;
eeprom_write_dword((uint32_t *)addr, u.u32);
}
static inline void eeprom_update_byte(uint8_t *addr, uint8_t value) __attribute__((always_inline, unused));
static inline void eeprom_update_byte(uint8_t *addr, uint8_t value)
{
eeprom_write_byte(addr, value);
}
static inline void eeprom_update_word(uint16_t *addr, uint16_t value) __attribute__((always_inline, unused));
static inline void eeprom_update_word(uint16_t *addr, uint16_t value)
{
eeprom_write_word(addr, value);
}
static inline void eeprom_update_dword(uint32_t *addr, uint32_t value) __attribute__((always_inline, unused));
static inline void eeprom_update_dword(uint32_t *addr, uint32_t value)
{
eeprom_write_dword(addr, value);
}
static inline void eeprom_update_float(float *addr, float value) __attribute__((always_inline, unused));
static inline void eeprom_update_float(float *addr, float value)
{
union {float f; uint32_t u32;} u;
u.f = value;
eeprom_write_dword((uint32_t *)addr, u.u32);
}
static inline void eeprom_update_block(const void *buf, void *addr, uint32_t len) __attribute__((always_inline, unused));
static inline void eeprom_update_block(const void *buf, void *addr, uint32_t len)
{
eeprom_write_block(buf, addr, len);
}
*/


char * ultoa(unsigned long val, char *buf, int radix);
char * ltoa(long val, char *buf, int radix);

#if defined(_NEWLIB_VERSION) && (__NEWLIB__ < 2 || __NEWLIB__ == 2 && __NEWLIB_MINOR__ < 2)
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); }
#endif

char * dtostrf(float val, int width, unsigned int precision, char *buf);


#ifdef __cplusplus
}
#endif
#endif

+ 517
- 0
teensy4/binary.h View File

@@ -0,0 +1,517 @@
// This header file is in the public domain.

#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

+ 202
- 0
teensy4/bootdata.c View File

@@ -0,0 +1,202 @@
//#include "imxrt.h"

#include <stdint.h>

extern void ResetHandler(void);
extern unsigned long _estack;
extern unsigned long _flashimagelen;

__attribute__ ((section(".vectors"), used))
const uint32_t vector_table[2] = {
(uint32_t)&_estack,
(uint32_t)&ResetHandler
};


__attribute__ ((section(".bootdata"), used))
const uint32_t BootData[3] = {
0x60000000,
(uint32_t)&_flashimagelen,
0
};


__attribute__ ((section(".ivt"), used))
const uint32_t ImageVectorTable[8] = {
0x402000D1, // header
(uint32_t)vector_table, // docs are wrong, needs to be vec table, not start addr
0, // reserved
0, // dcd
(uint32_t)BootData, // abs address of boot data
(uint32_t)ImageVectorTable, // self
0, // command sequence file
0 // reserved
};

__attribute__ ((section(".flashconfig"), used))
uint32_t FlexSPI_NOR_Config[128] = {
// 448 byte common FlexSPI configuration block , 8.6.3 page 342
// MCU_Flashloader_Reference_Manual.pdf, 8.2.1, Table 8-2, page 72-75
0x42464346, // Tag 0x00
0x56010000, // Version
0, // reserved
0x00030301, // columnAdressWidth,dataSetupTime,dataHoldTime,readSampleClkSrc

0x00000000, // waitTimeCfgCommands,-,deviceModeCfgEnable
0, // deviceModeSeq
0, // deviceModeArg
0x00000000, // -,-,-,configCmdEnable

0, // configCmdSeqs 0x20
0,
0,
0,

0, // cfgCmdArgs 0x30
0,
0,
0,

0x00000000, // controllerMiscOption 0x40
0x00060401, // lutCustomSeqEnable,serialClkFreq,sflashPadType,deviceType
0, // reserved
0, // reserved

0x00200000, // sflashA1Size 0x50
0, // sflashA2Size
0, // sflashB1Size
0, // sflashB2Size

0, // csPadSettingOverride 0x60
0, // sclkPadSettingOverride
0, // dataPadSettingOverride
0, // dqsPadSettingOverride

0, // timeoutInMs 0x70
0, // commandInterval
0, // dataValidTime
0x00000000, // busyBitPolarity,busyOffset

0x0A1804EB, // lookupTable[0] 0x80
0x26043206, // lookupTable[1]
0, // lookupTable[2]
0, // lookupTable[3]

0x24040405, // lookupTable[4] 0x90
0, // lookupTable[5]
0, // lookupTable[6]
0, // lookupTable[7]

0, // lookupTable[8] 0xA0
0, // lookupTable[9]
0, // lookupTable[10]
0, // lookupTable[11]

0x00000406, // lookupTable[12] 0xB0
0, // lookupTable[13]
0, // lookupTable[14]
0, // lookupTable[15]

0, // lookupTable[16] 0xC0
0, // lookupTable[17]
0, // lookupTable[18]
0, // lookupTable[19]

0x08180420, // lookupTable[20] 0xD0
0, // lookupTable[21]
0, // lookupTable[22]
0, // lookupTable[23]

0, // lookupTable[24] 0xE0
0, // lookupTable[25]
0, // lookupTable[26]
0, // lookupTable[27]

0, // lookupTable[28] 0xF0
0, // lookupTable[29]
0, // lookupTable[30]
0, // lookupTable[31]

0x081804D8, // lookupTable[32] 0x100
0, // lookupTable[33]
0, // lookupTable[34]
0, // lookupTable[35]

0x08180402, // lookupTable[36] 0x110
0x00002004, // lookupTable[37]
0, // lookupTable[38]
0, // lookupTable[39]

0, // lookupTable[40] 0x120
0, // lookupTable[41]
0, // lookupTable[42]
0, // lookupTable[43]

0x00000460, // lookupTable[44] 0x130
0, // lookupTable[45]
0, // lookupTable[46]
0, // lookupTable[47]

0, // lookupTable[48] 0x140
0, // lookupTable[49]
0, // lookupTable[50]
0, // lookupTable[51]

0, // lookupTable[52] 0x150
0, // lookupTable[53]
0, // lookupTable[54]
0, // lookupTable[55]

0, // lookupTable[56] 0x160
0, // lookupTable[57]
0, // lookupTable[58]
0, // lookupTable[59]

0, // lookupTable[60] 0x170
0, // lookupTable[61]
0, // lookupTable[62]
0, // lookupTable[63]

0, // LUT 0: Read 0x180
0, // LUT 1: ReadStatus
0, // LUT 3: WriteEnable
0, // LUT 5: EraseSector

0, // LUT 9: PageProgram 0x190
0, // LUT 11: ChipErase
0, // LUT 15: Dummy
0, // LUT unused?

0, // LUT unused? 0x1A0
0, // LUT unused?
0, // LUT unused?
0, // LUT unused?

0, // reserved 0x1B0
0, // reserved
0, // reserved
0, // reserved

// 64 byte Serial NOR configuration block, 8.6.3.2, page 346

256, // pageSize 0x1C0
4096, // sectorSize
1, // ipCmdSerialClkFreq
0, // reserved

0x00010000, // block size 0x1D0
0, // reserved
0, // reserved
0, // reserved

0, // reserved 0x1E0
0, // reserved
0, // reserved
0, // reserved

0, // reserved 0x1F0
0, // reserved
0, // reserved
0 // reserved
};


+ 5
- 0
teensy4/core_id.h View File

@@ -0,0 +1,5 @@
// This header file is in the public domain.

#ifndef CORE_TEENSY
#define CORE_TEENSY
#endif

+ 722
- 0
teensy4/core_pins.h View File

@@ -0,0 +1,722 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2018 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.
*/

#pragma once
#include "imxrt.h"
#include "pins_arduino.h"

#define HIGH 1
#define LOW 0
#define INPUT 0
#define OUTPUT 1
#define INPUT_PULLUP 2
#define INPUT_PULLDOWN 3
#define OUTPUT_OPENDRAIN 4
#define INPUT_DISABLE 5
#define LSBFIRST 0
#define MSBFIRST 1
#define _BV(n) (1<<(n))
#define CHANGE 4
#define FALLING 2
#define RISING 3

#define CORE_NUM_TOTAL_PINS 34
#define CORE_NUM_DIGITAL 34
#define CORE_NUM_INTERRUPT 34
#define CORE_NUM_ANALOG 14
#define CORE_NUM_PWM 27

#define CORE_PIN0_BIT 3
#define CORE_PIN1_BIT 2
#define CORE_PIN2_BIT 4
#define CORE_PIN3_BIT 5
#define CORE_PIN4_BIT 6
#define CORE_PIN5_BIT 7
#define CORE_PIN6_BIT 17
#define CORE_PIN7_BIT 16
#define CORE_PIN8_BIT 10
#define CORE_PIN9_BIT 11
#define CORE_PIN10_BIT 0
#define CORE_PIN11_BIT 2
#define CORE_PIN12_BIT 1
#define CORE_PIN13_BIT 3
#define CORE_PIN14_BIT 18
#define CORE_PIN15_BIT 19
#define CORE_PIN16_BIT 23
#define CORE_PIN17_BIT 22
#define CORE_PIN18_BIT 17
#define CORE_PIN19_BIT 16
#define CORE_PIN20_BIT 26
#define CORE_PIN21_BIT 27
#define CORE_PIN22_BIT 24
#define CORE_PIN23_BIT 25
#define CORE_PIN24_BIT 12
#define CORE_PIN25_BIT 13
#define CORE_PIN26_BIT 30
#define CORE_PIN27_BIT 31
#define CORE_PIN28_BIT 18
#define CORE_PIN29_BIT 31
#define CORE_PIN30_BIT 24
#define CORE_PIN31_BIT 23
#define CORE_PIN32_BIT 12
#define CORE_PIN33_BIT 8

#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 GPIO1_DR
#define CORE_PIN1_PORTREG GPIO1_DR
#define CORE_PIN2_PORTREG GPIO4_DR
#define CORE_PIN3_PORTREG GPIO4_DR
#define CORE_PIN4_PORTREG GPIO4_DR
#define CORE_PIN5_PORTREG GPIO4_DR
#define CORE_PIN6_PORTREG GPIO2_DR
#define CORE_PIN7_PORTREG GPIO2_DR
#define CORE_PIN8_PORTREG GPIO2_DR
#define CORE_PIN9_PORTREG GPIO2_DR
#define CORE_PIN10_PORTREG GPIO2_DR
#define CORE_PIN11_PORTREG GPIO2_DR
#define CORE_PIN12_PORTREG GPIO2_DR
#define CORE_PIN13_PORTREG GPIO2_DR
#define CORE_PIN14_PORTREG GPIO1_DR
#define CORE_PIN15_PORTREG GPIO1_DR
#define CORE_PIN16_PORTREG GPIO1_DR
#define CORE_PIN17_PORTREG GPIO1_DR
#define CORE_PIN18_PORTREG GPIO1_DR
#define CORE_PIN19_PORTREG GPIO1_DR
#define CORE_PIN20_PORTREG GPIO1_DR
#define CORE_PIN21_PORTREG GPIO1_DR
#define CORE_PIN22_PORTREG GPIO1_DR
#define CORE_PIN23_PORTREG GPIO1_DR
#define CORE_PIN24_PORTREG GPIO1_DR
#define CORE_PIN25_PORTREG GPIO1_DR
#define CORE_PIN26_PORTREG GPIO1_DR
#define CORE_PIN27_PORTREG GPIO1_DR
#define CORE_PIN28_PORTREG GPIO3_DR
#define CORE_PIN29_PORTREG GPIO4_DR
#define CORE_PIN30_PORTREG GPIO4_DR
#define CORE_PIN31_PORTREG GPIO4_DR
#define CORE_PIN32_PORTREG GPIO2_DR
#define CORE_PIN33_PORTREG GPIO4_DR

#define CORE_PIN0_PORTSET GPIO1_DR_SET
#define CORE_PIN1_PORTSET GPIO1_DR_SET
#define CORE_PIN2_PORTSET GPIO4_DR_SET
#define CORE_PIN3_PORTSET GPIO4_DR_SET
#define CORE_PIN4_PORTSET GPIO4_DR_SET
#define CORE_PIN5_PORTSET GPIO4_DR_SET
#define CORE_PIN6_PORTSET GPIO2_DR_SET
#define CORE_PIN7_PORTSET GPIO2_DR_SET
#define CORE_PIN8_PORTSET GPIO2_DR_SET
#define CORE_PIN9_PORTSET GPIO2_DR_SET
#define CORE_PIN10_PORTSET GPIO2_DR_SET
#define CORE_PIN11_PORTSET GPIO2_DR_SET
#define CORE_PIN12_PORTSET GPIO2_DR_SET
#define CORE_PIN13_PORTSET GPIO2_DR_SET
#define CORE_PIN14_PORTSET GPIO1_DR_SET
#define CORE_PIN15_PORTSET GPIO1_DR_SET
#define CORE_PIN16_PORTSET GPIO1_DR_SET
#define CORE_PIN17_PORTSET GPIO1_DR_SET
#define CORE_PIN18_PORTSET GPIO1_DR_SET
#define CORE_PIN19_PORTSET GPIO1_DR_SET
#define CORE_PIN20_PORTSET GPIO1_DR_SET
#define CORE_PIN21_PORTSET GPIO1_DR_SET
#define CORE_PIN22_PORTSET GPIO1_DR_SET
#define CORE_PIN23_PORTSET GPIO1_DR_SET
#define CORE_PIN24_PORTSET GPIO1_DR_SET
#define CORE_PIN25_PORTSET GPIO1_DR_SET
#define CORE_PIN26_PORTSET GPIO1_DR_SET
#define CORE_PIN27_PORTSET GPIO1_DR_SET
#define CORE_PIN28_PORTSET GPIO3_DR_SET
#define CORE_PIN29_PORTSET GPIO4_DR_SET
#define CORE_PIN30_PORTSET GPIO4_DR_SET
#define CORE_PIN31_PORTSET GPIO4_DR_SET
#define CORE_PIN32_PORTSET GPIO2_DR_SET
#define CORE_PIN33_PORTSET GPIO4_DR_SET

#define CORE_PIN0_PORTCLEAR GPIO1_DR_CLEAR
#define CORE_PIN1_PORTCLEAR GPIO1_DR_CLEAR
#define CORE_PIN2_PORTCLEAR GPIO4_DR_CLEAR
#define CORE_PIN3_PORTCLEAR GPIO4_DR_CLEAR
#define CORE_PIN4_PORTCLEAR GPIO4_DR_CLEAR
#define CORE_PIN5_PORTCLEAR GPIO4_DR_CLEAR
#define CORE_PIN6_PORTCLEAR GPIO2_DR_CLEAR
#define CORE_PIN7_PORTCLEAR GPIO2_DR_CLEAR
#define CORE_PIN8_PORTCLEAR GPIO2_DR_CLEAR
#define CORE_PIN9_PORTCLEAR GPIO2_DR_CLEAR
#define CORE_PIN10_PORTCLEAR GPIO2_DR_CLEAR
#define CORE_PIN11_PORTCLEAR GPIO2_DR_CLEAR
#define CORE_PIN12_PORTCLEAR GPIO2_DR_CLEAR
#define CORE_PIN13_PORTCLEAR GPIO2_DR_CLEAR
#define CORE_PIN14_PORTCLEAR GPIO1_DR_CLEAR
#define CORE_PIN15_PORTCLEAR GPIO1_DR_CLEAR
#define CORE_PIN16_PORTCLEAR GPIO1_DR_CLEAR
#define CORE_PIN17_PORTCLEAR GPIO1_DR_CLEAR
#define CORE_PIN18_PORTCLEAR GPIO1_DR_CLEAR
#define CORE_PIN19_PORTCLEAR GPIO1_DR_CLEAR
#define CORE_PIN20_PORTCLEAR GPIO1_DR_CLEAR
#define CORE_PIN21_PORTCLEAR GPIO1_DR_CLEAR
#define CORE_PIN22_PORTCLEAR GPIO1_DR_CLEAR
#define CORE_PIN23_PORTCLEAR GPIO1_DR_CLEAR
#define CORE_PIN24_PORTCLEAR GPIO1_DR_CLEAR
#define CORE_PIN25_PORTCLEAR GPIO1_DR_CLEAR
#define CORE_PIN26_PORTCLEAR GPIO1_DR_CLEAR
#define CORE_PIN27_PORTCLEAR GPIO1_DR_CLEAR
#define CORE_PIN28_PORTCLEAR GPIO3_DR_CLEAR
#define CORE_PIN29_PORTCLEAR GPIO4_DR_CLEAR
#define CORE_PIN30_PORTCLEAR GPIO4_DR_CLEAR
#define CORE_PIN31_PORTCLEAR GPIO4_DR_CLEAR
#define CORE_PIN32_PORTCLEAR GPIO2_DR_CLEAR
#define CORE_PIN33_PORTCLEAR GPIO4_DR_CLEAR

#define CORE_PIN0_DDRREG GPIO1_GDIR
#define CORE_PIN1_DDRREG GPIO1_GDIR
#define CORE_PIN2_DDRREG GPIO4_GDIR
#define CORE_PIN3_DDRREG GPIO4_GDIR
#define CORE_PIN4_DDRREG GPIO4_GDIR
#define CORE_PIN5_DDRREG GPIO4_GDIR
#define CORE_PIN6_DDRREG GPIO2_GDIR
#define CORE_PIN7_DDRREG GPIO2_GDIR
#define CORE_PIN8_DDRREG GPIO2_GDIR
#define CORE_PIN9_DDRREG GPIO2_GDIR
#define CORE_PIN10_DDRREG GPIO2_GDIR
#define CORE_PIN11_DDRREG GPIO2_GDIR
#define CORE_PIN12_DDRREG GPIO2_GDIR
#define CORE_PIN13_DDRREG GPIO2_GDIR
#define CORE_PIN14_DDRREG GPIO1_GDIR
#define CORE_PIN15_DDRREG GPIO1_GDIR
#define CORE_PIN16_DDRREG GPIO1_GDIR
#define CORE_PIN17_DDRREG GPIO1_GDIR
#define CORE_PIN18_DDRREG GPIO1_GDIR
#define CORE_PIN19_DDRREG GPIO1_GDIR
#define CORE_PIN20_DDRREG GPIO1_GDIR
#define CORE_PIN21_DDRREG GPIO1_GDIR
#define CORE_PIN22_DDRREG GPIO1_GDIR
#define CORE_PIN23_DDRREG GPIO1_GDIR
#define CORE_PIN24_DDRREG GPIO1_GDIR
#define CORE_PIN25_DDRREG GPIO1_GDIR
#define CORE_PIN26_DDRREG GPIO1_GDIR
#define CORE_PIN27_DDRREG GPIO1_GDIR
#define CORE_PIN28_DDRREG GPIO3_GDIR
#define CORE_PIN29_DDRREG GPIO4_GDIR
#define CORE_PIN30_DDRREG GPIO4_GDIR
#define CORE_PIN31_DDRREG GPIO4_GDIR
#define CORE_PIN32_DDRREG GPIO2_GDIR
#define CORE_PIN33_DDRREG GPIO4_GDIR

#define CORE_PIN0_PINREG GPIO1_PSR
#define CORE_PIN1_PINREG GPIO1_PSR
#define CORE_PIN2_PINREG GPIO4_PSR
#define CORE_PIN3_PINREG GPIO4_PSR
#define CORE_PIN4_PINREG GPIO4_PSR
#define CORE_PIN5_PINREG GPIO4_PSR
#define CORE_PIN6_PINREG GPIO2_PSR
#define CORE_PIN7_PINREG GPIO2_PSR
#define CORE_PIN8_PINREG GPIO2_PSR
#define CORE_PIN9_PINREG GPIO2_PSR
#define CORE_PIN10_PINREG GPIO2_PSR
#define CORE_PIN11_PINREG GPIO2_PSR
#define CORE_PIN12_PINREG GPIO2_PSR
#define CORE_PIN13_PINREG GPIO2_PSR
#define CORE_PIN14_PINREG GPIO1_PSR
#define CORE_PIN15_PINREG GPIO1_PSR
#define CORE_PIN16_PINREG GPIO1_PSR
#define CORE_PIN17_PINREG GPIO1_PSR
#define CORE_PIN18_PINREG GPIO1_PSR
#define CORE_PIN19_PINREG GPIO1_PSR
#define CORE_PIN20_PINREG GPIO1_PSR
#define CORE_PIN21_PINREG GPIO1_PSR
#define CORE_PIN22_PINREG GPIO1_PSR
#define CORE_PIN23_PINREG GPIO1_PSR
#define CORE_PIN24_PINREG GPIO1_PSR
#define CORE_PIN25_PINREG GPIO1_PSR
#define CORE_PIN26_PINREG GPIO1_PSR
#define CORE_PIN27_PINREG GPIO1_PSR
#define CORE_PIN28_PINREG GPIO3_PSR
#define CORE_PIN29_PINREG GPIO4_PSR
#define CORE_PIN30_PINREG GPIO4_PSR
#define CORE_PIN31_PINREG GPIO4_PSR
#define CORE_PIN32_PINREG GPIO2_PSR
#define CORE_PIN33_PINREG GPIO4_PSR

// mux config registers control which peripheral uses the pin
#define CORE_PIN0_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_02
#define CORE_PIN1_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_03
#define CORE_PIN2_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_04
#define CORE_PIN3_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_05
#define CORE_PIN4_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_06
#define CORE_PIN5_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_07
#define CORE_PIN6_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_01
#define CORE_PIN7_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00
#define CORE_PIN8_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_10
#define CORE_PIN9_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_11
#define CORE_PIN10_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_00
#define CORE_PIN11_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_02
#define CORE_PIN12_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_01
#define CORE_PIN13_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03
#define CORE_PIN14_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_02
#define CORE_PIN15_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_03
#define CORE_PIN16_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_07
#define CORE_PIN17_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_06
#define CORE_PIN18_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_01
#define CORE_PIN19_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_00
#define CORE_PIN20_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_10
#define CORE_PIN21_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_11
#define CORE_PIN22_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_08
#define CORE_PIN23_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_09
#define CORE_PIN24_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_12
#define CORE_PIN25_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_13
#define CORE_PIN26_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_14
#define CORE_PIN27_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_15
#define CORE_PIN28_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_32
#define CORE_PIN29_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_31
#define CORE_PIN30_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_24
#define CORE_PIN31_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_23
#define CORE_PIN32_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_12
#define CORE_PIN33_CONFIG IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_08

// pad config registers control pullup/pulldown/keeper, drive strength, etc
#define CORE_PIN0_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_02
#define CORE_PIN1_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_03
#define CORE_PIN2_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_04
#define CORE_PIN3_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_05
#define CORE_PIN4_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_06
#define CORE_PIN5_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_07
#define CORE_PIN6_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_B1_01
#define CORE_PIN7_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_B1_00
#define CORE_PIN8_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_10
#define CORE_PIN9_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_11
#define CORE_PIN10_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_00
#define CORE_PIN11_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_02
#define CORE_PIN12_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_01
#define CORE_PIN13_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_03
#define CORE_PIN14_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_02
#define CORE_PIN15_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_03
#define CORE_PIN16_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_07
#define CORE_PIN17_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_06
#define CORE_PIN18_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_01
#define CORE_PIN19_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_00
#define CORE_PIN20_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_10
#define CORE_PIN21_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_11
#define CORE_PIN22_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_08
#define CORE_PIN23_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_09
#define CORE_PIN24_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_12
#define CORE_PIN25_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_13
#define CORE_PIN26_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_14
#define CORE_PIN27_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_15
#define CORE_PIN28_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_32
#define CORE_PIN29_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_31
#define CORE_PIN30_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_24
#define CORE_PIN31_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_23
#define CORE_PIN32_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_12
#define CORE_PIN33_PADCONFIG IOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_08




#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 {
*portClearRegister(pin) = digitalPinToBitMask(pin);
}
}

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) & digitalPinToBitMask(pin)) ? 1 : 0;
}
}


void pinMode(uint8_t pin, uint8_t mode);
void init_pins(void);
void analogWrite(uint8_t pin, int val);
uint32_t analogWriteRes(uint32_t bits);
static inline uint32_t analogWriteResolution(uint32_t bits) { return analogWriteRes(bits); }
void analogWriteFrequency(uint8_t pin, float frequency);
#ifdef __cplusplus
void attachInterruptVector(IRQ_NUMBER_t irq, void (*function)(void));
#else
void attachInterruptVector(enum IRQ_NUMBER_t irq, void (*function)(void));
#endif
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);
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 F_CPU_ACTUAL;
extern volatile uint32_t F_BUS_ACTUAL;
extern volatile uint32_t systick_millis_count;

static inline uint32_t millis(void) __attribute__((always_inline, unused));
static inline uint32_t millis(void)
{
return systick_millis_count;
}

uint32_t micros(void);

static inline void delayMicroseconds(uint32_t) __attribute__((always_inline, unused));
static inline void delayMicroseconds(uint32_t usec)
{
uint32_t begin = ARM_DWT_CYCCNT;
uint32_t cycles = F_CPU_ACTUAL / 1000000 * usec;
// TODO: check if cycles is large, do a wait with yield calls until it's smaller
while (ARM_DWT_CYCCNT - begin < cycles) ; // wait
}



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 // __cplusplus





+ 13
- 0
teensy4/debug/printf.h View File

@@ -0,0 +1,13 @@
#define PRINT_DEBUG_STUFF

#ifdef PRINT_DEBUG_STUFF
#define printf_init() printf_debug_init()
#define printf(...) printf_debug(__VA_ARGS__)
void print_debug_init(void);
void printf_debug(const char *format, ...);

#else
#define printf_init()
#define printf(...)

#endif

+ 95
- 0
teensy4/debugprintf.c View File

@@ -0,0 +1,95 @@
#include "debug/printf.h"

#ifdef PRINT_DEBUG_STUFF

#include <stdarg.h>
#include "imxrt.h"

static void puint_debug(unsigned int num);


__attribute__((section(".progmem")))
void printf_debug(const char *format, ...)
{
va_list args;
unsigned int val;
int n;

va_start(args, format);
for (; *format != 0; format++) { // no-frills stand-alone printf
if (*format == '%') {
++format;
if (*format == '%') goto out;
if (*format == '-') format++; // ignore size
while (*format >= '0' && *format <= '9') format++; // ignore size
if (*format == 'l') format++; // ignore long
if (*format == '\0') break;
if (*format == 's') {
printf_debug((char *)va_arg(args, int));
} else if (*format == 'd') {
n = va_arg(args, int);
if (n < 0) {
n = -n;
putchar_debug('-');
}
val = n;
puint_debug(n);
} else if (*format == 'u') {
puint_debug(va_arg(args, unsigned int));
} else if (*format == 'x' || *format == 'X') {
val = va_arg(args, unsigned int);
for (n=0; n < 8; n++) {
unsigned int d = (val >> 28) & 15;
putchar_debug((d < 10) ? d + '0' : d - 10 + 'A');
val <<= 4;
}
} else if (*format == 'c' ) {
putchar_debug((char)va_arg(args, int));
}
} else {
out:
if (*format == '\n') putchar_debug('\r');
putchar_debug(*format);
}
}
va_end(args);
}

static void puint_debug(unsigned int num)
{
char buf[12];
unsigned int i = sizeof(buf)-2;

buf[sizeof(buf)-1] = 0;
while (1) {
buf[i] = (num % 10) + '0';
num /= 10;
if (num == 0) break;
i--;
}
printf_debug(buf + i);
}

__attribute__((section(".progmem")))
void putchar_debug(char c)
{
while (!(LPUART3_STAT & LPUART_STAT_TDRE)) ; // wait
LPUART3_DATA = c;
}

__attribute__((section(".progmem")))
void printf_debug_init(void)
{
// turn on Serial4, run at 115200 baud using 24 MHz clock (works if PLL3 off)
CCM_CCGR0 |= CCM_CCGR0_LPUART3(CCM_CCGR_ON);
IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_06 = 2; // Arduino pin 17
CCM_CSCDR1 = (CCM_CSCDR1 & ~CCM_CSCDR1_UART_CLK_PODF(0x3F)) | CCM_CSCDR1_UART_CLK_SEL;
LPUART3_BAUD = LPUART_BAUD_OSR(25) | LPUART_BAUD_SBR(8);
LPUART3_CTRL = LPUART_CTRL_TE;
}





#endif // PRINT_DEBUG_STUFF

+ 118
- 0
teensy4/delay.c View File

@@ -0,0 +1,118 @@
#include "core_pins.h"

//volatile uint32_t F_CPU = 396000000;
//volatile uint32_t F_BUS = 132000000;
volatile uint32_t systick_millis_count = 0;

// page 411 says "24 MHz XTALOSC can be the external clock source of SYSTICK"
// Testing shows the frequency is actually 100 kHz - but how? Did NXP really
// hide an undocumented divide-by-240 circuit in the hardware?
#define SYSTICK_EXT_FREQ 100000

void systick_isr(void)
{
systick_millis_count++;
// MillisTimer::runFromTimer();
//digitalWriteFast(12, HIGH);
//delayMicroseconds(1);
//digitalWriteFast(12, LOW);
}

#if 0
void millis_init(void)
{
//printf("millis_init %08lX\n", SYST_CALIB);
_VectorsRam[15] = systick_isr;
#ifdef SYSTICK_EXT_FREQ
SYST_RVR = (SYSTICK_EXT_FREQ / 1000) - 1;
SYST_CVR = 0;
SYST_CSR = SYST_CSR_TICKINT | SYST_CSR_ENABLE;
#else
SYST_RVR = (F_CPU / 1000) - 1;
SYST_CVR = 0;
SYST_CSR = SYST_CSR_CLKSOURCE | SYST_CSR_TICKINT | SYST_CSR_ENABLE;
#endif
//SCB_SHPR3 = 0x20200000; // Systick = priority 32
//printf("RVR=%lu\r\n", SYST_RVR);
}
#endif

void yield(void)
{

}

void delay(uint32_t msec)
{
uint32_t start;

if (msec == 0) return;
start = micros();
while (1) {
while ((micros() - start) >= 1000) {
if (--msec == 0) return;
start += 1000;
}
yield();
}
// TODO...
}

uint32_t micros(void)
{
uint32_t msec, tick, elapsed, istatus, usec;
//static uint32_t prev_msec=0;
//static uint32_t prev_istatus=0;
//static uint32_t prev_tick=0;
//static uint32_t prev_elapsed=0;
static uint32_t prev_usec=0;
static int doprint=180;

__disable_irq();
tick = SYST_CVR;
msec = systick_millis_count;
istatus = SCB_ICSR; // bit 26 indicates if systick exception pending
#ifndef SYSTICK_EXT_FREQ
const uint32_t fcpu = F_CPU;
#endif
__enable_irq();
istatus &= SCB_ICSR_PENDSTSET;
#ifdef SYSTICK_EXT_FREQ
if ((istatus & SCB_ICSR_PENDSTSET) && (tick == 0 || tick > (SYSTICK_EXT_FREQ / 2000))) {
#else
if ((istatus & SCB_ICSR_PENDSTSET) && (tick == 0 || tick > (fcpu / 2000))) {
#endif
// systick generated an interrupt at the 1 -> 0 transition, and
// we read it before an ISR could increment systick_millis_count
msec++;
}
#if defined(SYSTICK_EXT_FREQ) && SYSTICK_EXT_FREQ <= 1000000
elapsed = (SYSTICK_EXT_FREQ / 1000) - tick;
if (tick == 0) elapsed = 0;
usec = msec * 1000 + elapsed * (1000000 / SYSTICK_EXT_FREQ);
#elif defined(SYSTICK_EXT_FREQ) && SYSTICK_EXT_FREQ > 1000000
elapsed = (SYSTICK_EXT_FREQ / 1000) - tick;
if (tick == 0) elapsed = 0;
usec = msec * 1000 + elapsed / (SYSTICK_EXT_FREQ / 1000000);
#else
elapsed = (fcpu / 1000) - tick;
if (tick == 0) elapsed = 0;
usec = msec * 1000 + elapsed / (fcpu / 1000000);
#endif
//if (doprint) printf("%lu %lu\r\n", msec, systick);
if (usec < prev_usec && doprint) {
//print("opps\r\n");
//printf("opps then: msec=%lu, systick=%lu, elapsed=%lu, usec=%lu, i=%lx\n",
//prev_msec, prev_tick, prev_elapsed, prev_usec, prev_istatus);
//printf(" now: msec=%lu, systick=%lu, elapsed=%lu, usec=%lu, i=%lx\n",
//msec, tick, elapsed, usec, istatus);
if (doprint > 0) doprint--;
}
//prev_msec = msec;
//prev_elapsed = elapsed;
//prev_tick = tick;
//prev_istatus = istatus;
prev_usec = usec;
return usec;
}


+ 121
- 0
teensy4/digital.c View File

@@ -0,0 +1,121 @@

#include "core_pins.h"

/*
struct digital_pin_bitband_and_config_table_struct {
volatile uint32_t *reg;
volatile uint32_t *mux;
volatile uint32_t *pad;
uint32_t mask;
};
extern const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM[];
#define digitalPinToPort(pin) (pin)
#define digitalPinToBitMask(pin) (digital_pin_to_info_PGM[(pin)].mask)
#define portOutputRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg))
#define portSetRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 0x21))
#define portClearRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 0x22))
#define portToggleRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 0x23))
#define portInputRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 2))
#define portModeRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 1))
#define portConfigRegister(pin) ((digital_pin_to_info_PGM[(pin)].max))
#define digitalPinToPortReg(pin) (portOutputRegister(pin))
*/

const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM[] = {
{&CORE_PIN0_PORTREG, &CORE_PIN0_CONFIG, &CORE_PIN0_PADCONFIG, CORE_PIN0_BITMASK},
{&CORE_PIN1_PORTREG, &CORE_PIN1_CONFIG, &CORE_PIN1_PADCONFIG, CORE_PIN1_BITMASK},
{&CORE_PIN2_PORTREG, &CORE_PIN2_CONFIG, &CORE_PIN2_PADCONFIG, CORE_PIN2_BITMASK},
{&CORE_PIN3_PORTREG, &CORE_PIN3_CONFIG, &CORE_PIN3_PADCONFIG, CORE_PIN3_BITMASK},
{&CORE_PIN4_PORTREG, &CORE_PIN4_CONFIG, &CORE_PIN4_PADCONFIG, CORE_PIN4_BITMASK},
{&CORE_PIN5_PORTREG, &CORE_PIN5_CONFIG, &CORE_PIN5_PADCONFIG, CORE_PIN5_BITMASK},
{&CORE_PIN6_PORTREG, &CORE_PIN6_CONFIG, &CORE_PIN6_PADCONFIG, CORE_PIN6_BITMASK},
{&CORE_PIN7_PORTREG, &CORE_PIN7_CONFIG, &CORE_PIN7_PADCONFIG, CORE_PIN7_BITMASK},
{&CORE_PIN8_PORTREG, &CORE_PIN8_CONFIG, &CORE_PIN8_PADCONFIG, CORE_PIN8_BITMASK},
{&CORE_PIN9_PORTREG, &CORE_PIN9_CONFIG, &CORE_PIN9_PADCONFIG, CORE_PIN9_BITMASK},
{&CORE_PIN10_PORTREG, &CORE_PIN10_CONFIG, &CORE_PIN10_PADCONFIG, CORE_PIN10_BITMASK},
{&CORE_PIN11_PORTREG, &CORE_PIN11_CONFIG, &CORE_PIN11_PADCONFIG, CORE_PIN11_BITMASK},
{&CORE_PIN12_PORTREG, &CORE_PIN12_CONFIG, &CORE_PIN12_PADCONFIG, CORE_PIN12_BITMASK},
{&CORE_PIN13_PORTREG, &CORE_PIN13_CONFIG, &CORE_PIN13_PADCONFIG, CORE_PIN13_BITMASK},
{&CORE_PIN14_PORTREG, &CORE_PIN14_CONFIG, &CORE_PIN14_PADCONFIG, CORE_PIN14_BITMASK},
{&CORE_PIN15_PORTREG, &CORE_PIN15_CONFIG, &CORE_PIN15_PADCONFIG, CORE_PIN15_BITMASK},
{&CORE_PIN16_PORTREG, &CORE_PIN16_CONFIG, &CORE_PIN16_PADCONFIG, CORE_PIN16_BITMASK},
{&CORE_PIN17_PORTREG, &CORE_PIN17_CONFIG, &CORE_PIN17_PADCONFIG, CORE_PIN17_BITMASK},
{&CORE_PIN18_PORTREG, &CORE_PIN18_CONFIG, &CORE_PIN18_PADCONFIG, CORE_PIN18_BITMASK},
{&CORE_PIN19_PORTREG, &CORE_PIN19_CONFIG, &CORE_PIN19_PADCONFIG, CORE_PIN19_BITMASK},
{&CORE_PIN20_PORTREG, &CORE_PIN20_CONFIG, &CORE_PIN20_PADCONFIG, CORE_PIN20_BITMASK},
{&CORE_PIN21_PORTREG, &CORE_PIN21_CONFIG, &CORE_PIN21_PADCONFIG, CORE_PIN21_BITMASK},
{&CORE_PIN22_PORTREG, &CORE_PIN22_CONFIG, &CORE_PIN22_PADCONFIG, CORE_PIN22_BITMASK},
{&CORE_PIN23_PORTREG, &CORE_PIN23_CONFIG, &CORE_PIN23_PADCONFIG, CORE_PIN23_BITMASK},
{&CORE_PIN24_PORTREG, &CORE_PIN24_CONFIG, &CORE_PIN24_PADCONFIG, CORE_PIN24_BITMASK},
{&CORE_PIN25_PORTREG, &CORE_PIN25_CONFIG, &CORE_PIN25_PADCONFIG, CORE_PIN25_BITMASK},
{&CORE_PIN26_PORTREG, &CORE_PIN26_CONFIG, &CORE_PIN26_PADCONFIG, CORE_PIN26_BITMASK},
{&CORE_PIN27_PORTREG, &CORE_PIN27_CONFIG, &CORE_PIN27_PADCONFIG, CORE_PIN27_BITMASK},
{&CORE_PIN28_PORTREG, &CORE_PIN28_CONFIG, &CORE_PIN28_PADCONFIG, CORE_PIN28_BITMASK},
{&CORE_PIN29_PORTREG, &CORE_PIN29_CONFIG, &CORE_PIN29_PADCONFIG, CORE_PIN29_BITMASK},
{&CORE_PIN30_PORTREG, &CORE_PIN30_CONFIG, &CORE_PIN30_PADCONFIG, CORE_PIN30_BITMASK},
{&CORE_PIN31_PORTREG, &CORE_PIN31_CONFIG, &CORE_PIN31_PADCONFIG, CORE_PIN31_BITMASK},
{&CORE_PIN32_PORTREG, &CORE_PIN32_CONFIG, &CORE_PIN32_PADCONFIG, CORE_PIN32_BITMASK},
{&CORE_PIN33_PORTREG, &CORE_PIN33_CONFIG, &CORE_PIN33_PADCONFIG, CORE_PIN33_BITMASK},
};

void digitalWrite(uint8_t pin, uint8_t val)
{
const struct digital_pin_bitband_and_config_table_struct *p;
uint32_t pinmode, mask;

if (pin >= CORE_NUM_DIGITAL) return;
p = digital_pin_to_info_PGM + pin;
pinmode = *(p->reg + 1);
mask = p->mask;
if (pinmode & mask) {
// pin is configured for output mode
if (val) {
*(p->reg + 0x21) = mask; // set register
} else {
*(p->reg + 0x22) = mask; // clear register
}
} else {
// pin is configured for input mode
// writing controls pullup resistor

// TODO....
}
}

uint8_t digitalRead(uint8_t pin)
{
const struct digital_pin_bitband_and_config_table_struct *p;

if (pin >= CORE_NUM_DIGITAL) return 0;
p = digital_pin_to_info_PGM + pin;
return (*(p->reg + 2) & p->mask) ? 1 : 0;
}

void pinMode(uint8_t pin, uint8_t mode)
{
const struct digital_pin_bitband_and_config_table_struct *p;

if (pin >= CORE_NUM_DIGITAL) return;
p = digital_pin_to_info_PGM + pin;
if (mode == OUTPUT || mode == OUTPUT_OPENDRAIN) {
*(p->reg + 1) |= p->mask; // TODO: atomic
if (mode == OUTPUT) {
*(p->pad) = IOMUXC_PAD_DSE(7);
} else { // OUTPUT_OPENDRAIN
*(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_ODE;
}
} else {
*(p->reg + 1) &= ~(p->mask); // TODO: atomic
if (mode == INPUT) {
*(p->pad) = 0;
} else if (mode == INPUT_PULLUP) {
*(p->pad) = IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(3) | IOMUXC_PAD_HYS;
} else if (mode == INPUT_PULLDOWN) {
*(p->pad) = IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(0) | IOMUXC_PAD_HYS;
} else { // INPUT_DISABLE
*(p->pad) = IOMUXC_PAD_HYS;
}
}
*(p->mux) = 5;
}


+ 81
- 0
teensy4/elapsedMillis.h View File

@@ -0,0 +1,81 @@
/* Elapsed time types - for easy-to-use measurements of elapsed time
* http://www.pjrc.com/teensy/
* Copyright (c) 2017 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

+ 162
- 2
teensy4/imxrt.h View File

@@ -5,7 +5,6 @@
// i.MX RT1050 Reference Manual, Rev. 1, 03/2018
// ARM v7-M Architecture Reference Manual (DDI 0403E.b)

#if !defined(KINETISL) && !defined(KINETISK)
enum IRQ_NUMBER_t {
IRQ_DMA_CH0 = 0,
IRQ_DMA_CH1 = 1,
@@ -168,7 +167,156 @@ enum IRQ_NUMBER_t {
IRQ_SJC_DEBUG = 158,
IRQ_NMI_WAKEUP = 159
};
#endif
#define NVIC_NUM_INTERRUPTS 160
#define DMA_NUM_CHANNELS 32

#define DMAMUX_SOURCE_FLEXIO1_REQUEST0 0
#define DMAMUX_SOURCE_FLEXIO1_REQUEST1 0
#define DMAMUX_SOURCE_FLEXIO2_REQUEST0 1
#define DMAMUX_SOURCE_FLEXIO2_REQUEST1 1
#define DMAMUX_SOURCE_LPUART1_RX 2
#define DMAMUX_SOURCE_LPUART1_TX 3
#define DMAMUX_SOURCE_LPUART3_RX 4
#define DMAMUX_SOURCE_LPUART3_TX 5
#define DMAMUX_SOURCE_LPUART5_RX 6
#define DMAMUX_SOURCE_LPUART5_TX 7
#define DMAMUX_SOURCE_LPUART7_RX 8
#define DMAMUX_SOURCE_LPUART7_TX 9
#define DMAMUX_SOURCE_FLEXCAN3 11
#define DMAMUX_SOURCE_CSI 12
#define DMAMUX_SOURCE_LPSPI1_RX 13
#define DMAMUX_SOURCE_LPSPI1_TX 14
#define DMAMUX_SOURCE_LPSPI3_RX 15
#define DMAMUX_SOURCE_LPSPI3_TX 16
#define DMAMUX_SOURCE_LPI2C1 17
#define DMAMUX_SOURCE_LPI2C3 18
#define DMAMUX_SOURCE_SAI1_RX 19
#define DMAMUX_SOURCE_SAI1_TX 20
#define DMAMUX_SOURCE_SAI2_RX 21
#define DMAMUX_SOURCE_SAI2_TX 22
#define DMAMUX_SOURCE_ADC_ETC 23
#define DMAMUX_SOURCE_ADC1 24
#define DMAMUX_SOURCE_ACMP1 25
#define DMAMUX_SOURCE_ACMP3 26
#define DMAMUX_SOURCE_FLEXSPI_RX 28
#define DMAMUX_SOURCE_FLEXSPI_TX 29
#define DMAMUX_SOURCE_XBAR1_0 30
#define DMAMUX_SOURCE_XBAR1_1 31
#define DMAMUX_SOURCE_FLEXPWM1_READ0 32
#define DMAMUX_SOURCE_FLEXPWM1_READ1 33
#define DMAMUX_SOURCE_FLEXPWM1_READ2 34
#define DMAMUX_SOURCE_FLEXPWM1_READ3 35
#define DMAMUX_SOURCE_FLEXPWM1_WRITE0 36
#define DMAMUX_SOURCE_FLEXPWM1_WRITE1 37
#define DMAMUX_SOURCE_FLEXPWM1_WRITE2 38
#define DMAMUX_SOURCE_FLEXPWM1_WRITE3 39
#define DMAMUX_SOURCE_FLEXPWM3_READ0 40
#define DMAMUX_SOURCE_FLEXPWM3_READ1 41
#define DMAMUX_SOURCE_FLEXPWM3_READ2 42
#define DMAMUX_SOURCE_FLEXPWM3_READ3 43
#define DMAMUX_SOURCE_FLEXPWM3_WRITE0 44
#define DMAMUX_SOURCE_FLEXPWM3_WRITE1 45
#define DMAMUX_SOURCE_FLEXPWM3_WRITE2 46
#define DMAMUX_SOURCE_FLEXPWM3_WRITE3 47
#define DMAMUX_SOURCE_QTIMER1_READ0 48
#define DMAMUX_SOURCE_QTIMER1_READ1 49
#define DMAMUX_SOURCE_QTIMER1_READ2 50
#define DMAMUX_SOURCE_QTIMER1_READ3 51
#define DMAMUX_SOURCE_QTIMER1_WRITE0_CMPLD1 52
#define DMAMUX_SOURCE_QTIMER1_WRITE1_CMPLD1 53
#define DMAMUX_SOURCE_QTIMER1_WRITE2_CMPLD1 54
#define DMAMUX_SOURCE_QTIMER1_WRITE3_CMPLD1 55
#define DMAMUX_SOURCE_QTIMER1_WRITE1_CMPLD2 52
#define DMAMUX_SOURCE_QTIMER1_WRITE0_CMPLD2 53
#define DMAMUX_SOURCE_QTIMER1_WRITE3_CMPLD2 54
#define DMAMUX_SOURCE_QTIMER1_WRITE2_CMPLD2 55
#define DMAMUX_SOURCE_QTIMER3_READ0 56
#define DMAMUX_SOURCE_QTIMER3_READ1 57
#define DMAMUX_SOURCE_QTIMER3_READ2 58
#define DMAMUX_SOURCE_QTIMER3_READ3 59
#define DMAMUX_SOURCE_QTIMER3_WRITE0_CMPLD1 56
#define DMAMUX_SOURCE_QTIMER3_WRITE1_CMPLD1 57
#define DMAMUX_SOURCE_QTIMER3_WRITE2_CMPLD1 58
#define DMAMUX_SOURCE_QTIMER3_WRITE3_CMPLD1 59
#define DMAMUX_SOURCE_QTIMER3_WRITE1_CMPLD2 56
#define DMAMUX_SOURCE_QTIMER3_WRITE0_CMPLD2 57
#define DMAMUX_SOURCE_QTIMER3_WRITE3_CMPLD2 58
#define DMAMUX_SOURCE_QTIMER3_WRITE2_CMPLD2 59
#define DMAMUX_SOURCE_FLEXSPI2_RX 60
#define DMAMUX_SOURCE_FLEXSPI2_TX 61
#define DMAMUX_SOURCE_FLEXIO1_REQUEST2 64
#define DMAMUX_SOURCE_FLEXIO1_REQUEST3 64
#define DMAMUX_SOURCE_FLEXIO2_REQUEST2 65
#define DMAMUX_SOURCE_FLEXIO2_REQUEST3 65
#define DMAMUX_SOURCE_LPUART2_RX 66
#define DMAMUX_SOURCE_LPUART2_TX 67
#define DMAMUX_SOURCE_LPUART4_RX 68
#define DMAMUX_SOURCE_LPUART4_TX 69
#define DMAMUX_SOURCE_LPUART6_RX 70
#define DMAMUX_SOURCE_LPUART6_TX 71
#define DMAMUX_SOURCE_LPUART8_RX 72
#define DMAMUX_SOURCE_LPUART8_TX 73
#define DMAMUX_SOURCE_PXP 75
#define DMAMUX_SOURCE_LCDIF 76
#define DMAMUX_SOURCE_LPSPI2_RX 77
#define DMAMUX_SOURCE_LPSPI2_TX 78
#define DMAMUX_SOURCE_LPSPI4_RX 79
#define DMAMUX_SOURCE_LPSPI4_TX 80
#define DMAMUX_SOURCE_LPI2C2 81
#define DMAMUX_SOURCE_LPI2C4 82
#define DMAMUX_SOURCE_SAI3_RX 83
#define DMAMUX_SOURCE_SAI3_TX 84
#define DMAMUX_SOURCE_SPDIF_RX 85
#define DMAMUX_SOURCE_SPDIF_TX 86
#define DMAMUX_SOURCE_ADC2 88
#define DMAMUX_SOURCE_ACMP2 89
#define DMAMUX_SOURCE_ACMP4 90
#define DMAMUX_SOURCE_ENET1_TIMER0 92
#define DMAMUX_SOURCE_ENET1_TIMER1 93
#define DMAMUX_SOURCE_XBAR1_2 94
#define DMAMUX_SOURCE_XBAR1_3 95
#define DMAMUX_SOURCE_FLEXPWM2_READ0 96
#define DMAMUX_SOURCE_FLEXPWM2_READ1 97
#define DMAMUX_SOURCE_FLEXPWM2_READ2 98
#define DMAMUX_SOURCE_FLEXPWM2_READ3 99
#define DMAMUX_SOURCE_FLEXPWM2_WRITE0 100
#define DMAMUX_SOURCE_FLEXPWM2_WRITE1 101
#define DMAMUX_SOURCE_FLEXPWM2_WRITE2 102
#define DMAMUX_SOURCE_FLEXPWM2_WRITE3 103
#define DMAMUX_SOURCE_FLEXPWM4_READ0 104
#define DMAMUX_SOURCE_FLEXPWM4_READ1 105
#define DMAMUX_SOURCE_FLEXPWM4_READ2 106
#define DMAMUX_SOURCE_FLEXPWM4_READ3 107
#define DMAMUX_SOURCE_FLEXPWM4_WRITE0 108
#define DMAMUX_SOURCE_FLEXPWM4_WRITE1 109
#define DMAMUX_SOURCE_FLEXPWM4_WRITE2 110
#define DMAMUX_SOURCE_FLEXPWM4_WRITE3 111
#define DMAMUX_SOURCE_QTIMER2_READ0 112
#define DMAMUX_SOURCE_QTIMER2_READ1 113
#define DMAMUX_SOURCE_QTIMER2_READ2 114
#define DMAMUX_SOURCE_QTIMER2_READ3 115
#define DMAMUX_SOURCE_QTIMER2_WRITE0_CMPLD1 116
#define DMAMUX_SOURCE_QTIMER2_WRITE1_CMPLD1 117
#define DMAMUX_SOURCE_QTIMER2_WRITE2_CMPLD1 118
#define DMAMUX_SOURCE_QTIMER2_WRITE3_CMPLD1 119
#define DMAMUX_SOURCE_QTIMER2_WRITE1_CMPLD2 116
#define DMAMUX_SOURCE_QTIMER2_WRITE0_CMPLD2 117
#define DMAMUX_SOURCE_QTIMER2_WRITE3_CMPLD2 118
#define DMAMUX_SOURCE_QTIMER2_WRITE2_CMPLD2 119
#define DMAMUX_SOURCE_QTIMER4_READ0 120
#define DMAMUX_SOURCE_QTIMER4_READ1 121
#define DMAMUX_SOURCE_QTIMER4_READ2 122
#define DMAMUX_SOURCE_QTIMER4_READ3 123
#define DMAMUX_SOURCE_QTIMER4_WRITE0_CMPLD1 120
#define DMAMUX_SOURCE_QTIMER4_WRITE1_CMPLD1 121
#define DMAMUX_SOURCE_QTIMER4_WRITE2_CMPLD1 122
#define DMAMUX_SOURCE_QTIMER4_WRITE3_CMPLD1 123
#define DMAMUX_SOURCE_QTIMER4_WRITE1_CMPLD2 120
#define DMAMUX_SOURCE_QTIMER4_WRITE0_CMPLD2 121
#define DMAMUX_SOURCE_QTIMER4_WRITE3_CMPLD2 122
#define DMAMUX_SOURCE_QTIMER4_WRITE2_CMPLD2 123
#define DMAMUX_SOURCE_ENET2_TIMER0 124
#define DMAMUX_SOURCE_ENET2_TIMER1 125


typedef struct {
@@ -5647,6 +5795,13 @@ typedef struct {
#define PIT_MCR (IMXRT_PIT.offset000)
#define PIT_LTMR64H (IMXRT_PIT.offset0E0)
#define PIT_LTMR64L (IMXRT_PIT.offset0E4)
typedef struct {
volatile uint32_t LDVAL;
volatile uint32_t CVAL;
volatile uint32_t TCTRL;
volatile uint32_t TFLG;
} IMXRT_PIT_CHANNEL_t;
#define IMXRT_PIT_CHANNELS ((IMXRT_PIT_CHANNEL_t *)(&(IMXRT_PIT.offset100)))
#define PIT_LDVAL0 (IMXRT_PIT.offset100)
#define PIT_CVAL0 (IMXRT_PIT.offset104)
#define PIT_TCTRL0 (IMXRT_PIT.offset108)
@@ -6784,6 +6939,11 @@ typedef struct {
#define XTALOSC24M_OSC_CONFIG2_TOG (IMXRT_XTALOSC24M.offset2CC)


// 0 = highest priority
// Cortex-M7: 0,16,32,48,64,80,96,112,128,144,160,176,192,208,224,240
#define NVIC_SET_PRIORITY(irqnum, priority) (*((volatile uint8_t *)0xE000E400 + (irqnum)) = (uint8_t)(priority))
#define NVIC_GET_PRIORITY(irqnum) (*((uint8_t *)0xE000E400 + (irqnum)))


#define __disable_irq() __asm__ volatile("CPSID i":::"memory");
#define __enable_irq() __asm__ volatile("CPSIE i":::"memory");

+ 72
- 0
teensy4/imxrt.ld View File

@@ -0,0 +1,72 @@
MEMORY
{
ITCM (rwx): ORIGIN = 0x00000000, LENGTH = 128K
DTCM (rwx): ORIGIN = 0x20000000, LENGTH = 128K
RAM (rwx): ORIGIN = 0x20200000, LENGTH = 256K
FLASH (rwx): ORIGIN = 0x60000000, LENGTH = 1536K
}

ENTRY(ImageVectorTable)

SECTIONS
{
.text.progmem : {
KEEP(*(.flashconfig))
FILL(0xFF)
. = ORIGIN(FLASH) + 0x1000;
KEEP(*(.ivt))
KEEP(*(.bootdata))
KEEP(*(.vectors))
KEEP(*(.startup))
*(.progmem*)
. = ALIGN(16);
} > FLASH

.text : {
. = . + 32; /* MPU to trap NULL pointer deref */
*(.fastrun)
*(.text*)
. = ALIGN(16);
} > ITCM AT> FLASH

.data : {
*(.rodata*)
*(.data*)
. = ALIGN(16);
} > DTCM AT> FLASH

.bss : {
*(.bss*)
*(COMMON)
. = ALIGN(32);
. = . + 32; /* MPU to trap stack overflow */
} > DTCM

.bss.dma : {
*(.dmabuffers)
. = ALIGN(16);
} > RAM

_stext = ADDR(.text);
_etext = ADDR(.text) + SIZEOF(.text);
_stextload = LOADADDR(.text);

_sdata = ADDR(.data);
_edata = ADDR(.data) + SIZEOF(.data);
_sdataload = LOADADDR(.data);

_estack = ORIGIN(DTCM) + LENGTH(DTCM) - 16;

_sbss = ADDR(.bss);
_ebss = ADDR(.bss) + SIZEOF(.bss);

_flashimagelen = SIZEOF(.text.progmem) + SIZEOF(.text) + SIZEOF(.data);

.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }

}

+ 5789
- 0
teensy4/keylayouts.h
File diff suppressed because it is too large
View File


+ 175
- 0
teensy4/pins_arduino.h View File

@@ -0,0 +1,175 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2018 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>

// A0-A9 are always digital 14-23, for Arduino compatibility
#define PIN_A0 (14)
#define PIN_A1 (15)
#define PIN_A2 (16)
#define PIN_A3 (17)
#define PIN_A4 (18)
#define PIN_A5 (19)
#define PIN_A6 (20)
#define PIN_A7 (21)
#define PIN_A8 (22)
#define PIN_A9 (23)
const static uint8_t A0 = PIN_A0;
const static uint8_t A1 = PIN_A1;
const static uint8_t A2 = PIN_A2;
const static uint8_t A3 = PIN_A3;
const static uint8_t A4 = PIN_A4;
const static uint8_t A5 = PIN_A5;
const static uint8_t A6 = PIN_A6;
const static uint8_t A7 = PIN_A7;
const static uint8_t A8 = PIN_A8;
const static uint8_t A9 = PIN_A9;

#if defined(__IMXRT1052__)
#define PIN_A10 (24)
#define PIN_A11 (25)
const static uint8_t A10 = PIN_A10;
const static uint8_t A11 = PIN_A11;
#endif

#define LED_BUILTIN (13)

#define PIN_SPI_SS (10)
#define PIN_SPI_MOSI (11)
#define PIN_SPI_MISO (12)
#define PIN_SPI_SCK (13)
const static uint8_t SS = 10;
const static uint8_t MOSI = 11;
const static uint8_t MISO = 12;
const static uint8_t SCK = 13;

#define PIN_WIRE_SDA (18)
#define PIN_WIRE_SCL (19)
const static uint8_t SDA = 18;
const static uint8_t SCL = 19;

#define PIN_SERIAL_RX (0)
#define PIN_SERIAL_TX (1)


#define NUM_DIGITAL_PINS 34
#define NUM_ANALOG_INPUTS 12


#define NOT_AN_INTERRUPT -1


#if defined(__IMXRT1052__)
#define analogInputToDigitalPin(p) (((p) <= 9) ? (p) + 14 : (((p) >= 14 && (p) <= 25) ? (p) : -1))
#define digitalPinHasPWM(p) ((p) <= 15 || (p) == 18 || (p) == 19 || ((p) >= 22 && (p) <= 25) || ((p) >= 28 && (p) <= 31) || (p) == 33)
#define digitalPinToInterrupt(p) ((p) < NUM_DIGITAL_PINS ? (p) : -1)
#endif

#define digitalPinToPCICR(p) ((volatile uint8_t *)0)
#define digitalPinToPCICRbit(p) (0)
#define digitalPinToPCIFR(p) ((volatile uint8_t *)0)
#define digitalPinToPCIFRbit(p) (0)
#define digitalPinToPCMSK(p) ((volatile uint8_t *)0)
#define digitalPinToPCMSKbit(p) (0)


struct digital_pin_bitband_and_config_table_struct { // not really bitband, old name from Teensy3
volatile uint32_t *reg;
volatile uint32_t *mux;
volatile uint32_t *pad;
uint32_t mask;
};
extern const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM[];
#define digitalPinToPort(pin) (pin)
#define digitalPinToBitMask(pin) (digital_pin_to_info_PGM[(pin)].mask)
#define portOutputRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 0))
#define portSetRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 4))
#define portClearRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 8))
#define portToggleRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 12))
#define portInputRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 16))
#define portModeRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 20))
#define portConfigRegister(pin) ((digital_pin_to_info_PGM[(pin)].mux))
#define digitalPinToPortReg(pin) (portOutputRegister(pin))
#define digitalPinToBit(pin) // TODO, is this needed?


#define NOT_ON_TIMER 0
static inline uint8_t digitalPinToTimer(uint8_t) __attribute__((always_inline, unused));
static inline uint8_t digitalPinToTimer(uint8_t pin)
{
// TODO: does anything meaningful use this?
return NOT_ON_TIMER;
}

// These serial port names are intended to allow libraries and architecture-neutral
// sketches to automatically default to the correct port name for a particular type
// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
// the first hardware serial port whose RX/TX pins are not dedicated to another use.
//
// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor
//
// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial
//
// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library
//
// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins.
//
// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX
// pins are NOT connected to anything by default.
//
#if F_CPU >= 20000000 && !defined(USB_DISABLED)
#define SERIAL_PORT_MONITOR Serial
#else
#define SERIAL_PORT_MONITOR Serial1
#endif
#define SERIAL_PORT_USBVIRTUAL Serial
#define SERIAL_PORT_HARDWARE Serial1
#define SERIAL_PORT_HARDWARE1 Serial2
#define SERIAL_PORT_HARDWARE2 Serial3
#define SERIAL_PORT_HARDWARE_OPEN Serial1
#define SERIAL_PORT_HARDWARE_OPEN1 Serial2
#define SERIAL_PORT_HARDWARE_OPEN2 Serial3
#define SERIAL_PORT_HARDWARE3 Serial4
#define SERIAL_PORT_HARDWARE4 Serial5
#define SERIAL_PORT_HARDWARE5 Serial6
#define SERIAL_PORT_HARDWARE6 Serial7
#define SERIAL_PORT_HARDWARE7 Serial8
#define SERIAL_PORT_HARDWARE_OPEN3 Serial4
#define SERIAL_PORT_HARDWARE_OPEN4 Serial5
#define SERIAL_PORT_HARDWARE_OPEN5 Serial6
#define SERIAL_PORT_HARDWARE_OPEN6 Serial7
#define SERIAL_PORT_HARDWARE_OPEN7 Serial8

#define SerialUSB Serial

#endif // pins_macros_for_arduino_compatibility_h

+ 299
- 0
teensy4/startup.c View File

@@ -0,0 +1,299 @@
#include "imxrt.h"
#include "wiring.h"
#include "debug/printf.h"

// from the linker
extern unsigned long _stextload;
extern unsigned long _stext;
extern unsigned long _etext;
extern unsigned long _sdataload;
extern unsigned long _sdata;
extern unsigned long _edata;
extern unsigned long _sbss;
extern unsigned long _ebss;


__attribute__ ((used, aligned(1024)))
void (* _VectorsRam[160+16])(void);

static void memory_copy(uint32_t *dest, const uint32_t *src, uint32_t *dest_end);
static void memory_clear(uint32_t *dest, uint32_t *dest_end);
static void configure_systick(void);
extern void systick_isr(void);
void configure_cache(void);
void unused_interrupt_vector(void);


__attribute__((section(".startup")))
void ResetHandler(void)
{
unsigned int i;

//force the stack to begin at some arbitrary location
//__asm__ volatile("mov sp, %0" : : "r" (0x20010000) : );

// pin 13 - if startup crashes, use this to turn on the LED early for troubleshooting
//IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03 = 5;
//IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_03 = IOMUXC_PAD_DSE(7);
//GPIO2_GDIR |= (1<<3);
//GPIO2_DR_SET = (1<<3);

memory_copy(&_stext, &_stextload, &_etext);
memory_copy(&_sdata, &_sdataload, &_edata);
memory_clear(&_sbss, &_ebss);

for (i=0; i < 176; i++) _VectorsRam[i] = &unused_interrupt_vector;
SCB_VTOR = (uint32_t)_VectorsRam;

// must enable PRINT_DEBUG_STUFF in debug/print.h
printf_init();
printf("\n***********IMXRT Startup**********\n");
printf("test %d %d %d\n", 1, -1234567, 3);

configure_cache();
configure_systick();
#if 1

//uint32_t pll1;
//uint32_t n =
//pll = CCM_ANALOG_PLL_ARM;
printf("ARM PLL = %08lX\n", CCM_ANALOG_PLL_ARM);

uint32_t cdcdr = CCM_CBCDR;
uint32_t cbcmr = CCM_CBCMR;
printf("AHB divisor = %ld\n", ((cdcdr >> 10) & 7) + 1);
printf("IPG divisor = %ld\n", ((cdcdr >> 8) & 3) + 1);

if (cdcdr & CCM_CBCDR_PERIPH_CLK_SEL) {
printf("using periph_clk2_clk_divided\n");

} else {
printf("using pre_periph_clk_sel\n");
uint32_t n = (cbcmr >> 19) & 3;
if (n == 0) {
printf("using PLL2\n");
} else if (n == 1) {
printf("using PLL2 PFD2\n");
} else if (n == 2) {
printf("using PLL2 PFD0\n");
} else {
printf("using PLL1\n");
}


}
//set_arm_clock(300000000);
#endif


printf("before setup\n");
setup();
printf("after setup\n");
while (1) {
printf("loop\n");
loop();
}
}




// ARM SysTick is used for most Ardiuno timing functions, delay(), millis(),
// micros(). SysTick can run from either the ARM core clock, or from an
// "external" clock. NXP documents it as "24 MHz XTALOSC can be the external
// clock source of SYSTICK" (RT1052 ref manual, rev 1, page 411). However,
// NXP actually hid an undocumented divide-by-240 circuit in the hardware, so
// the external clock is really 100 kHz. We use this clock rather than the
// ARM clock, to allow SysTick to maintain correct timing even when we change
// the ARM clock to run at different speeds.
#define SYSTICK_EXT_FREQ 100000

static void configure_systick(void)
{
_VectorsRam[15] = systick_isr;
SYST_RVR = (SYSTICK_EXT_FREQ / 1000) - 1;
SYST_CVR = 0;
SYST_CSR = SYST_CSR_TICKINT | SYST_CSR_ENABLE;
ARM_DEMCR |= ARM_DEMCR_TRCENA;
ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; // turn on cycle counter
}


// concise defines for SCB_MPU_RASR and SCB_MPU_RBAR, ARM DDI0403E, pg 696
#define NOEXEC SCB_MPU_RASR_XN
#define READONLY SCB_MPU_RASR_AP(7)
#define READWRITE SCB_MPU_RASR_AP(3)
#define NOACCESS SCB_MPU_RASR_AP(0)
#define MEM_CACHE_WT SCB_MPU_RASR_TEX(0) | SCB_MPU_RASR_C
#define MEM_CACHE_WB SCB_MPU_RASR_TEX(0) | SCB_MPU_RASR_C | SCB_MPU_RASR_B
#define MEM_CACHE_WBWA SCB_MPU_RASR_TEX(1) | SCB_MPU_RASR_C | SCB_MPU_RASR_B
#define MEM_NOCACHE SCB_MPU_RASR_TEX(1)
#define DEV_NOCACHE SCB_MPU_RASR_TEX(2)
#define SIZE_128K (SCB_MPU_RASR_SIZE(16) | SCB_MPU_RASR_ENABLE)
#define SIZE_256K (SCB_MPU_RASR_SIZE(17) | SCB_MPU_RASR_ENABLE)
#define SIZE_512K (SCB_MPU_RASR_SIZE(18) | SCB_MPU_RASR_ENABLE)
#define SIZE_1M (SCB_MPU_RASR_SIZE(19) | SCB_MPU_RASR_ENABLE)
#define SIZE_2M (SCB_MPU_RASR_SIZE(20) | SCB_MPU_RASR_ENABLE)
#define SIZE_4M (SCB_MPU_RASR_SIZE(21) | SCB_MPU_RASR_ENABLE)
#define SIZE_8M (SCB_MPU_RASR_SIZE(22) | SCB_MPU_RASR_ENABLE)
#define SIZE_16M (SCB_MPU_RASR_SIZE(23) | SCB_MPU_RASR_ENABLE)
#define SIZE_32M (SCB_MPU_RASR_SIZE(24) | SCB_MPU_RASR_ENABLE)
#define SIZE_64M (SCB_MPU_RASR_SIZE(25) | SCB_MPU_RASR_ENABLE)
#define REGION(n) (SCB_MPU_RBAR_REGION(n) | SCB_MPU_RBAR_VALID)

__attribute__((section(".progmem")))
void configure_cache(void)
{
//printf("MPU_TYPE = %08lX\n", SCB_MPU_TYPE);
//printf("CCR = %08lX\n", SCB_CCR);

// TODO: check if caches already active - skip?

SCB_MPU_CTRL = 0; // turn off MPU

SCB_MPU_RBAR = 0x00000000 | REGION(0); // ITCM
SCB_MPU_RASR = MEM_NOCACHE | READWRITE | SIZE_512K;

SCB_MPU_RBAR = 0x00200000 | REGION(1); // Boot ROM
SCB_MPU_RASR = MEM_CACHE_WT | READONLY | SIZE_128K;

SCB_MPU_RBAR = 0x20000000 | REGION(2); // DTCM
SCB_MPU_RASR = MEM_NOCACHE | READWRITE | NOEXEC | SIZE_512K;

SCB_MPU_RBAR = 0x20200000 | REGION(3); // RAM (AXI bus)
SCB_MPU_RASR = MEM_CACHE_WBWA | READWRITE | NOEXEC | SIZE_1M;

SCB_MPU_RBAR = 0x40000000 | REGION(4); // Peripherals
SCB_MPU_RASR = DEV_NOCACHE | READWRITE | NOEXEC | SIZE_64M;

SCB_MPU_RBAR = 0x60000000 | REGION(5); // QSPI Flash
SCB_MPU_RASR = MEM_CACHE_WBWA | READONLY | SIZE_16M;

// TODO: 32 byte sub-region at 0x00000000 with NOACCESS, to trap NULL pointer deref
// TODO: protect access to power supply config
// TODO: 32 byte sub-region at end of .bss section with NOACCESS, to trap stack overflow

SCB_MPU_CTRL = SCB_MPU_CTRL_ENABLE;

// cache enable, ARM DDI0403E, pg 628
asm("dsb");
asm("isb");
SCB_CACHE_ICIALLU = 0;

asm("dsb");
asm("isb");
SCB_CCR |= (SCB_CCR_IC | SCB_CCR_DC);
}


uint32_t set_arm_clock(uint32_t frequency)
{
if (!(CCM_CBCDR & CCM_CBCDR_PERIPH_CLK_SEL)) {
//print("need to switch to stable clock while reconfigure of ARM PLL\n");
const uint32_t need1s = CCM_ANALOG_PLL_USB1_ENABLE | CCM_ANALOG_PLL_USB1_POWER |
CCM_ANALOG_PLL_USB1_LOCK | CCM_ANALOG_PLL_USB1_EN_USB_CLKS;
if ((CCM_ANALOG_PLL_USB1 & need1s) == need1s) {
//print(" run temporarily from USB/4 (120 MHz)\n");

} else {
//print(" run temporarily from crystal (24 MHz)\n");

}

} else {
//print("already running from an alternate clock, ok to mess with ARM PLL\n");
}

// if SYS PLL running at 528 MHz
// if frequency == 528
// if frequency == 396
// if frequency == 352
//

return frequency;
}



__attribute__((section(".progmem")))
void usb_pll_start()
{
while (1) {
uint32_t n = CCM_ANALOG_PLL_USB1; // pg 759
//printf("CCM_ANALOG_PLL_USB1=%08lX\r\n", n);
if (n & CCM_ANALOG_PLL_USB1_DIV_SELECT) {
//print(" ERROR, 528 MHz mode!\r\n"); // never supposed to use this mode!
CCM_ANALOG_PLL_USB1_CLR = 0xC000; // bypass 24 MHz
CCM_ANALOG_PLL_USB1_SET = CCM_ANALOG_PLL_USB1_BYPASS; // bypass
CCM_ANALOG_PLL_USB1_CLR = CCM_ANALOG_PLL_USB1_POWER | // power down
CCM_ANALOG_PLL_USB1_DIV_SELECT | // use 480 MHz
CCM_ANALOG_PLL_USB1_ENABLE | // disable
CCM_ANALOG_PLL_USB1_EN_USB_CLKS; // disable usb
continue;
}
if (!(n & CCM_ANALOG_PLL_USB1_ENABLE)) {
//print(" enable PLL\r\n");
// TODO: should this be done so early, or later??
CCM_ANALOG_PLL_USB1_SET = CCM_ANALOG_PLL_USB1_ENABLE;
continue;
}
if (!(n & CCM_ANALOG_PLL_USB1_POWER)) {
//print(" power up PLL\r\n");
CCM_ANALOG_PLL_USB1_SET = CCM_ANALOG_PLL_USB1_POWER;
continue;
}
if (!(n & CCM_ANALOG_PLL_USB1_LOCK)) {
//print(" wait for lock\r\n");
continue;
}
if (n & CCM_ANALOG_PLL_USB1_BYPASS) {
//print(" turn off bypass\r\n");
CCM_ANALOG_PLL_USB1_CLR = CCM_ANALOG_PLL_USB1_BYPASS;
continue;
}
if (!(n & CCM_ANALOG_PLL_USB1_EN_USB_CLKS)) {
//print(" enable USB clocks\r\n");
CCM_ANALOG_PLL_USB1_SET = CCM_ANALOG_PLL_USB1_EN_USB_CLKS;
continue;
}
return; // everything is as it should be :-)
}
}

void unused_interrupt_vector(void)
{
// TODO: polling Serial to complete buffered transmits
#if 1
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03 = 5; // pin 13
IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_03 = IOMUXC_PAD_DSE(7);
GPIO2_GDIR |= (1<<3);
GPIO2_DR_SET = (1<<3);
while (1) {
volatile uint32_t n;
GPIO2_DR_SET = (1<<3); //digitalWrite(13, HIGH);
for (n=0; n < 5000000; n++) ;
GPIO2_DR_CLEAR = (1<<3); //digitalWrite(13, LOW);
for (n=0; n < 4000000; n++) ;
}
#else
while (1) {
}
#endif
}

static void memory_copy(uint32_t *dest, const uint32_t *src, uint32_t *dest_end)
{
if (dest == src) return;
while (dest < dest_end) {
*dest++ = *src++;
}
}

static void memory_clear(uint32_t *dest, uint32_t *dest_end)
{
while (dest < dest_end) {
*dest++ = 0;
}
}



+ 556
- 0
teensy4/usb.c View File

@@ -0,0 +1,556 @@
#include "usb_dev.h"
#define USB_DESC_LIST_DEFINE
#include "usb_desc.h"
#include <string.h>

// Use this for access to endpoint 1 for debug
// https://github.com/BrandonLWhite/Stellaris-LaunchPad-UsbDevBulk-AutoWinusbInstall

// device mode, page 3155

typedef struct endpoint_struct endpoint_t;
//typedef struct transfer_struct transfer_t;

struct endpoint_struct {
uint32_t config;
uint32_t current;
uint32_t next;
uint32_t status;
uint32_t pointer0;
uint32_t pointer1;
uint32_t pointer2;
uint32_t pointer3;
uint32_t pointer4;
uint32_t reserved;
uint32_t setup0;
uint32_t setup1;
transfer_t *first_transfer;
transfer_t *last_transfer;
void (*callback_function)(transfer_t *completed_transfer);
uint32_t unused1;
};

/*struct transfer_struct {
uint32_t next;
uint32_t status;
uint32_t pointer0;
uint32_t pointer1;
uint32_t pointer2;
uint32_t pointer3;
uint32_t pointer4;
uint32_t callback_param;
};*/

endpoint_t endpoint_queue_head[(NUM_ENDPOINTS+1)*2] __attribute__ ((used, aligned(4096)));

transfer_t endpoint0_transfer_data __attribute__ ((used, aligned(32)));
transfer_t endpoint0_transfer_ack __attribute__ ((used, aligned(32)));


typedef 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;
};
uint64_t bothwords;
} setup_t;

static setup_t endpoint0_setupdata;
static uint32_t endpoint0_notify_mask=0;
static uint32_t endpointN_notify_mask=0;
//static int reset_count=0;
volatile uint8_t usb_configuration = 0;
static uint8_t endpoint0_buffer[8];


static void isr(void);
static void endpoint0_setup(uint64_t setupdata);
static void endpoint0_transmit(const void *data, uint32_t len, int notify);
static void endpoint0_receive(void *data, uint32_t len, int notify);
static void endpoint0_complete(void);




void usb_init(void)
{
// TODO: make sure USB voltage regulator is running at full strength

// assume PLL3 is already running - already done by usb_pll_start() in main.c

CCM_CCGR6 |= CCM_CCGR6_USBOH3(CCM_CCGR_ON); // turn on clocks to USB peripheral
// Before programming this register, the PHY clocks must be enabled in registers
// USBPHYx_CTRLn and CCM_ANALOG_USBPHYx_PLL_480_CTRLn.

//printf("USBPHY1_PWD=%08lX\r\n", USBPHY1_PWD);
//printf("USBPHY1_TX=%08lX\r\n", USBPHY1_TX);
//printf("USBPHY1_RX=%08lX\r\n", USBPHY1_RX);
//printf("USBPHY1_CTRL=%08lX\r\n", USBPHY1_CTRL);
//printf("USB1_USBMODE=%08lX\r\n", USB1_USBMODE);

// turn on PLL3, wait for 480 MHz lock?
// turn on CCM clock gates? CCGR6[CG0]

if ((USBPHY1_PWD & (USBPHY_PWD_RXPWDRX | USBPHY_PWD_RXPWDDIFF | USBPHY_PWD_RXPWD1PT1
| USBPHY_PWD_RXPWDENV | USBPHY_PWD_TXPWDV2I | USBPHY_PWD_TXPWDIBIAS
| USBPHY_PWD_TXPWDFS)) || (USB1_USBMODE & USB_USBMODE_CM_MASK)) {
// USB controller is turned on from previous use
// reset needed to turn it off & start from clean slate
USBPHY1_CTRL_SET = USBPHY_CTRL_SFTRST; // USBPHY1_CTRL page 3292
USB1_USBCMD |= USB_USBCMD_RST; // reset controller
int count=0;
while (USB1_USBCMD & USB_USBCMD_RST) count++;
NVIC_CLEAR_PENDING(IRQ_USB1);
USBPHY1_CTRL_CLR = USBPHY_CTRL_SFTRST; // reset PHY
//USB1_USBSTS = USB1_USBSTS; // TODO: is this needed?
//printf("USB reset took %d loops\r\n", count);
//delay(10);
//print("\r\n");
//printf("USBPHY1_PWD=%08lX\r\n", USBPHY1_PWD);
//printf("USBPHY1_TX=%08lX\r\n", USBPHY1_TX);
//printf("USBPHY1_RX=%08lX\r\n", USBPHY1_RX);
//printf("USBPHY1_CTRL=%08lX\r\n", USBPHY1_CTRL);
//printf("USB1_USBMODE=%08lX\r\n", USB1_USBMODE);
//delay(500);
}

// Device Controller Initialization, page 3161
// USBCMD pg 3216
// USBSTS pg 3220
// USBINTR pg 3224
// DEVICEADDR pg 3227
// ENDPTLISTADDR 3229
// USBMODE pg 3244
// ENDPTSETUPSTAT 3245
// ENDPTPRIME pg 3246
// ENDPTFLUSH pg 3247
// ENDPTSTAT pg 3247
// ENDPTCOMPLETE 3248
// ENDPTCTRL0 pg 3249

USBPHY1_CTRL_CLR = USBPHY_CTRL_CLKGATE;
USBPHY1_PWD = 0;
//printf("USBPHY1_PWD=%08lX\r\n", USBPHY1_PWD);
//printf("USBPHY1_CTRL=%08lX\r\n", USBPHY1_CTRL);

USB1_USBMODE = USB_USBMODE_CM(2) | USB_USBMODE_SLOM;
memset(endpoint_queue_head, 0, sizeof(endpoint_queue_head));
endpoint_queue_head[0].config = (64 << 16) | (1 << 15);
endpoint_queue_head[1].config = (64 << 16);
USB1_ENDPOINTLISTADDR = (uint32_t)&endpoint_queue_head;
// Recommended: enable all device interrupts including: USBINT, USBERRINT,
// Port Change Detect, USB Reset Received, DCSuspend.
USB1_USBINTR = USB_USBINTR_UE | USB_USBINTR_UEE | /* USB_USBINTR_PCE | */
USB_USBINTR_URE | USB_USBINTR_SLE;
//_VectorsRam[IRQ_USB1+16] = &isr;
attachInterruptVector(IRQ_USB1, &isr);
NVIC_ENABLE_IRQ(IRQ_USB1);
//printf("USB1_ENDPTCTRL0=%08lX\r\n", USB1_ENDPTCTRL0);
//printf("USB1_ENDPTCTRL1=%08lX\r\n", USB1_ENDPTCTRL1);
//printf("USB1_ENDPTCTRL2=%08lX\r\n", USB1_ENDPTCTRL2);
//printf("USB1_ENDPTCTRL3=%08lX\r\n", USB1_ENDPTCTRL3);
USB1_USBCMD |= USB_USBCMD_RS;
}


static void isr(void)
{
//print("*");

// Port control in device mode is only used for
// status port reset, suspend, and current connect status.
uint32_t status = USB1_USBSTS;
USB1_USBSTS = status;

// USB_USBSTS_SLI - set to 1 when enters a suspend state from an active state
// USB_USBSTS_SRI - set at start of frame
// USB_USBSTS_SRI - set when USB reset detected

if (status & USB_USBSTS_UI) {
//print("data\r\n");
uint32_t setupstatus = USB1_ENDPTSETUPSTAT;
//printf("USB1_ENDPTSETUPSTAT=%X\r\n", setupstatus);
while (setupstatus) {
USB1_ENDPTSETUPSTAT = setupstatus;
setup_t s;
do {
USB1_USBCMD |= USB_USBCMD_SUTW;
s.word1 = endpoint_queue_head[0].setup0;
s.word2 = endpoint_queue_head[0].setup1;
} while (!(USB1_USBCMD & USB_USBCMD_SUTW));
USB1_USBCMD &= ~USB_USBCMD_SUTW;
//printf("setup %08lX %08lX\r\n", s.word1, s.word2);
USB1_ENDPTFLUSH = (1<<16) | (1<<0); // page 3174
while (USB1_ENDPTFLUSH & ((1<<16) | (1<<0))) ;
endpoint0_notify_mask = 0;
endpoint0_setup(s.bothwords);
setupstatus = USB1_ENDPTSETUPSTAT; // page 3175
}
uint32_t completestatus = USB1_ENDPTCOMPLETE;
if (completestatus) {
USB1_ENDPTCOMPLETE = completestatus;
//printf("USB1_ENDPTCOMPLETE=%lX\r\n", completestatus);
if (completestatus & endpoint0_notify_mask) {
endpoint0_notify_mask = 0;
endpoint0_complete();
}
if (completestatus & endpointN_notify_mask) {
// TODO: callback functions...
}
}
}
if (status & USB_USBSTS_URI) { // page 3164
USB1_ENDPTSETUPSTAT = USB1_ENDPTSETUPSTAT; // Clear all setup token semaphores
USB1_ENDPTCOMPLETE = USB1_ENDPTCOMPLETE; // Clear all the endpoint complete status
while (USB1_ENDPTPRIME != 0) ; // Wait for any endpoint priming
USB1_ENDPTFLUSH = 0xFFFFFFFF; // Cancel all endpoint primed status
if ((USB1_PORTSC1 & USB_PORTSC1_PR)) {
//print("reset\r\n");
} else {
// we took too long to respond :(
// TODO; is this ever really a problem?
//print("reset too slow\r\n");
}
// TODO: Free all allocated dTDs
//if (++reset_count >= 3) {
// shut off USB - easier to see results in protocol analyzer
//USB1_USBCMD &= ~USB_USBCMD_RS;
//print("shut off USB\r\n");
//}
}
if (status & USB_USBSTS_PCI) {
if (USB1_PORTSC1 & USB_PORTSC1_HSP) {
//print("port at 480 Mbit\r\n");
} else {
//print("port at 12 Mbit\r\n");
}
}
if (status & USB_USBSTS_SLI) { // page 3165
//print("suspend\r\n");
}
if (status & USB_USBSTS_UEI) {
//print("error\r\n");
}


}


/*
struct transfer_struct { // table 55-60, pg 3159
uint32_t next;
uint32_t status;
uint32_t pointer0;
uint32_t pointer1;
uint32_t pointer2;
uint32_t pointer3;
uint32_t pointer4;
uint32_t unused1;
};
transfer_t endpoint0_transfer_data __attribute__ ((aligned(32)));;
transfer_t endpoint0_transfer_ack __attribute__ ((aligned(32)));;
*/

static void endpoint0_setup(uint64_t setupdata)
{
setup_t setup;
uint32_t datalen = 0;
const usb_descriptor_list_t *list;

setup.bothwords = setupdata;
switch (setup.wRequestAndType) {
case 0x0500: // SET_ADDRESS
endpoint0_receive(NULL, 0, 0);
USB1_DEVICEADDR = USB_DEVICEADDR_USBADR(setup.wValue) | USB_DEVICEADDR_USBADRA;
return;
case 0x0900: // SET_CONFIGURATION
usb_configuration = setup.wValue;
// configure all other endpoints
volatile uint32_t *reg = &USB1_ENDPTCTRL1;
const uint32_t *cfg = usb_endpoint_config_table;
int i;
for (i=0; i < NUM_ENDPOINTS; i++) {
uint32_t n = *cfg++;
*reg = n;
// TODO: do the TRX & RXR bits self clear??
uint32_t m = n & ~(USB_ENDPTCTRL_TXR | USB_ENDPTCTRL_RXR);
*reg = m;
//uint32_t p = *reg;
//printf(" ep=%d: cfg=%08lX - %08lX - %08lX\r\n", i + 1, n, m, p);
reg++;
}
// TODO: configure all queue heads with max packet length, zlt & mult
endpoint_queue_head[CDC_ACM_ENDPOINT*2+1].config = (CDC_ACM_ENDPOINT << 16);
endpoint_queue_head[CDC_RX_ENDPOINT*2+0].config = (CDC_RX_SIZE << 16) | (1 << 29);
endpoint_queue_head[CDC_TX_ENDPOINT*2+1].config = (CDC_TX_SIZE << 16) | (1 << 29);

// TODO: de-allocate any pending transfers?
endpoint0_receive(NULL, 0, 0);
return;

case 0x0680: // GET_DESCRIPTOR
case 0x0681:
//printf("desc:\r\n"); // yay - sending device descriptor now works!!!!
for (list = usb_descriptor_list; list->addr != NULL; list++) {
if (setup.wValue == list->wValue && setup.wIndex == list->wIndex) {
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 (datalen > setup.wLength) datalen = setup.wLength;
endpoint0_transmit(list->addr, datalen, 0);
return;
}
}
break;
case 0x2221: // CDC_SET_CONTROL_LINE_STATE
//usb_cdc_line_rtsdtr_millis = systick_millis_count;
//usb_cdc_line_rtsdtr = setup.wValue;
case 0x2321: // CDC_SEND_BREAK
endpoint0_receive(NULL, 0, 0);
return;
case 0x2021: // CDC_SET_LINE_CODING
if (setup.wLength != 7) break;
endpoint0_setupdata.bothwords = setupdata;
endpoint0_receive(endpoint0_buffer, 7, 1);
return;
}
USB1_ENDPTCTRL0 = 0x000010001; // stall
}

static void endpoint0_transmit(const void *data, uint32_t len, int notify)
{
//printf("tx %lu\r\n", len);
if (len > 0) {
// Executing A Transfer Descriptor, page 3182
endpoint0_transfer_data.next = 1;
endpoint0_transfer_data.status = (len << 16) | (1<<7);
uint32_t addr = (uint32_t)data;
endpoint0_transfer_data.pointer0 = addr; // format: table 55-60, pg 3159
endpoint0_transfer_data.pointer1 = addr + 4096;
endpoint0_transfer_data.pointer2 = addr + 8192;
endpoint0_transfer_data.pointer3 = addr + 12288;
endpoint0_transfer_data.pointer4 = addr + 16384;
// Case 1: Link list is empty, page 3182
endpoint_queue_head[1].next = (uint32_t)&endpoint0_transfer_data;
endpoint_queue_head[1].status = 0;
USB1_ENDPTPRIME |= (1<<16);
while (USB1_ENDPTPRIME) ;
}
endpoint0_transfer_ack.next = 1;
endpoint0_transfer_ack.status = (1<<7) | (notify ? (1 << 15) : 0);
endpoint0_transfer_ack.pointer0 = 0;
endpoint_queue_head[0].next = (uint32_t)&endpoint0_transfer_ack;
endpoint_queue_head[0].status = 0;
USB1_ENDPTPRIME |= (1<<0);
endpoint0_notify_mask = (notify ? (1 << 0) : 0);
while (USB1_ENDPTPRIME) ;
}

static void endpoint0_receive(void *data, uint32_t len, int notify)
{
//printf("rx %lu\r\n", len);
if (len > 0) {
// Executing A Transfer Descriptor, page 3182
endpoint0_transfer_data.next = 1;
endpoint0_transfer_data.status = (len << 16) | (1<<7);
uint32_t addr = (uint32_t)data;
endpoint0_transfer_data.pointer0 = addr; // format: table 55-60, pg 3159
endpoint0_transfer_data.pointer1 = addr + 4096;
endpoint0_transfer_data.pointer2 = addr + 8192;
endpoint0_transfer_data.pointer3 = addr + 12288;
endpoint0_transfer_data.pointer4 = addr + 16384;
// Case 1: Link list is empty, page 3182
endpoint_queue_head[0].next = (uint32_t)&endpoint0_transfer_data;
endpoint_queue_head[0].status = 0;
USB1_ENDPTPRIME |= (1<<0);
while (USB1_ENDPTPRIME) ;
}
endpoint0_transfer_ack.next = 1;
endpoint0_transfer_ack.status = (1<<7) | (notify ? (1 << 15) : 0);
endpoint0_transfer_ack.pointer0 = 0;
endpoint_queue_head[1].next = (uint32_t)&endpoint0_transfer_ack;
endpoint_queue_head[1].status = 0;
USB1_ENDPTPRIME |= (1<<16);
endpoint0_notify_mask = (notify ? (1 << 16) : 0);
while (USB1_ENDPTPRIME) ;
}

/*typedef 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;
};
uint64_t bothwords;
} setup_t; */


static void endpoint0_complete(void)
{
setup_t setup;

setup.bothwords = endpoint0_setupdata.bothwords;
//print("complete\r\n");
#ifdef CDC_STATUS_INTERFACE
if (setup.wRequestAndType == 0x2021 /*CDC_SET_LINE_CODING*/) {
//memcpy(usb_cdc_line_coding, endpoint0_buffer, 7);
//if (usb_cdc_line_coding[0] == 134) usb_reboot_timer = 15;
}
#endif
}

void usb_prepare_transfer(transfer_t *transfer, const void *data, uint32_t len, uint32_t param)
{
transfer->next = 1;
transfer->status = (len << 16) | (1<<7);
uint32_t addr = (uint32_t)data;
transfer->pointer0 = addr;
transfer->pointer1 = addr + 4096;
transfer->pointer2 = addr + 8192;
transfer->pointer3 = addr + 12288;
transfer->pointer4 = addr + 16384;
transfer->callback_param = param;
}

void usb_transmit(int endpoint_number, transfer_t *transfer)
{
// endpoint 0 reserved for control
// endpoint 1 reserved for debug
//printf("usb_transmit %d\r\n", endpoint_number);
if (endpoint_number < 2 || endpoint_number > NUM_ENDPOINTS) return;
endpoint_t *endpoint = &endpoint_queue_head[endpoint_number * 2 + 1];
if (endpoint->callback_function) {
transfer->status |= (1<<15);
} else {
transfer->status |= (1<<15);
// remove all inactive transfers
}
uint32_t mask = 1 << (endpoint_number + 16);
__disable_irq();
#if 0
if (endpoint->last_transfer) {
if (!(endpoint->last_transfer->status & (1<<7))) {
endpoint->last_transfer->next = (uint32_t)transfer;
} else {
// Case 2: Link list is not empty, page 3182
endpoint->last_transfer->next = (uint32_t)transfer;
if (USB1_ENDPTPRIME & mask) {
endpoint->last_transfer = transfer;
__enable_irq();
printf(" case 2a\r\n");
return;
}
uint32_t stat;
uint32_t cmd = USB1_USBCMD;
do {
USB1_USBCMD = cmd | USB_USBCMD_ATDTW;
stat = USB1_ENDPTSTATUS;
} while (!(USB1_USBCMD & USB_USBCMD_ATDTW));
USB1_USBCMD = cmd & ~USB_USBCMD_ATDTW;
if (stat & mask) {
endpoint->last_transfer = transfer;
__enable_irq();
printf(" case 2b\r\n");
return;
}
}
} else {
endpoint->first_transfer = transfer;
}
endpoint->last_transfer = transfer;
#endif
// Case 1: Link list is empty, page 3182
endpoint->next = (uint32_t)transfer;
endpoint->status = 0;
USB1_ENDPTPRIME |= mask;
while (USB1_ENDPTPRIME & mask) ;
__enable_irq();
//printf(" case 1\r\n");


// ENDPTPRIME - momentarily set by hardware during hardware re-priming
// operations when a dTD is retired, and the dQH is updated.

// ENDPTSTAT - Transmit Buffer Ready - set to one by the hardware as a
// response to receiving a command from a corresponding bit
// in the ENDPTPRIME register. . Buffer ready is cleared by
// USB reset, by the USB DMA system, or through the ENDPTFLUSH
// register. (so 0=buffer ready, 1=buffer primed for transmit)

}

/*struct endpoint_struct {
uint32_t config;
uint32_t current;
uint32_t next;
uint32_t status;
uint32_t pointer0;
uint32_t pointer1;
uint32_t pointer2;
uint32_t pointer3;
uint32_t pointer4;
uint32_t reserved;
uint32_t setup0;
uint32_t setup1;
transfer_t *first_transfer;
transfer_t *last_transfer;
void (*callback_function)(transfer_t *completed_transfer);
uint32_t unused1;
};*/






























+ 1614
- 0
teensy4/usb_desc.c
File diff suppressed because it is too large
View File


+ 889
- 0
teensy4/usb_desc.h View File

@@ -0,0 +1,889 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2017 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.
*/

#pragma once

// 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_TRANSMIT_UNUSED 0x00020000
#define ENDPOINT_TRANSMIT_ISOCHRONOUS 0x00C40000
#define ENDPOINT_TRANSMIT_BULK 0x00C80000
#define ENDPOINT_TRANSMIT_INTERRUPT 0x00CC0000
#define ENDPOINT_RECEIVE_UNUSED 0x00000002
#define ENDPOINT_RECEIVE_ISOCHRONOUS 0x000000C4
#define ENDPOINT_RECEIVE_BULK 0x000000C8
#define ENDPOINT_RECEIVE_INTERRUPT 0x000000CC

/*
Each group of #define lines below corresponds to one of the
settings in the Tools > USB Type menu. This file defines what
type of USB device is actually created for each of those menu
options.

Each "interface" is a set of functionality your PC or Mac will
use and treat as if it is a unique device. Within each interface,
the "endpoints" are the actual communication channels. Most
interfaces use 1, 2 or 3 endpoints. By editing only this file,
you can customize the USB Types to be any collection of interfaces.

To modify a USB Type, 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 total number of interfaces.

Next, assign unique endpoint numbers to all the endpoints across
all the interfaces your device has. You can reuse an endpoint
number for transmit and receive, but the same endpoint number must
not be used twice to transmit, or twice to receive.

Most endpoints also require their maximum size, and some also
need an interval specification (the number of milliseconds the
PC will check for data from that endpoint). For existing
interfaces, usually these other settings should not be changed.

Edit NUM_ENDPOINTS to be at least the largest endpoint number used.

Edit NUM_USB_BUFFERS to control how much memory the USB stack will
allocate. At least 2 should be used for each endpoint. More
memory will allow higher throughput for user programs that have
high latency (eg, spending time doing things other than interacting
with the USB).

Edit the ENDPOINT*_CONFIG lines so each endpoint is configured
the proper way (transmit, receive, or both).

If you are using existing interfaces (making your own device with
a different set of interfaces) the code in all other files should
automatically adapt to the new endpoints you specify here.

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. Usually, a pair of files are added for the actual code,
and code is also added in usb_dev.c for any control transfers,
interrupt-level code, or other very low-level stuff not possible
from the packet send/receive functons. Code also is added in
usb_inst.c to create an instance of your C++ object. This message
gives a quick summary of things you will need to know:
https://forum.pjrc.com/threads/49045?p=164512&viewfull=1#post164512

You may edit the Vendor and Product ID numbers, and strings. If
the numbers are changed, Teensyduino may not be able to automatically
find and reboot your board when you click the Upload button in
the Arduino IDE. You will need to press the Program button on
Teensy to initiate programming.

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 ENDPOINT2_CONFIG ENDPOINT_RECEIVE_INTERRUPT + ENDPOINT_TRANSMIT_UNUSED
#define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_BULK + ENDPOINT_TRANSMIT_UNUSED
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_UNUSED + ENDPOINT_TRANSMIT_BULK
//#define ENDPOINT2_CONFIG ENDPOINT_TRANSMIT_ONLY
//#define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY
//#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY

#elif defined(USB_KEYBOARDONLY)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x04D0
#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'}
#define PRODUCT_NAME_LEN 8
#define EP0_SIZE 64
#define NUM_ENDPOINTS 4
#define NUM_USB_BUFFERS 14
#define NUM_INTERFACE 3
#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 KEYBOARD_INTERFACE 0 // Keyboard
#define KEYBOARD_ENDPOINT 3
#define KEYBOARD_SIZE 8
#define KEYBOARD_INTERVAL 1
#define KEYMEDIA_INTERFACE 2 // Keyboard Media Keys
#define KEYMEDIA_ENDPOINT 4
#define KEYMEDIA_SIZE 8
#define KEYMEDIA_INTERVAL 4
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_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 6
#define NUM_USB_BUFFERS 24
#define NUM_INTERFACE 5
#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 KEYMEDIA_INTERFACE 4 // Keyboard Media Keys
#define KEYMEDIA_ENDPOINT 6
#define KEYMEDIA_SIZE 8
#define KEYMEDIA_INTERVAL 4
#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 12 // 12 = normal, 64 = extreme joystick
#define JOYSTICK_INTERVAL 2
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_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 7
#define NUM_USB_BUFFERS 30
#define NUM_INTERFACE 6
#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 KEYMEDIA_INTERFACE 5 // Keyboard Media Keys
#define KEYMEDIA_ENDPOINT 7
#define KEYMEDIA_SIZE 8
#define KEYMEDIA_INTERVAL 4
#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 12 // 12 = normal, 64 = extreme joystick
#define JOYSTICK_INTERVAL 1
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT7_CONFIG ENDPOINT_TRANSMIT_ONLY

#elif defined(USB_TOUCHSCREEN)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x04D3
#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','/','T','o','u','c','h','s','c','r','e','e','n'}
#define PRODUCT_NAME_LEN 20
#define EP0_SIZE 64
#define NUM_ENDPOINTS 5
#define NUM_USB_BUFFERS 15
#define NUM_INTERFACE 4
#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 KEYBOARD_INTERFACE 0 // Keyboard
#define KEYBOARD_ENDPOINT 3
#define KEYBOARD_SIZE 8
#define KEYBOARD_INTERVAL 1
#define KEYMEDIA_INTERFACE 2 // Keyboard Media Keys
#define KEYMEDIA_ENDPOINT 4
#define KEYMEDIA_SIZE 8
#define KEYMEDIA_INTERVAL 4
#define MULTITOUCH_INTERFACE 3 // Touchscreen
#define MULTITOUCH_ENDPOINT 5
#define MULTITOUCH_SIZE 8
#define MULTITOUCH_FINGERS 10
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY

#elif defined(USB_HID_TOUCHSCREEN)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x04D4
#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','/','T','o','u','c','h','s','c','r','e','e','n'}
#define PRODUCT_NAME_LEN 26
#define EP0_SIZE 64
#define NUM_ENDPOINTS 6
#define NUM_USB_BUFFERS 20
#define NUM_INTERFACE 5
#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 KEYMEDIA_INTERFACE 3 // Keyboard Media Keys
#define KEYMEDIA_ENDPOINT 4
#define KEYMEDIA_SIZE 8
#define KEYMEDIA_INTERVAL 4
#define MOUSE_INTERFACE 1 // Mouse
#define MOUSE_ENDPOINT 6
#define MOUSE_SIZE 8
#define MOUSE_INTERVAL 2
#define MULTITOUCH_INTERFACE 4 // Touchscreen
#define MULTITOUCH_ENDPOINT 5
#define MULTITOUCH_SIZE 8
#define MULTITOUCH_FINGERS 10
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_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_NUM_CABLES 1
#define MIDI_TX_ENDPOINT 3
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 4
#define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY

#elif defined(USB_MIDI4)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x0485
#define BCD_DEVICE 0x0211
#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','x','4'}
#define PRODUCT_NAME_LEN 13
#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_NUM_CABLES 4
#define MIDI_TX_ENDPOINT 3
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 4
#define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY

#elif defined(USB_MIDI16)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x0485
#define BCD_DEVICE 0x0212
#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','x','1','6'}
#define PRODUCT_NAME_LEN 14
#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_NUM_CABLES 16
#define MIDI_TX_ENDPOINT 3
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 4
#define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY

#elif defined(USB_MIDI_SERIAL)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x0489
#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 5
#define NUM_USB_BUFFERS 30
#define NUM_INTERFACE 3
#define CDC_IAD_DESCRIPTOR 1
#define CDC_STATUS_INTERFACE 0
#define CDC_DATA_INTERFACE 1 // Serial
#define CDC_ACM_ENDPOINT 1
#define CDC_RX_ENDPOINT 2
#define CDC_TX_ENDPOINT 3
#define CDC_ACM_SIZE 16
#define CDC_RX_SIZE 64
#define CDC_TX_SIZE 64
#define MIDI_INTERFACE 2 // MIDI
#define MIDI_NUM_CABLES 1
#define MIDI_TX_ENDPOINT 4
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 5
#define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY

#elif defined(USB_MIDI4_SERIAL)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x0489
#define BCD_DEVICE 0x0211
#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','x','4'}
#define PRODUCT_NAME_LEN 13
#define EP0_SIZE 64
#define NUM_ENDPOINTS 5
#define NUM_USB_BUFFERS 30
#define NUM_INTERFACE 3
#define CDC_IAD_DESCRIPTOR 1
#define CDC_STATUS_INTERFACE 0
#define CDC_DATA_INTERFACE 1 // Serial
#define CDC_ACM_ENDPOINT 1
#define CDC_RX_ENDPOINT 2
#define CDC_TX_ENDPOINT 3
#define CDC_ACM_SIZE 16
#define CDC_RX_SIZE 64
#define CDC_TX_SIZE 64
#define MIDI_INTERFACE 2 // MIDI
#define MIDI_NUM_CABLES 4
#define MIDI_TX_ENDPOINT 4
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 5
#define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY

#elif defined(USB_MIDI16_SERIAL)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x0489
#define BCD_DEVICE 0x0212
#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','x','1','6'}
#define PRODUCT_NAME_LEN 14
#define EP0_SIZE 64
#define NUM_ENDPOINTS 5
#define NUM_USB_BUFFERS 30
#define NUM_INTERFACE 3
#define CDC_IAD_DESCRIPTOR 1
#define CDC_STATUS_INTERFACE 0
#define CDC_DATA_INTERFACE 1 // Serial
#define CDC_ACM_ENDPOINT 1
#define CDC_RX_ENDPOINT 2
#define CDC_TX_ENDPOINT 3
#define CDC_ACM_SIZE 16
#define CDC_RX_SIZE 64
#define CDC_TX_SIZE 64
#define MIDI_INTERFACE 2 // MIDI
#define MIDI_NUM_CABLES 16
#define MIDI_TX_ENDPOINT 4
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 5
#define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT5_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 4
#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 ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_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 ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY

#elif defined(USB_FLIGHTSIM_JOYSTICK)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x0488
#define BCD_DEVICE 0x0211
#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 5
#define NUM_USB_BUFFERS 20
#define NUM_INTERFACE 3
#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 JOYSTICK_INTERFACE 2 // Joystick
#define JOYSTICK_ENDPOINT 5
#define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick
#define JOYSTICK_INTERVAL 1
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY


#elif defined(USB_MTPDISK)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x04D1
#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','T','P',' ','D','i','s','k'}
#define PRODUCT_NAME_LEN 15
#define EP0_SIZE 64
#define NUM_ENDPOINTS 4
#define NUM_USB_BUFFERS 20
#define NUM_INTERFACE 2
#define MTP_INTERFACE 0 // MTP Disk
#define MTP_TX_ENDPOINT 3
#define MTP_TX_SIZE 64
#define MTP_RX_ENDPOINT 3
#define MTP_RX_SIZE 64
#define MTP_EVENT_ENDPOINT 4
#define MTP_EVENT_SIZE 16
#define MTP_EVENT_INTERVAL 10
#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 ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY

#elif defined(USB_AUDIO)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x04D2
#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',' ','A','u','d','i','o'}
#define PRODUCT_NAME_LEN 12
#define EP0_SIZE 64
#define NUM_ENDPOINTS 5
#define NUM_USB_BUFFERS 16
#define NUM_INTERFACE 4
#define SEREMU_INTERFACE 0 // 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 AUDIO_INTERFACE 1 // Audio (uses 3 consecutive interfaces)
#define AUDIO_TX_ENDPOINT 3
#define AUDIO_TX_SIZE 180
#define AUDIO_RX_ENDPOINT 4
#define AUDIO_RX_SIZE 180
#define AUDIO_SYNC_ENDPOINT 5
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ISOCHRONOUS
#define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS

#elif defined(USB_MIDI_AUDIO_SERIAL)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x048A
#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','/','A','u','d','i','o'}
#define PRODUCT_NAME_LEN 17
#define EP0_SIZE 64
#define NUM_ENDPOINTS 8
#define NUM_USB_BUFFERS 30
#define NUM_INTERFACE 6
#define CDC_IAD_DESCRIPTOR 1
#define CDC_STATUS_INTERFACE 0
#define CDC_DATA_INTERFACE 1 // Serial
#define CDC_ACM_ENDPOINT 1
#define CDC_RX_ENDPOINT 2
#define CDC_TX_ENDPOINT 3
#define CDC_ACM_SIZE 16
#define CDC_RX_SIZE 64
#define CDC_TX_SIZE 64
#define MIDI_INTERFACE 2 // MIDI
#define MIDI_NUM_CABLES 1
#define MIDI_TX_ENDPOINT 4
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 5
#define MIDI_RX_SIZE 64
#define AUDIO_INTERFACE 3 // Audio (uses 3 consecutive interfaces)
#define AUDIO_TX_ENDPOINT 6
#define AUDIO_TX_SIZE 180
#define AUDIO_RX_ENDPOINT 7
#define AUDIO_RX_SIZE 180
#define AUDIO_SYNC_ENDPOINT 8
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS
#define ENDPOINT7_CONFIG ENDPOINT_RECEIVE_ISOCHRONOUS
#define ENDPOINT8_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS

#elif defined(USB_MIDI16_AUDIO_SERIAL)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x048A
#define BCD_DEVICE 0x0212
#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','x','1','6','/','A','u','d','i','o'}
#define PRODUCT_NAME_LEN 20
#define EP0_SIZE 64
#define NUM_ENDPOINTS 8
#define NUM_USB_BUFFERS 30
#define NUM_INTERFACE 6
#define CDC_IAD_DESCRIPTOR 1
#define CDC_STATUS_INTERFACE 0
#define CDC_DATA_INTERFACE 1 // Serial
#define CDC_ACM_ENDPOINT 1
#define CDC_RX_ENDPOINT 2
#define CDC_TX_ENDPOINT 3
#define CDC_ACM_SIZE 16
#define CDC_RX_SIZE 64
#define CDC_TX_SIZE 64
#define MIDI_INTERFACE 2 // MIDI
#define MIDI_NUM_CABLES 16
#define MIDI_TX_ENDPOINT 4
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 5
#define MIDI_RX_SIZE 64
#define AUDIO_INTERFACE 3 // Audio (uses 3 consecutive interfaces)
#define AUDIO_TX_ENDPOINT 6
#define AUDIO_TX_SIZE 180
#define AUDIO_RX_ENDPOINT 7
#define AUDIO_RX_SIZE 180
#define AUDIO_SYNC_ENDPOINT 8
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS
#define ENDPOINT7_CONFIG ENDPOINT_RECEIVE_ISOCHRONOUS
#define ENDPOINT8_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS

#elif defined(USB_EVERYTHING)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x0476
#define RAWHID_USAGE_PAGE 0xFFAB // recommended: 0xFF00 to 0xFFFF
#define RAWHID_USAGE 0x0200 // recommended: 0x0100 to 0xFFFF
#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 {'A','l','l',' ','T','h','e',' ','T','h','i','n','g','s'}
#define PRODUCT_NAME_LEN 14
#define EP0_SIZE 64
#define NUM_ENDPOINTS 15
#define NUM_USB_BUFFERS 31
#define NUM_INTERFACE 13
#define CDC_IAD_DESCRIPTOR 1
#define CDC_STATUS_INTERFACE 0
#define CDC_DATA_INTERFACE 1 // Serial
#define CDC_ACM_ENDPOINT 1
#define CDC_RX_ENDPOINT 2
#define CDC_TX_ENDPOINT 2
#define CDC_ACM_SIZE 16
#define CDC_RX_SIZE 64
#define CDC_TX_SIZE 64
#define MIDI_INTERFACE 2 // MIDI
#define MIDI_NUM_CABLES 16
#define MIDI_TX_ENDPOINT 3
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 3
#define MIDI_RX_SIZE 64
#define KEYBOARD_INTERFACE 3 // Keyboard
#define KEYBOARD_ENDPOINT 4
#define KEYBOARD_SIZE 8
#define KEYBOARD_INTERVAL 1
#define MOUSE_INTERFACE 4 // Mouse
#define MOUSE_ENDPOINT 5
#define MOUSE_SIZE 8
#define MOUSE_INTERVAL 2
#define RAWHID_INTERFACE 5 // RawHID
#define RAWHID_TX_ENDPOINT 6
#define RAWHID_TX_SIZE 64
#define RAWHID_TX_INTERVAL 1
#define RAWHID_RX_ENDPOINT 6
#define RAWHID_RX_SIZE 64
#define RAWHID_RX_INTERVAL 1
#define FLIGHTSIM_INTERFACE 6 // Flight Sim Control
#define FLIGHTSIM_TX_ENDPOINT 9
#define FLIGHTSIM_TX_SIZE 64
#define FLIGHTSIM_TX_INTERVAL 1
#define FLIGHTSIM_RX_ENDPOINT 9
#define FLIGHTSIM_RX_SIZE 64
#define FLIGHTSIM_RX_INTERVAL 1
#define JOYSTICK_INTERFACE 7 // Joystick
#define JOYSTICK_ENDPOINT 10
#define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick
#define JOYSTICK_INTERVAL 1
/*
#define MTP_INTERFACE 8 // MTP Disk
#define MTP_TX_ENDPOINT 11
#define MTP_TX_SIZE 64
#define MTP_RX_ENDPOINT 3
#define MTP_RX_SIZE 64
#define MTP_EVENT_ENDPOINT 11
#define MTP_EVENT_SIZE 16
#define MTP_EVENT_INTERVAL 10
*/
#define KEYMEDIA_INTERFACE 8 // Keyboard Media Keys
#define KEYMEDIA_ENDPOINT 12
#define KEYMEDIA_SIZE 8
#define KEYMEDIA_INTERVAL 4
#define AUDIO_INTERFACE 9 // Audio (uses 3 consecutive interfaces)
#define AUDIO_TX_ENDPOINT 13
#define AUDIO_TX_SIZE 180
#define AUDIO_RX_ENDPOINT 13
#define AUDIO_RX_SIZE 180
#define AUDIO_SYNC_ENDPOINT 14
#define MULTITOUCH_INTERFACE 12 // Touchscreen
#define MULTITOUCH_ENDPOINT 15
#define MULTITOUCH_SIZE 8
#define MULTITOUCH_FINGERS 10
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE
#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE
#define ENDPOINT7_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE
#define ENDPOINT8_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT9_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE
#define ENDPOINT10_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT11_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE
#define ENDPOINT12_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT13_CONFIG (ENDPOINT_RECEIVE_ISOCHRONOUS|ENDPOINT_TRANSMIT_ISOCHRONOUS)
#define ENDPOINT14_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS
#define ENDPOINT15_CONFIG ENDPOINT_TRANSMIT_ONLY

#endif

#ifdef USB_DESC_LIST_DEFINE
#if defined(NUM_ENDPOINTS) && NUM_ENDPOINTS > 0
// NUM_ENDPOINTS = number of non-zero endpoints (0 to 7)
extern const uint32_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 // NUM_ENDPOINTS
#endif // USB_DESC_LIST_DEFINE


+ 21
- 0
teensy4/usb_dev.h View File

@@ -0,0 +1,21 @@
#pragma once
#include "imxrt.h"

typedef struct transfer_struct transfer_t;
struct transfer_struct {
uint32_t next;
uint32_t status;
uint32_t pointer0;
uint32_t pointer1;
uint32_t pointer2;
uint32_t pointer3;
uint32_t pointer4;
uint32_t callback_param;
};

void usb_init(void);

void usb_prepare_transfer(transfer_t *transfer, const void *data, uint32_t len, uint32_t param);
void usb_transmit(int endpoint_number, transfer_t *transfer);



+ 57
- 0
teensy4/usb_names.h View File

@@ -0,0 +1,57 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2017 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

+ 337
- 0
teensy4/usb_serial.c View File

@@ -0,0 +1,337 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2017 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 "delay.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)
//#if F_CPU >= 20000000

uint32_t usb_cdc_line_coding[2];
volatile uint32_t usb_cdc_line_rtsdtr_millis;
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)
{
#if 0
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;
#endif
return -1;
}

// peek at the next character, or -1 if nothing received
int usb_serial_peekchar(void)
{
#if 0
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];
#endif
return -1;
}

// number of bytes available in the receive buffer
int usb_serial_available(void)
{
#if 0
int count;
count = usb_rx_byte_count(CDC_RX_ENDPOINT);
if (rx_packet) count += rx_packet->len - rx_packet->index;
return count;
#endif
return 0;
}

// read a block of bytes to a buffer
int usb_serial_read(void *buffer, uint32_t size)
{
#if 0
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;
#endif
return 0;
}

// discard any buffered input
void usb_serial_flush_input(void)
{
#if 0
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);
}
#endif
}

// 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 == 240000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1600)
#elif F_CPU == 216000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440)
#elif F_CPU == 192000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1280)
#elif F_CPU == 180000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1200)
#elif F_CPU == 168000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1100)
#elif F_CPU == 144000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 932)
#elif F_CPU == 120000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 764)
#elif F_CPU == 96000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596)
#elif F_CPU == 72000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 512)
#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);
}


static transfer_t transfer __attribute__ ((used, aligned(32)));
static uint8_t txbuffer[256];

int usb_serial_write(const void *buffer, uint32_t size)
{

if (size > sizeof(txbuffer)) size = sizeof(txbuffer);
memcpy(txbuffer, buffer, size);
usb_prepare_transfer(&transfer, txbuffer, size, 0);
usb_transmit(CDC_TX_ENDPOINT, &transfer);

#if 0
uint32_t ret = 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 ret;
#endif
return 0;
}

int usb_serial_write_buffer_free(void)
{
#if 0
uint32_t len;

tx_noautoflush = 1;
if (!tx_packet) {
if (!usb_configuration ||
usb_tx_packet_count(CDC_TX_ENDPOINT) >= TX_PACKET_LIMIT ||
(tx_packet = usb_malloc()) == NULL) {
tx_noautoflush = 0;
return 0;
}
}
len = CDC_TX_SIZE - tx_packet->index;
// TODO: Perhaps we need "usb_cdc_transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT"
// added here, so the SOF interrupt can't take away the available buffer
// space we just promised the user could write without blocking?
// But does this come with other performance downsides? Could it lead to
// buffer data never actually transmitting in some usage cases? More
// investigation is needed.
// https://github.com/PaulStoffregen/cores/issues/10#issuecomment-61514955
tx_noautoflush = 0;
return len;
#endif
return 0;
}

void usb_serial_flush_output(void)
{
#if 0
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;
#endif
}

void usb_serial_flush_callback(void)
{
#if 0
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
}



//#endif // F_CPU
#endif // CDC_STATUS_INTERFACE && CDC_DATA_INTERFACE

+ 127
- 0
teensy4/usb_serial.h View File

@@ -0,0 +1,127 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2017 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.
*/

#pragma once

#include "usb_desc.h"

#if (defined(CDC_STATUS_INTERFACE) && defined(CDC_DATA_INTERFACE)) || defined(USB_DISABLED)

#include <stdint.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);
int usb_serial_write_buffer_free(void);
void usb_serial_flush_output(void);
extern uint32_t usb_cdc_line_coding[2];
extern volatile uint32_t usb_cdc_line_rtsdtr_millis;
extern volatile uint32_t systick_millis_count;
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:
constexpr usb_serial_class() {}
void begin(long) {
//uint32_t millis_begin = systick_millis_count;
//disabled for now - causes more trouble than it solves?
//while (!(*this)) {
// wait up to 2.5 seconds for Arduino Serial Monitor
// Yes, this is a long time, but some Windows systems open
// the port very slowly. This wait allows programs for
// Arduino Uno to "just work" (without forcing a reboot when
// the port is opened), and when no PC is connected the user's
// sketch still gets to run normally after this wait time.
//if ((uint32_t)(systick_millis_count - millis_begin) > 2500) break;
//}
}
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 void clear(void) { usb_serial_flush_input(); }
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); }
virtual int availableForWrite() { return usb_serial_write_buffer_free(); }
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) &&
((uint32_t)(systick_millis_count - usb_cdc_line_rtsdtr_millis) >= 15);
}
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;
extern void serialEvent(void);
#endif // __cplusplus


#endif // CDC_STATUS_INTERFACE && CDC_DATA_INTERFACE


+ 197
- 0
teensy4/wiring.h View File

@@ -0,0 +1,197 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2017 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 Wiring_h
#define Wiring_h

#include <stdint.h>
#include <stdlib.h>
#include "binary.h"
#include "core_id.h"
#include "core_pins.h"

// type_traits interferes with min() and other defines
// include it early, so we can define these later
// for Arduino compatibility
#ifdef __cplusplus
#include <type_traits>
// when the input number is an integer type, do all math as 32 bit signed long
template <class T, class A, class B, class C, class D>
long map(T _x, A _in_min, B _in_max, C _out_min, D _out_max, typename std::enable_if<std::is_integral<T>::value >::type* = 0)
{
long x = _x, in_min = _in_min, in_max = _in_max, out_min = _out_min, out_max = _out_max;
// Arduino's traditional algorithm
//return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
// st42's suggestion: https://github.com/arduino/Arduino/issues/2466#issuecomment-69873889
// more conversation:
// https://forum.pjrc.com/threads/44503-map()-function-improvements
if ((in_max - in_min) > (out_max - out_min)) {
return (x - in_min) * (out_max - out_min+1) / (in_max - in_min+1) + out_min;
} else {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
}
// when the input is a float or double, do all math using the input's type
template <class T, class A, class B, class C, class D>
T map(T x, A in_min, B in_max, C out_min, D out_max, typename std::enable_if<std::is_floating_point<T>::value >::type* = 0)
{
return (x - (T)in_min) * ((T)out_max - (T)out_min) / ((T)in_max - (T)in_min) + (T)out_min;
}
//#include <algorithm> // this isn't really needed, is it? (slows down compiling)
#include <utility>
// https://forum.pjrc.com/threads/44596-Teensyduino-1-37-Beta-2-(Arduino-1-8-3-support)?p=145150&viewfull=1#post145150
template<class A, class B>
constexpr auto min(A&& a, B&& b) -> decltype(a < b ? std::forward<A>(a) : std::forward<B>(b)) {
return a < b ? std::forward<A>(a) : std::forward<B>(b);
}
template<class A, class B>
constexpr auto max(A&& a, B&& b) -> decltype(a < b ? std::forward<A>(a) : std::forward<B>(b)) {
return a >= b ? std::forward<A>(a) : std::forward<B>(b);
}
#else // not C++
#define min(a, b) ({ \
typeof(a) _a = (a); \
typeof(b) _b = (b); \
(_a < _b) ? _a : _b; \
})
#define max(a, b) ({ \
typeof(a) _a = (a); \
typeof(b) _b = (b); \
(_a > _b) ? _a : _b; \
})
#endif


#ifdef PI
#undef PI
#endif
#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

#if __cplusplus >= 201103L && defined(__STRICT_ANSI__)
#define typeof(a) decltype(a)
#endif

#define abs(x) ({ \
typeof(x) _x = (x); \
(_x > 0) ? _x : -_x; \
})
#define constrain(amt, low, high) ({ \
typeof(amt) _amt = (amt); \
typeof(low) _low = (low); \
typeof(high) _high = (high); \
(_amt < _low) ? _low : ((_amt > _high) ? _high : _amt); \
})
#define round(x) ({ \
typeof(x) _x = (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) ({ \
typeof(x) _x = (x); \
_x * _x; \
})

#ifdef __cplusplus
extern "C"{
#endif

extern double exp10(double x);
extern float exp10f(float x);
extern long double exp10l(long double x);
extern double pow10(double x);
extern float pow10f(float x);
extern long double pow10l(long double x);

#define stricmp(a, b) strcasecmp(a, b)

#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 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 setup(void);
void loop(void);

#ifdef __cplusplus
} // extern "C"
#endif

// fix C++ boolean issue
// https://github.com/arduino/Arduino/pull/2151
#ifdef __cplusplus
typedef bool boolean;
#else
typedef uint8_t boolean;
#define false 0
#define true (!false)
#endif

#endif

Loading…
Cancel
Save