@@ -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 |
@@ -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); | |||
} |
@@ -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 |
@@ -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(); | |||
} | |||
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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) | |||
{ | |||
} | |||
@@ -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 |
@@ -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 | |||
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -0,0 +1,168 @@ | |||
/* | |||
WCharacter.h - Character utility functions for Wiring & Arduino | |||
Copyright (c) 2010 Hernando Barragan. All right reserved. | |||
This library is free software; you can redistribute it and/or | |||
modify it under the terms of the GNU Lesser General Public | |||
License as published by the Free Software Foundation; either | |||
version 2.1 of the License, or (at your option) any later version. | |||
This library is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public | |||
License along with this library; if not, write to the Free Software | |||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |||
*/ | |||
#ifndef Character_h | |||
#define Character_h | |||
#include <ctype.h> | |||
// WCharacter.h prototypes | |||
inline boolean isAlphaNumeric(int c) __attribute__((always_inline)); | |||
inline boolean isAlpha(int c) __attribute__((always_inline)); | |||
inline boolean isAscii(int c) __attribute__((always_inline)); | |||
inline boolean isWhitespace(int c) __attribute__((always_inline)); | |||
inline boolean isControl(int c) __attribute__((always_inline)); | |||
inline boolean isDigit(int c) __attribute__((always_inline)); | |||
inline boolean isGraph(int c) __attribute__((always_inline)); | |||
inline boolean isLowerCase(int c) __attribute__((always_inline)); | |||
inline boolean isPrintable(int c) __attribute__((always_inline)); | |||
inline boolean isPunct(int c) __attribute__((always_inline)); | |||
inline boolean isSpace(int c) __attribute__((always_inline)); | |||
inline boolean isUpperCase(int c) __attribute__((always_inline)); | |||
inline boolean isHexadecimalDigit(int c) __attribute__((always_inline)); | |||
inline int toAscii(int c) __attribute__((always_inline)); | |||
inline int toLowerCase(int c) __attribute__((always_inline)); | |||
inline int toUpperCase(int c)__attribute__((always_inline)); | |||
// Checks for an alphanumeric character. | |||
// It is equivalent to (isalpha(c) || isdigit(c)). | |||
inline boolean isAlphaNumeric(int c) | |||
{ | |||
return ( isalnum(c) == 0 ? false : true); | |||
} | |||
// Checks for an alphabetic character. | |||
// It is equivalent to (isupper(c) || islower(c)). | |||
inline boolean isAlpha(int c) | |||
{ | |||
return ( isalpha(c) == 0 ? false : true); | |||
} | |||
// Checks whether c is a 7-bit unsigned char value | |||
// that fits into the ASCII character set. | |||
inline boolean isAscii(int c) | |||
{ | |||
return ( isascii (c) == 0 ? false : true); | |||
} | |||
// Checks for a blank character, that is, a space or a tab. | |||
inline boolean isWhitespace(int c) | |||
{ | |||
return ( isblank (c) == 0 ? false : true); | |||
} | |||
// Checks for a control character. | |||
inline boolean isControl(int c) | |||
{ | |||
return ( iscntrl (c) == 0 ? false : true); | |||
} | |||
// Checks for a digit (0 through 9). | |||
inline boolean isDigit(int c) | |||
{ | |||
return ( isdigit (c) == 0 ? false : true); | |||
} | |||
// Checks for any printable character except space. | |||
inline boolean isGraph(int c) | |||
{ | |||
return ( isgraph (c) == 0 ? false : true); | |||
} | |||
// Checks for a lower-case character. | |||
inline boolean isLowerCase(int c) | |||
{ | |||
return (islower (c) == 0 ? false : true); | |||
} | |||
// Checks for any printable character including space. | |||
inline boolean isPrintable(int c) | |||
{ | |||
return ( isprint (c) == 0 ? false : true); | |||
} | |||
// Checks for any printable character which is not a space | |||
// or an alphanumeric character. | |||
inline boolean isPunct(int c) | |||
{ | |||
return ( ispunct (c) == 0 ? false : true); | |||
} | |||
// Checks for white-space characters. For the avr-libc library, | |||
// these are: space, formfeed ('\f'), newline ('\n'), carriage | |||
// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). | |||
inline boolean isSpace(int c) | |||
{ | |||
return ( isspace (c) == 0 ? false : true); | |||
} | |||
// Checks for an uppercase letter. | |||
inline boolean isUpperCase(int c) | |||
{ | |||
return ( isupper (c) == 0 ? false : true); | |||
} | |||
// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7 | |||
// 8 9 a b c d e f A B C D E F. | |||
inline boolean isHexadecimalDigit(int c) | |||
{ | |||
return ( isxdigit (c) == 0 ? false : true); | |||
} | |||
// Converts c to a 7-bit unsigned char value that fits into the | |||
// ASCII character set, by clearing the high-order bits. | |||
inline int toAscii(int c) | |||
{ | |||
return toascii (c); | |||
} | |||
// Warning: | |||
// Many people will be unhappy if you use this function. | |||
// This function will convert accented letters into random | |||
// characters. | |||
// Converts the letter c to lower case, if possible. | |||
inline int toLowerCase(int c) | |||
{ | |||
return tolower (c); | |||
} | |||
// Converts the letter c to upper case, if possible. | |||
inline int toUpperCase(int c) | |||
{ | |||
return toupper (c); | |||
} | |||
#endif |
@@ -0,0 +1,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 |
@@ -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 |
@@ -0,0 +1 @@ | |||
// This header file is in the public domain. |
@@ -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" |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 +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 |
@@ -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 |
@@ -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 | |||
}; | |||
@@ -0,0 +1,5 @@ | |||
// This header file is in the public domain. | |||
#ifndef CORE_TEENSY | |||
#define CORE_TEENSY | |||
#endif |
@@ -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 | |||
@@ -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 |
@@ -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 |
@@ -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; | |||
} | |||
@@ -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; | |||
} | |||
@@ -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 |
@@ -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"); |
@@ -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) } | |||
} |
@@ -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 |
@@ -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; | |||
} | |||
} | |||
@@ -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; | |||
};*/ | |||
@@ -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 | |||
@@ -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); | |||
@@ -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 |
@@ -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 |
@@ -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 | |||
@@ -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 |