// This header file is in the public domain. | |||||
#ifndef Arduino_h | |||||
#define Arduino_h | |||||
#include "WProgram.h" | |||||
#include "pins_arduino.h" | |||||
#endif |
// 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); | |||||
} |
/* | |||||
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 |
/* 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(); | |||||
} | |||||
/* 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 |
/* 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 |
/* | |||||
* | |||||
* 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 |
/* 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) | |||||
{ | |||||
} | |||||
/* 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 |
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 | |||||
/* 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 |
/* | |||||
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 |
/* | |||||
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 |
/* | |||||
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 |
/* | |||||
* 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 |
/* | |||||
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 |
/* 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 |
/* | |||||
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 |
// This header file is in the public domain. |
/* 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" |
/* 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 |
/* 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 |
/* 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 |
// 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 |
/* 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 |
// 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 |
//#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 | |||||
}; | |||||
// This header file is in the public domain. | |||||
#ifndef CORE_TEENSY | |||||
#define CORE_TEENSY | |||||
#endif |
/* 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 | |||||
#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 |
#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 |
#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; | |||||
} | |||||
#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; | |||||
} | |||||
/* 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 |
// i.MX RT1050 Reference Manual, Rev. 1, 03/2018 | // i.MX RT1050 Reference Manual, Rev. 1, 03/2018 | ||||
// ARM v7-M Architecture Reference Manual (DDI 0403E.b) | // ARM v7-M Architecture Reference Manual (DDI 0403E.b) | ||||
#if !defined(KINETISL) && !defined(KINETISK) | |||||
enum IRQ_NUMBER_t { | enum IRQ_NUMBER_t { | ||||
IRQ_DMA_CH0 = 0, | IRQ_DMA_CH0 = 0, | ||||
IRQ_DMA_CH1 = 1, | IRQ_DMA_CH1 = 1, | ||||
IRQ_SJC_DEBUG = 158, | IRQ_SJC_DEBUG = 158, | ||||
IRQ_NMI_WAKEUP = 159 | 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 { | typedef struct { | ||||
#define PIT_MCR (IMXRT_PIT.offset000) | #define PIT_MCR (IMXRT_PIT.offset000) | ||||
#define PIT_LTMR64H (IMXRT_PIT.offset0E0) | #define PIT_LTMR64H (IMXRT_PIT.offset0E0) | ||||
#define PIT_LTMR64L (IMXRT_PIT.offset0E4) | #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_LDVAL0 (IMXRT_PIT.offset100) | ||||
#define PIT_CVAL0 (IMXRT_PIT.offset104) | #define PIT_CVAL0 (IMXRT_PIT.offset104) | ||||
#define PIT_TCTRL0 (IMXRT_PIT.offset108) | #define PIT_TCTRL0 (IMXRT_PIT.offset108) | ||||
#define XTALOSC24M_OSC_CONFIG2_TOG (IMXRT_XTALOSC24M.offset2CC) | #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 __disable_irq() __asm__ volatile("CPSID i":::"memory"); | ||||
#define __enable_irq() __asm__ volatile("CPSIE i":::"memory"); | #define __enable_irq() __asm__ volatile("CPSIE i":::"memory"); |
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) } | |||||
} |
/* 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 |
#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; | |||||
} | |||||
} | |||||
#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; | |||||
};*/ | |||||
/* 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 | |||||
#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); | |||||
/* 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 |
/* 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 |
/* 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 | |||||
/* 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 |