浏览代码

Merge remote-tracking branch 'upstream/master'

main
Tino Hernandez 4 年前
父节点
当前提交
7cb39b2f4d
共有 100 个文件被更改,包括 3885 次插入343 次删除
  1. +1
    -1
      README.md
  2. +24
    -2
      keywords.txt
  3. +183
    -0
      teensy/FS.h
  4. +33
    -0
      teensy/Print.cpp
  5. +12
    -3
      teensy/Print.h
  6. +1
    -0
      teensy/Udp.h
  7. +335
    -0
      teensy/core_pins.h
  8. +2
    -2
      teensy/keylayouts.h
  9. +1
    -1
      teensy/malloc.c
  10. +6
    -0
      teensy/pins_arduino.h
  11. +2
    -4
      teensy/wiring.h
  12. +5
    -0
      teensy3/Arduino.h
  13. +19
    -4
      teensy3/AudioStream.cpp
  14. +6
    -1
      teensy3/AudioStream.h
  15. +17
    -4
      teensy3/DMAChannel.h
  16. +12
    -0
      teensy3/EventResponder.cpp
  17. +5
    -0
      teensy3/EventResponder.h
  18. +157
    -46
      teensy3/FS.h
  19. +45
    -0
      teensy3/HardwareSerial.cpp
  20. +33
    -13
      teensy3/HardwareSerial.h
  21. +10
    -3
      teensy3/HardwareSerial1.cpp
  22. +8
    -4
      teensy3/HardwareSerial2.cpp
  23. +8
    -3
      teensy3/HardwareSerial3.cpp
  24. +8
    -3
      teensy3/HardwareSerial4.cpp
  25. +8
    -3
      teensy3/HardwareSerial5.cpp
  26. +12
    -3
      teensy3/HardwareSerial6.cpp
  27. +1
    -1
      teensy3/IPAddress.cpp
  28. +1
    -1
      teensy3/Makefile
  29. +34
    -5
      teensy3/Print.cpp
  30. +15
    -4
      teensy3/Print.h
  31. +10
    -1
      teensy3/SPIFIFO.h
  32. +9
    -5
      teensy3/Stream.cpp
  33. +1
    -4
      teensy3/Tone.cpp
  34. +1
    -0
      teensy3/Udp.h
  35. +2
    -2
      teensy3/WCharacter.h
  36. +2
    -0
      teensy3/WProgram.h
  37. +3
    -1
      teensy3/WString.cpp
  38. +5
    -1
      teensy3/WString.h
  39. +9
    -7
      teensy3/analog.c
  40. +3
    -0
      teensy3/avr/eeprom.h
  41. +1
    -0
      teensy3/avr/pgmspace.h
  42. +1
    -1
      teensy3/avr_emulation.cpp
  43. +1
    -1
      teensy3/avr_emulation.h
  44. +1
    -1
      teensy3/avr_functions.h
  45. +448
    -5
      teensy3/core_pins.h
  46. +8
    -0
      teensy3/eeprom.c
  47. +2
    -2
      teensy3/keylayouts.h
  48. +36
    -21
      teensy3/kinetis.h
  49. +1
    -1
      teensy3/main.cpp
  50. +49
    -10
      teensy3/mk20dx128.c
  51. +2
    -0
      teensy3/mk20dx128.ld
  52. +2
    -0
      teensy3/mk20dx256.ld
  53. +3
    -1
      teensy3/mk64fx512.ld
  54. +2
    -0
      teensy3/mk66fx1m0.ld
  55. +2
    -0
      teensy3/mkl26z64.ld
  56. +6
    -3
      teensy3/pins_arduino.h
  57. +38
    -5
      teensy3/pins_teensy.c
  58. +10
    -2
      teensy3/serial1.c
  59. +10
    -2
      teensy3/serial2.c
  60. +10
    -2
      teensy3/serial3.c
  61. +10
    -2
      teensy3/serial4.c
  62. +10
    -2
      teensy3/serial5.c
  63. +10
    -2
      teensy3/serial6.c
  64. +1
    -1
      teensy3/serial6_lpuart.c
  65. +6
    -0
      teensy3/serialEvent.cpp
  66. +6
    -0
      teensy3/serialEvent1.cpp
  67. +6
    -0
      teensy3/serialEvent2.cpp
  68. +6
    -0
      teensy3/serialEvent3.cpp
  69. +8
    -0
      teensy3/serialEvent4.cpp
  70. +8
    -0
      teensy3/serialEvent5.cpp
  71. +8
    -0
      teensy3/serialEvent6.cpp
  72. +5
    -0
      teensy3/serialEventUSB1.cpp
  73. +5
    -0
      teensy3/serialEventUSB2.cpp
  74. +1
    -3
      teensy3/usb_audio.cpp
  75. +187
    -3
      teensy3/usb_desc.c
  76. +151
    -68
      teensy3/usb_desc.h
  77. +77
    -15
      teensy3/usb_dev.c
  78. +12
    -9
      teensy3/usb_dev.h
  79. +172
    -0
      teensy3/usb_flightsim.cpp
  80. +99
    -0
      teensy3/usb_flightsim.h
  81. +15
    -5
      teensy3/usb_inst.cpp
  82. +3
    -2
      teensy3/usb_joystick.c
  83. +3
    -2
      teensy3/usb_keyboard.c
  84. +2
    -0
      teensy3/usb_keyboard.h
  85. +12
    -4
      teensy3/usb_midi.c
  86. +3
    -2
      teensy3/usb_mouse.c
  87. +3
    -2
      teensy3/usb_seremu.c
  88. +3
    -2
      teensy3/usb_serial.c
  89. +5
    -3
      teensy3/usb_serial.h
  90. +306
    -0
      teensy3/usb_serial2.c
  91. +139
    -0
      teensy3/usb_serial2.h
  92. +306
    -0
      teensy3/usb_serial3.c
  93. +139
    -0
      teensy3/usb_serial3.h
  94. +14
    -2
      teensy3/usb_touch.c
  95. +50
    -2
      teensy3/usb_undef.h
  96. +25
    -6
      teensy3/wiring.h
  97. +41
    -17
      teensy3/yield.cpp
  98. +9
    -0
      teensy4/Arduino.h
  99. +337
    -0
      teensy4/AudioStream.cpp
  100. +0
    -0
      teensy4/AudioStream.h

+ 1
- 1
README.md 查看文件

@@ -1,4 +1,4 @@
Teensy 2.0, 3.x, LC core libraries for Arduino.
Teensy 2.0, LC, 3.x, 4.x core libraries for Arduino.

The latest stable version of Teensy's core library is always available in the Teensyduino installer, at this page:


+ 24
- 2
keywords.txt 查看文件

@@ -8,6 +8,7 @@ nullptr LITERAL1
noexcept LITERAL1
static_assert LITERAL1
thread_local LITERAL1
size_t LITERAL1

# teensy specific functions
elapsedMillis LITERAL1
@@ -26,18 +27,28 @@ IntervalTimer KEYWORD2
printf KEYWORD2
digitalWriteFast KEYWORD2
digitalReadFast KEYWORD2
digitalToggleFast KEYWORD2
digitalToggle KEYWORD2
transmitterEnable KEYWORD2
attachRts KEYWORD2
attachCts KEYWORD2
PROGMEM LITERAL1
FLASHMEM LITERAL1
DMAMEM LITERAL1
EXTMEM LITERAL1
FASTRUN LITERAL1
Serial4 KEYWORD1
Serial5 KEYWORD1
Serial6 KEYWORD1
Serial7 KEYWORD1
Serial8 KEYWORD1
SerialUSB1 KEYWORD1
SerialUSB2 KEYWORD1
setRX KEYWORD2
setTX KEYWORD2
write9bit KEYWORD2
addMemoryForRead KEYWORD2
addMemoryForWrite KEYWORD2
clear KEYWORD2
EventResponder LITERAL1
EventResponderRef LITERAL1
@@ -51,9 +62,15 @@ getContext KEYWORD2
waitForEvent KEYWORD2
MillisTimer LITERAL1
beginRepeating KEYWORD2
delayNanoseconds KEYWORD2
extmem_malloc KEYWORD2
extmem_free KEYWORD2
extmem_calloc KEYWORD2
extmem_realloc KEYWORD2
strcasecmp KEYWORD2

# removed by Arduino 1.0, but still in Teensyduino
BYTE LITERAL1
# removed by Arduino 1.0, now also removed from Teensyduino
#BYTE LITERAL1

# Arduino constants
A0 LITERAL1
@@ -95,6 +112,9 @@ analogInputToDigitalPin KEYWORD2
digitalPinHasPWM KEYWORD2
NOT_AN_INTERRUPT LITERAL1
digitalPinToInterrupt KEYWORD2
FILE_READ LITERAL1
FILE_WRITE LITERAL1
FILE_WRITE_BEGIN LITERAL1

# HardwareSerial modes
SERIAL_7E1 LITERAL1
@@ -503,6 +523,8 @@ FlightSimCommand KEYWORD2
FlightSimInteger KEYWORD2
FlightSimFloat KEYWORD2
FlightSimElapsedFrames KEYWORD2
FlightSimData KEYWORD2
FlightSimEvent KEYWORD2
onChange KEYWORD2
update KEYWORD2
isEnabled KEYWORD2

+ 183
- 0
teensy/FS.h 查看文件

@@ -0,0 +1,183 @@
/* Teensyduino Core Library - File base class
* http://www.pjrc.com/teensy/
* Copyright (c) 2020 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 FS_H
#define FS_H
#ifdef __cplusplus

#include <Arduino.h>

#define FILE_READ 0
#define FILE_WRITE 1
#define FILE_WRITE_BEGIN 2

enum SeekMode {
SeekSet = 0,
SeekCur = 1,
SeekEnd = 2
};

//#define FILE_WHOAMI

class File : public Stream {
public:
File() : f(nullptr) { }
File(File *file) {
// "file" must only be a class derived from File
// can we use is_same or is_polymorphic with static_assert?
// or is_base_of
//static_assert(std::is_same<decltype(*file),File>::value,
//"File(File *file) constructor only accepts pointers "
//"to derived classes, not File itself");
f = file;
if (f) f->refcount++;
}
File(const File &file) {
//Serial.println("File copy constructor");
//static int copycount=0;
//if (++copycount > 20) while (1) ;
f = file.f;
if (f) f->refcount++;
}
File& operator = (const File &file) {
//Serial.println("File assignment");
//static int assigncount=0;
//if (++assigncount > 20) while (1) ;
invalidate();
f = file.f;
if (f) f->refcount++;
return *this;
}
virtual ~File() {
invalidate();
}
#ifdef FILE_WHOAMI
virtual void whoami() { // testing only
Serial.printf(" File this=%x, f=%x\n", (int)this, (int)f);
if (f) f->whoami();
}
unsigned int getRefcount() { // testing only
return refcount;
}
#endif
virtual size_t read(void *buf, size_t nbyte) {
return (f) ? f->read(buf, nbyte) : 0;
}
virtual size_t write(const void *buf, size_t size) {
return (f) ? f->write(buf, size) : 0;
}
virtual int available() {
return (f) ? f->available() : 0;
}
virtual int peek() {
return (f) ? f->peek() : -1;
}
virtual void flush() {
if (f) f->flush();
}
virtual bool truncate(uint64_t size=0) {
return (f) ? f->truncate(size) : false;
}
virtual bool seek(uint64_t pos, int mode) {
return (f) ? f->seek(pos, mode) : false;
}
virtual uint64_t position() {
return (f) ? f->position() : 0;
}
virtual uint64_t size() {
return (f) ? f->size() : 0;
}
virtual void close() {
if (f) f->close();
}
virtual operator bool() {
return (f) ? (bool)*f : false;
}
virtual const char* name() {
return (f) ? f->name() : "";
}
virtual bool isDirectory() {
return (f) ? f->isDirectory() : false;
}
virtual File openNextFile(uint8_t mode=0) {
return (f) ? f->openNextFile(mode) : *this;
}
virtual void rewindDirectory(void) {
if (f) f->rewindDirectory();
}
bool seek(uint64_t pos) {
return seek(pos, SeekSet);
}
int read() {
if (!f) return -1;
unsigned char b;
if (f->read(&b, 1) < 1) return -1;
return b;
}
size_t write(uint8_t b) {
return write(&b, 1);
}
size_t write(const char *str) {
return write(str, strlen(str));
}
size_t readBytes(char *buffer, size_t length) {
return read(buffer, length);
}
private:
void invalidate() {
if (f && --(f->refcount) == 0) delete f;
}
union {
// instances of base File class use this pointer
File *f;
// instances of derived classes (which actually access media)
// use this reference count which is managed by the base class
unsigned int refcount;
};
};


class FS
{
public:
FS() {}
virtual File open(const char *filename, uint8_t mode = FILE_READ);
virtual bool exists(const char *filepath);
virtual bool mkdir(const char *filepath);
virtual bool rename(const char *oldfilepath, const char *newfilepath);
virtual bool remove(const char *filepath);
virtual bool rmdir(const char *filepath);
virtual uint64_t usedSize();
virtual uint64_t totalSize();
};


#endif // __cplusplus
#endif // FS_H

+ 33
- 0
teensy/Print.cpp 查看文件

@@ -353,6 +353,39 @@ size_t Print::printNumberAny(unsigned long n, uint8_t base)
return write(p, sizeof(buf) - (p - buf));
}

size_t Print::print(int64_t n)
{
if (n < 0) return printNumber64(-n, 10, 1);
return printNumber64(n, 10, 0);
}

size_t Print::printNumber64(uint64_t n, uint8_t base, uint8_t sign)
{
uint8_t buf[66];
uint8_t digit, i;

if (base < 2) return 0;
if (n == 0) {
buf[sizeof(buf) - 1] = '0';
i = sizeof(buf) - 1;
} else {
i = sizeof(buf) - 1;
while (1) {
digit = n % base;
buf[i] = ((digit < 10) ? '0' + digit : 'A' + digit - 10);
n /= base;
if (n == 0) break;
i--;
}
}
if (sign) {
i--;
buf[i] = '-';
}
return write(buf + i, sizeof(buf) - i);
}


size_t Print::printFloat(double number, uint8_t digits)
{
uint8_t sign=0;

+ 12
- 3
teensy/Print.h 查看文件

@@ -34,9 +34,9 @@

// 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
//#ifndef BYTE
//#define BYTE 0
//#endif

class __FlashStringHelper;

@@ -60,12 +60,16 @@ class Print
size_t print(unsigned int n) { return printNumber(n, 0, 10); }
size_t print(long n);
size_t print(unsigned long n) { return printNumber(n, 0, 10); }
size_t print(int64_t n);
size_t print(uint64_t n) { return printNumber64(n, 10, 0); }

size_t print(unsigned char n, int base) { return printNumber(n, 0, base); }
size_t print(int n, int base) { return (base == 10) ? print(n) : printNumber(n, 0, base); }
size_t print(unsigned int n, int base) { return printNumber(n, 0, base); }
size_t print(long n, int base) { return (base == 10) ? print(n) : printNumber(n, 0, base); }
size_t print(unsigned long n, int base) { return printNumber(n, 0, base); }
size_t print(int64_t n, int base) { return (base == 10) ? print(n) : printNumber64(n, base, 0); }
size_t print(uint64_t n, int base) { return printNumber64(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); }
@@ -80,12 +84,16 @@ class Print
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(int64_t n) { return print(n) + println(); }
size_t println(uint64_t 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(int64_t n, int base) { return print(n, base) + println(); }
size_t println(uint64_t 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(); }
@@ -111,6 +119,7 @@ class Print
if (base == 2) return printNumberBin(n);
return printNumberAny(n, base);
}
size_t printNumber64(uint64_t n, uint8_t base, uint8_t sign);
size_t printFloat(double n, uint8_t digits);
};


+ 1
- 0
teensy/Udp.h 查看文件

@@ -44,6 +44,7 @@ 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

+ 335
- 0
teensy/core_pins.h 查看文件

@@ -1935,6 +1935,253 @@ static inline void pinMode(uint8_t pin, uint8_t mode)
}
}

static inline void digitalToggle(uint8_t) __attribute__((always_inline, unused));
static inline void digitalToggle(uint8_t pin)
{
if (__builtin_constant_p(pin)) {
if (pin == 0) {
CORE_PIN0_PINREG = CORE_PIN0_BITMASK;
} else if (pin == 1) {
CORE_PIN1_PINREG = CORE_PIN1_BITMASK;
} else if (pin == 2) {
CORE_PIN2_PINREG = CORE_PIN2_BITMASK;
} else if (pin == 3) {
CORE_PIN3_PINREG = CORE_PIN3_BITMASK;
} else if (pin == 4) {
CORE_PIN4_PINREG = CORE_PIN4_BITMASK;
} else if (pin == 5) {
CORE_PIN5_PINREG = CORE_PIN5_BITMASK;
} else if (pin == 6) {
CORE_PIN6_PINREG = CORE_PIN6_BITMASK;
} else if (pin == 7) {
CORE_PIN7_PINREG = CORE_PIN7_BITMASK;
} else if (pin == 8) {
CORE_PIN8_PINREG = CORE_PIN8_BITMASK;
} else if (pin == 9) {
CORE_PIN9_PINREG = CORE_PIN9_BITMASK;
} else if (pin == 10) {
CORE_PIN10_PINREG = CORE_PIN10_BITMASK;
} else if (pin == 11) {
CORE_PIN11_PINREG = CORE_PIN11_BITMASK;
} else if (pin == 12) {
CORE_PIN12_PINREG = CORE_PIN12_BITMASK;
} else if (pin == 13) {
CORE_PIN13_PINREG = CORE_PIN13_BITMASK;
} else if (pin == 14) {
CORE_PIN14_PINREG = CORE_PIN14_BITMASK;
} else if (pin == 15) {
CORE_PIN15_PINREG = CORE_PIN15_BITMASK;
} else if (pin == 16) {
CORE_PIN16_PINREG = CORE_PIN16_BITMASK;
} else if (pin == 17) {
CORE_PIN17_PINREG = CORE_PIN17_BITMASK;
} else if (pin == 18) {
CORE_PIN18_PINREG = CORE_PIN18_BITMASK;
} else if (pin == 19) {
CORE_PIN19_PINREG = CORE_PIN19_BITMASK;
} else if (pin == 20) {
CORE_PIN20_PINREG = CORE_PIN20_BITMASK;
}
#if CORE_NUM_TOTAL_PINS > 21
else if (pin == 21) {
CORE_PIN21_PINREG = CORE_PIN21_BITMASK;
} else if (pin == 22) {
CORE_PIN22_PINREG = CORE_PIN22_BITMASK;
} else if (pin == 23) {
CORE_PIN23_PINREG = CORE_PIN23_BITMASK;
} else if (pin == 24) {
CORE_PIN24_PINREG = CORE_PIN24_BITMASK;
}
#endif
#if CORE_NUM_TOTAL_PINS > 25
else if (pin == 25) {
CORE_PIN25_PINREG = CORE_PIN25_BITMASK;
} else if (pin == 26) {
CORE_PIN26_PINREG = CORE_PIN26_BITMASK;
} else if (pin == 27) {
CORE_PIN27_PINREG = CORE_PIN27_BITMASK;
} else if (pin == 28) {
CORE_PIN28_PINREG = CORE_PIN28_BITMASK;
} else if (pin == 29) {
CORE_PIN29_PINREG = CORE_PIN29_BITMASK;
} else if (pin == 30) {
CORE_PIN30_PINREG = CORE_PIN30_BITMASK;
} else if (pin == 31) {
CORE_PIN31_PINREG = CORE_PIN31_BITMASK;
} else if (pin == 32) {
CORE_PIN32_PINREG = CORE_PIN32_BITMASK;
} else if (pin == 33) {
CORE_PIN33_PINREG = CORE_PIN33_BITMASK;
} else if (pin == 34) {
CORE_PIN34_PINREG = CORE_PIN34_BITMASK;
} else if (pin == 35) {
CORE_PIN35_PINREG = CORE_PIN35_BITMASK;
} else if (pin == 36) {
CORE_PIN36_PINREG = CORE_PIN36_BITMASK;
} else if (pin == 37) {
CORE_PIN37_PINREG = CORE_PIN37_BITMASK;
} else if (pin == 38) {
CORE_PIN38_PINREG = CORE_PIN38_BITMASK;
} else if (pin == 39) {
CORE_PIN39_PINREG = CORE_PIN39_BITMASK;
} else if (pin == 40) {
CORE_PIN40_PINREG = CORE_PIN40_BITMASK;
} else if (pin == 41) {
CORE_PIN41_PINREG = CORE_PIN41_BITMASK;
} else if (pin == 42) {
CORE_PIN42_PINREG = CORE_PIN42_BITMASK;
} else if (pin == 43) {
CORE_PIN43_PINREG = CORE_PIN43_BITMASK;
} else if (pin == 44) {
CORE_PIN44_PINREG = CORE_PIN44_BITMASK;
} else if (pin == 45) {
CORE_PIN45_PINREG = CORE_PIN45_BITMASK;
}
#endif
if (pin == CORE_OC0B_PIN) {
_SFR_BYTE(TCCR0A) &= ~(1<<COM0B1);
} else if (pin == CORE_OC1A_PIN) {
TCCR1A &= ~(1<<COM1A1);
} else if (pin == CORE_OC1B_PIN) {
TCCR1A &= ~(1<<COM1B1);
} else if (pin == CORE_OC1C_PIN) {
TCCR1A &= ~(1<<COM1C1);
}
#if defined(__AVR_ATmega32U4__)
else if (pin == CORE_OC3A_PIN) {
TCCR3A &= ~(1<<COM3A1);
} else if (pin == CORE_OC4A_PIN) {
TCCR4A &= ~(1<<COM4A1);
} else if (pin == CORE_OC4D_PIN) {
TCCR4C &= ~(1<<COM4D1);
}
#endif
#if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
else if (pin == CORE_OC2A_PIN) {
TCCR2A &= ~(1<<COM2A1);
} else if (pin == CORE_OC2B_PIN) {
TCCR2A &= ~(1<<COM2B1);
} else if (pin == CORE_OC3A_PIN) {
TCCR3A &= ~(1<<COM3A1);
} else if (pin == CORE_OC3B_PIN) {
TCCR3A &= ~(1<<COM3B1);
} else if (pin == CORE_OC3C_PIN) {
TCCR3A &= ~(1<<COM3C1);
}
#endif
} else {
digitalWrite(pin, !(digitalRead(pin)));
}
}

static inline void digitalToggleFast(uint8_t) __attribute__((always_inline, unused));
static inline void digitalToggleFast(uint8_t pin)
{
if (__builtin_constant_p(pin)) {
if (pin == 0) {
CORE_PIN0_PINREG = CORE_PIN0_BITMASK;
} else if (pin == 1) {
CORE_PIN1_PINREG = CORE_PIN1_BITMASK;
} else if (pin == 2) {
CORE_PIN2_PINREG = CORE_PIN2_BITMASK;
} else if (pin == 3) {
CORE_PIN3_PINREG = CORE_PIN3_BITMASK;
} else if (pin == 4) {
CORE_PIN4_PINREG = CORE_PIN4_BITMASK;
} else if (pin == 5) {
CORE_PIN5_PINREG = CORE_PIN5_BITMASK;
} else if (pin == 6) {
CORE_PIN6_PINREG = CORE_PIN6_BITMASK;
} else if (pin == 7) {
CORE_PIN7_PINREG = CORE_PIN7_BITMASK;
} else if (pin == 8) {
CORE_PIN8_PINREG = CORE_PIN8_BITMASK;
} else if (pin == 9) {
CORE_PIN9_PINREG = CORE_PIN9_BITMASK;
} else if (pin == 10) {
CORE_PIN10_PINREG = CORE_PIN10_BITMASK;
} else if (pin == 11) {
CORE_PIN11_PINREG = CORE_PIN11_BITMASK;
} else if (pin == 12) {
CORE_PIN12_PINREG = CORE_PIN12_BITMASK;
} else if (pin == 13) {
CORE_PIN13_PINREG = CORE_PIN13_BITMASK;
} else if (pin == 14) {
CORE_PIN14_PINREG = CORE_PIN14_BITMASK;
} else if (pin == 15) {
CORE_PIN15_PINREG = CORE_PIN15_BITMASK;
} else if (pin == 16) {
CORE_PIN16_PINREG = CORE_PIN16_BITMASK;
} else if (pin == 17) {
CORE_PIN17_PINREG = CORE_PIN17_BITMASK;
} else if (pin == 18) {
CORE_PIN18_PINREG = CORE_PIN18_BITMASK;
} else if (pin == 19) {
CORE_PIN19_PINREG = CORE_PIN19_BITMASK;
} else if (pin == 20) {
CORE_PIN20_PINREG = CORE_PIN20_BITMASK;
}
#if CORE_NUM_TOTAL_PINS > 21
else if (pin == 21) {
CORE_PIN21_PINREG = CORE_PIN21_BITMASK;
} else if (pin == 22) {
CORE_PIN22_PINREG = CORE_PIN22_BITMASK;
} else if (pin == 23) {
CORE_PIN23_PINREG = CORE_PIN23_BITMASK;
} else if (pin == 24) {
CORE_PIN24_PINREG = CORE_PIN24_BITMASK;
}
#endif
#if CORE_NUM_TOTAL_PINS > 25
else if (pin == 25) {
CORE_PIN25_PINREG = CORE_PIN25_BITMASK;
} else if (pin == 26) {
CORE_PIN26_PINREG = CORE_PIN26_BITMASK;
} else if (pin == 27) {
CORE_PIN27_PINREG = CORE_PIN27_BITMASK;
} else if (pin == 28) {
CORE_PIN28_PINREG = CORE_PIN28_BITMASK;
} else if (pin == 29) {
CORE_PIN29_PINREG = CORE_PIN29_BITMASK;
} else if (pin == 30) {
CORE_PIN30_PINREG = CORE_PIN30_BITMASK;
} else if (pin == 31) {
CORE_PIN31_PINREG = CORE_PIN31_BITMASK;
} else if (pin == 32) {
CORE_PIN32_PINREG = CORE_PIN32_BITMASK;
} else if (pin == 33) {
CORE_PIN33_PINREG = CORE_PIN33_BITMASK;
} else if (pin == 34) {
CORE_PIN34_PINREG = CORE_PIN34_BITMASK;
} else if (pin == 35) {
CORE_PIN35_PINREG = CORE_PIN35_BITMASK;
} else if (pin == 36) {
CORE_PIN36_PINREG = CORE_PIN36_BITMASK;
} else if (pin == 37) {
CORE_PIN37_PINREG = CORE_PIN37_BITMASK;
} else if (pin == 38) {
CORE_PIN38_PINREG = CORE_PIN38_BITMASK;
} else if (pin == 39) {
CORE_PIN39_PINREG = CORE_PIN39_BITMASK;
} else if (pin == 40) {
CORE_PIN40_PINREG = CORE_PIN40_BITMASK;
} else if (pin == 41) {
CORE_PIN41_PINREG = CORE_PIN41_BITMASK;
} else if (pin == 42) {
CORE_PIN42_PINREG = CORE_PIN42_BITMASK;
} else if (pin == 43) {
CORE_PIN43_PINREG = CORE_PIN43_BITMASK;
} else if (pin == 44) {
CORE_PIN44_PINREG = CORE_PIN44_BITMASK;
} else if (pin == 45) {
CORE_PIN45_PINREG = CORE_PIN45_BITMASK;
}
#endif
} else {
digitalWrite(pin, !(digitalRead(pin)));
}
}

extern void _init_Teensyduino_internal_(void);
extern int analogRead(uint8_t);

@@ -2198,6 +2445,94 @@ static inline void delayMicroseconds(uint16_t usec)
}


static inline void delayNanoseconds(uint16_t) __attribute__((always_inline, unused));
static inline void delayNanoseconds(uint16_t nsec)
{
if (__builtin_constant_p(nsec)) {
// use NOPs for the common usage of a constexpr input and short delay
if (nsec == 0) return;
if (nsec <= 1000 / (F_CPU / 1000000)) {
__asm__ volatile("nop");
return;
}
if (nsec <= 2000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop");
return;
}
if (nsec <= 3000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop");
return;
}
if (nsec <= 4000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop");
return;
}
if (nsec <= 5000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
return;
}
if (nsec <= 6000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop");
return;
}
if (nsec <= 7000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop");
return;
}
if (nsec <= 8000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop");
return;
}
if (nsec <= 9000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop\n nop");
return;
}
if (nsec <= 10000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
return;
}
if (nsec <= 11000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop");
return;
}
if (nsec <= 12000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop");
return;
}
if (nsec <= 13000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop");
return;
}
if (nsec <= 14000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop\n nop");
return;
}
if (nsec <= 15000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
return;
}
}
// if we can't use NOPs, just round up to the nearest microsecond...
// not ideal, but AVR is too slow to do anything more complex
delayMicroseconds((nsec >> 10) + 1);
}




#ifdef __cplusplus

+ 2
- 2
teensy/keylayouts.h 查看文件

@@ -1451,7 +1451,7 @@ extern "C"{
#define ASCII_20 KEY_SPACE // 32
#define ASCII_21 KEY_1 + SHIFT_MASK // 33 !
#define ASCII_22 KEY_2 + SHIFT_MASK // 34 "
#define ASCII_23 KEY_BACKSPACE // 35 #
#define ASCII_23 KEY_BACKSLASH // 35 #
#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $
#define ASCII_25 KEY_5 + SHIFT_MASK // 37 %
#define ASCII_26 KEY_7 + SHIFT_MASK // 38 &
@@ -4533,7 +4533,7 @@ extern "C"{
#define ASCII_20 KEY_SPACE // 32
#define ASCII_21 KEY_1 + SHIFT_MASK // 33 !
#define ASCII_22 KEY_2 + SHIFT_MASK // 34 "
#define ASCII_23 KEY_BACKSPACE // 35 #
#define ASCII_23 KEY_BACKSLASH // 35 #
#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $
#define ASCII_25 KEY_5 + SHIFT_MASK // 37 %
#define ASCII_26 KEY_7 + SHIFT_MASK // 38 &

+ 1
- 1
teensy/malloc.c 查看文件

@@ -73,7 +73,7 @@ struct __freelist *__flp; // freelist pointer (head of freelist)
void *
malloc(size_t len)
{
struct __freelist *fp1, *fp2, *sfp1, *sfp2;
struct __freelist *fp1, *fp2, *sfp1=NULL, *sfp2=NULL;
char *cp;
size_t s, avail;


+ 6
- 0
teensy/pins_arduino.h 查看文件

@@ -36,6 +36,12 @@ const static uint8_t SCL = CORE_SCL0_PIN;
#define NUM_DIGITAL_PINS CORE_NUM_TOTAL_PINS
#define NUM_ANALOG_INPUTS CORE_NUM_ANALOG

// default CS pin to use for Ethernet library
#if defined(__AVR_ATmega32U4__)
#define PIN_SPI_SS_ETHERNET_LIB 0
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
#define PIN_SPI_SS_ETHERNET_LIB 20
#endif

// This allows CapSense to work. Do any libraries
// depend on these to be zero?

+ 2
- 4
teensy/wiring.h 查看文件

@@ -27,6 +27,7 @@

#include <avr/io.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include "binary.h"
#include "core_id.h"
@@ -39,9 +40,6 @@
extern "C"{
#endif

#define true 1
#define false 0

#define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398
#define TWO_PI 6.283185307179586476925286766559
@@ -93,7 +91,7 @@ typedef unsigned int word;

#define bit(b) (1UL << (b))

typedef uint8_t boolean;
typedef bool boolean;
typedef uint8_t byte;

unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);

+ 5
- 0
teensy3/Arduino.h 查看文件

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

#ifndef Arduino_h
#define Arduino_h

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

#endif

+ 19
- 4
teensy3/AudioStream.cpp 查看文件

@@ -29,9 +29,8 @@
*/


#include <string.h> // for memcpy
#include "AudioStream.h"
#include <Arduino.h>
#include "AudioStream.h"

#if defined(__MKL26Z64__)
#define MAX_AUDIO_MEMORY 6144
@@ -244,6 +243,8 @@ void AudioConnection::disconnect(void)
// Remove destination from source list
p = src.destination_list;
if (p == NULL) {
//>>> PAH re-enable the IRQ
__enable_irq();
return;
} else if (p == this) {
if (p->next_dest) {
@@ -265,8 +266,14 @@ void AudioConnection::disconnect(void)
p = p->next_dest;
}
}
//>>> PAH release the audio buffer properly
//Remove possible pending src block from destination
dst.inputQueue[dest_index] = NULL;
if(dst.inputQueue[dest_index] != NULL) {
AudioStream::release(dst.inputQueue[dest_index]);
// release() re-enables the IRQ. Need it to be disabled a little longer
__disable_irq();
dst.inputQueue[dest_index] = NULL;
}

//Check if the disconnected AudioStream objects should still be active
src.numConnections--;
@@ -313,9 +320,13 @@ void software_isr(void) // AudioStream::update_all()
{
AudioStream *p;

#if defined(KINETISK)
ARM_DEMCR |= ARM_DEMCR_TRCENA;
ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
uint32_t totalcycles = ARM_DWT_CYCCNT;
#elif defined(KINETISL)
uint32_t totalcycles = micros();
#endif
//digitalWriteFast(2, HIGH);
for (p = AudioStream::first_update; p; p = p->next_update) {
if (p->active) {
@@ -329,7 +340,11 @@ void software_isr(void) // AudioStream::update_all()
}
}
//digitalWriteFast(2, LOW);
totalcycles = (ARM_DWT_CYCCNT - totalcycles) >> 4;;
#if defined(KINETISK)
totalcycles = (ARM_DWT_CYCCNT - totalcycles) >> 4;
#elif defined(KINETISL)
totalcycles = micros() - totalcycles;
#endif
AudioStream::cpu_cycles_total = totalcycles;
if (totalcycles > AudioStream::cpu_cycles_total_max)
AudioStream::cpu_cycles_total_max = totalcycles;

+ 6
- 1
teensy3/AudioStream.h 查看文件

@@ -59,7 +59,8 @@
#if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
#define AUDIO_SAMPLE_RATE_EXACT 44117.64706 // 48 MHz / 1088, or 96 MHz * 2 / 17 / 256
#elif defined(__MKL26Z64__)
#define AUDIO_SAMPLE_RATE_EXACT 22058.82353 // 48 MHz / 2176, or 96 MHz * 1 / 17 / 256
//#define AUDIO_SAMPLE_RATE_EXACT 22058.82353 // 48 MHz / 2176, or 96 MHz * 1 / 17 / 256
#define AUDIO_SAMPLE_RATE_EXACT 44117.64706
#endif
#endif

@@ -113,7 +114,11 @@ protected:
AudioStream::initialize_memory(data, num); \
})

#if defined(KINETISK)
#define CYCLE_COUNTER_APPROX_PERCENT(n) (((n) + (F_CPU / 32 / AUDIO_SAMPLE_RATE * AUDIO_BLOCK_SAMPLES / 100)) / (F_CPU / 16 / AUDIO_SAMPLE_RATE * AUDIO_BLOCK_SAMPLES / 100))
#elif defined(KINETISL)
#define CYCLE_COUNTER_APPROX_PERCENT(n) ((n) * (int)(AUDIO_SAMPLE_RATE) + (int)(AUDIO_SAMPLE_RATE/2)) / (AUDIO_BLOCK_SAMPLES * 10000)
#endif

#define AudioProcessorUsage() (CYCLE_COUNTER_APPROX_PERCENT(AudioStream::cpu_cycles_total))
#define AudioProcessorUsageMax() (CYCLE_COUNTER_APPROX_PERCENT(AudioStream::cpu_cycles_total_max))

+ 17
- 4
teensy3/DMAChannel.h 查看文件

@@ -380,6 +380,7 @@ protected:
DMABaseClass() {}

static inline void copy_tcd(TCD_t *dst, const TCD_t *src) {
dst->CSR = 0;
const uint32_t *p = (const uint32_t *)src;
uint32_t *q = (uint32_t *)dst;
uint32_t t1, t2, t3, t4;
@@ -534,6 +535,12 @@ public:
NVIC_ENABLE_IRQ(IRQ_DMA_CH0 + channel);
}

void attachInterrupt(void (*isr)(void), uint8_t prio) {
_VectorsRam[channel + IRQ_DMA_CH0 + 16] = isr;
NVIC_ENABLE_IRQ(IRQ_DMA_CH0 + channel);
NVIC_SET_PRIORITY(IRQ_DMA_CH0 + channel, prio);
}
void detachInterrupt(void) {
NVIC_DISABLE_IRQ(IRQ_DMA_CH0 + channel);
}
@@ -811,11 +818,11 @@ public:
void transferSize(unsigned int len) {
uint32_t dcr = CFG->DCR & 0xF0C8FFFF;
if (len == 4) {
CFG->DCR = dcr | DMA_DCR_DSIZE(0) | DMA_DCR_DSIZE(0);
CFG->DCR = dcr | DMA_DCR_SSIZE(0) | DMA_DCR_DSIZE(0);
} else if (len == 2) {
CFG->DCR = dcr | DMA_DCR_DSIZE(2) | DMA_DCR_DSIZE(2);
CFG->DCR = dcr | DMA_DCR_SSIZE(2) | DMA_DCR_DSIZE(2);
} else {
CFG->DCR = dcr | DMA_DCR_DSIZE(1) | DMA_DCR_DSIZE(1);
CFG->DCR = dcr | DMA_DCR_SSIZE(1) | DMA_DCR_DSIZE(1);
}
}

@@ -1034,7 +1041,13 @@ public:
_VectorsRam[channel + IRQ_DMA_CH0 + 16] = isr;
NVIC_ENABLE_IRQ(IRQ_DMA_CH0 + channel);
}

void attachInterrupt(void (*isr)(void), uint8_t prio) {
_VectorsRam[channel + IRQ_DMA_CH0 + 16] = isr;
NVIC_ENABLE_IRQ(IRQ_DMA_CH0 + channel);
NVIC_SET_PRIORITY(IRQ_DMA_CH0 + channel, prio);
}
void detachInterrupt(void) {
NVIC_DISABLE_IRQ(IRQ_DMA_CH0 + channel);
}

+ 12
- 0
teensy3/EventResponder.cpp 查看文件

@@ -31,6 +31,7 @@
* https://forum.pjrc.com/threads/44723-Arduino-Events
*/

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

EventResponder * EventResponder::firstYield = nullptr;
@@ -40,6 +41,10 @@ EventResponder * EventResponder::lastInterrupt = nullptr;
bool EventResponder::runningFromYield = false;

// TODO: interrupt disable/enable needed in many places!!!
// BUGBUG: See if file name order makes difference?
uint8_t _serialEvent_default __attribute__((weak)) PROGMEM = 0 ;
uint8_t _serialEventUSB1_default __attribute__((weak)) PROGMEM = 0 ;
uint8_t _serialEventUSB2_default __attribute__((weak)) PROGMEM = 0 ;

void EventResponder::triggerEventNotImmediate()
{
@@ -334,10 +339,17 @@ void MillisTimer::runFromTimer()
// with libraries using mid-to-high priority interrupts.

extern "C" volatile uint32_t systick_millis_count;

void systick_isr(void)
{
systick_millis_count++;
}

extern "C" void systick_isr_with_timer_events(void)
{
systick_millis_count++;
MillisTimer::runFromTimer();
}




+ 5
- 0
teensy3/EventResponder.h 查看文件

@@ -59,6 +59,7 @@
* your function is called only one time, based on the last trigger
* event.
*/
extern "C" void systick_isr_with_timer_events(void);

class EventResponder;
typedef EventResponder& EventResponderRef;
@@ -87,6 +88,7 @@ public:
detachNoInterrupts();
_function = function;
_type = EventTypeYield;
yield_active_check_flags |= YIELD_CHECK_EVENT_RESPONDER; // user setup a yield type...
enableInterrupts(irq);
}

@@ -112,6 +114,8 @@ public:
_function = function;
_type = EventTypeInterrupt;
SCB_SHPR3 |= 0x00FF0000; // configure PendSV, lowest priority
// Make sure we are using the systic ISR that process this
_VectorsRam[15] = systick_isr_with_timer_events;
enableInterrupts(irq);
}

@@ -170,6 +174,7 @@ public:
EventResponder * waitForEvent(EventResponder *list, int listsize, int timeout);

static void runFromYield() {
if (!firstYield) return;
// First, check if yield was called from an interrupt
// never call normal handler functions from any interrupt context
uint32_t ipsr;

+ 157
- 46
teensy3/FS.h 查看文件

@@ -1,43 +1,146 @@
/* Experimental File & Dir base classes. VERY experimental!

These are intended to someday allow libraries using files,
such as a JPEG decoder, to accept a File object from SD,
Bridge, USB Host, ESP SPIFFS, and others. Perhaps only a
distant dream at this point, but maybe someday....
*/

/* Teensyduino Core Library - File base class
* http://www.pjrc.com/teensy/
* Copyright (c) 2020 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 FS_H
#define FS_H
#ifdef __cplusplus

#include "Stream.h"
#include "WString.h"
#include <Arduino.h>

#define FILE_READ 0
#define FILE_WRITE 1
#define FILE_WRITE_BEGIN 2

enum SeekMode {
SeekSet = 0,
SeekCur = 1,
SeekEnd = 2
};

#define FILE_WHOAMI

class File : public Stream {
public:
constexpr File() {}
enum SeekMode {
SeekSet = 0,
SeekCur = 1,
SeekEnd = 2
};
virtual size_t read(void *buf, size_t nbyte);
virtual size_t write(const void *buf, size_t size);
virtual int available();
virtual int read();
virtual int peek();
virtual void flush();
virtual bool seek(uint32_t pos, int mode);
virtual uint32_t position() const;
virtual uint32_t size() const;
virtual void close();
virtual operator bool() const;
//virtual const char* name() const; // why does ESP have this in File?

bool seek(uint32_t pos) {
constexpr File() : f(nullptr) { }
File(File *file) {
// "file" must only be a class derived from File
// can we use is_same or is_polymorphic with static_assert?
// or is_base_of
//static_assert(std::is_same<decltype(*file),File>::value,
//"File(File *file) constructor only accepts pointers "
//"to derived classes, not File itself");
f = file;
if (f) f->refcount++;
}
File(const File &file) {
//Serial.println("File copy constructor");
//static int copycount=0;
//if (++copycount > 20) while (1) ;
f = file.f;
if (f) f->refcount++;
}
File& operator = (const File &file) {
//Serial.println("File assignment");
//static int assigncount=0;
//if (++assigncount > 20) while (1) ;
invalidate();
f = file.f;
if (f) f->refcount++;
return *this;
}
virtual ~File() {
invalidate();
}
#ifdef FILE_WHOAMI
virtual void whoami() { // testing only
Serial.printf(" File this=%x, f=%x\n", (int)this, (int)f);
if (f) f->whoami();
}
unsigned int getRefcount() { // testing only
return refcount;
}
#endif
virtual size_t read(void *buf, size_t nbyte) {
return (f) ? f->read(buf, nbyte) : 0;
}
virtual size_t write(const void *buf, size_t size) {
return (f) ? f->write(buf, size) : 0;
}
virtual int available() {
return (f) ? f->available() : 0;
}
virtual int peek() {
return (f) ? f->peek() : -1;
}
virtual void flush() {
if (f) f->flush();
}
virtual bool truncate(uint64_t size=0) {
return (f) ? f->truncate(size) : false;
}
virtual bool seek(uint64_t pos, int mode) {
return (f) ? f->seek(pos, mode) : false;
}
virtual uint64_t position() {
return (f) ? f->position() : 0;
}
virtual uint64_t size() {
return (f) ? f->size() : 0;
}
virtual void close() {
if (f) f->close();
}
virtual operator bool() {
return (f) ? (bool)*f : false;
}
virtual const char* name() {
return (f) ? f->name() : "";
}
virtual bool isDirectory() {
return (f) ? f->isDirectory() : false;
}
virtual File openNextFile(uint8_t mode=0) {
return (f) ? f->openNextFile(mode) : *this;
}
virtual void rewindDirectory(void) {
if (f) f->rewindDirectory();
}
bool seek(uint64_t pos) {
return seek(pos, SeekSet);
}
int read() {
if (!f) return -1;
unsigned char b;
if (f->read(&b, 1) < 1) return -1;
return b;
}
size_t write(uint8_t b) {
return write(&b, 1);
}
@@ -47,26 +150,34 @@ public:
size_t readBytes(char *buffer, size_t length) {
return read(buffer, length);
}

// needed for compatiblity with Arduino's SD & Bridge libs
virtual const char* name();
virtual bool isDirectory();
virtual File openNextFile(uint8_t mode=0);
virtual void rewindDirectory(void);
private:
void invalidate() {
if (f && --(f->refcount) == 0) delete f;
}
union {
// instances of base File class use this pointer
File *f;
// instances of derived classes (which actually access media)
// use this reference count which is managed by the base class
unsigned int refcount;
};
};

class Dir {

class FS
{
public:
constexpr Dir() {}
virtual const char *name(); // from SD's File (and ESP's File)
virtual uint32_t fileSize();
virtual bool isDirectory(); // from SD, not in ESP
virtual File openFile(const char *mode);
virtual bool next();
String fileName() {
return String(name());
}
FS() {}
virtual File open(const char *filename, uint8_t mode = FILE_READ);
virtual bool exists(const char *filepath);
virtual bool mkdir(const char *filepath);
virtual bool rename(const char *oldfilepath, const char *newfilepath);
virtual bool remove(const char *filepath);
virtual bool rmdir(const char *filepath);
virtual uint64_t usedSize();
virtual uint64_t totalSize();
};


#endif // __cplusplus
#endif // FS_H

+ 45
- 0
teensy3/HardwareSerial.cpp 查看文件

@@ -0,0 +1,45 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2019 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 "HardwareSerial.h"
#include "core_pins.h"
#include "Arduino.h"

// define our static objects
HardwareSerial *HardwareSerial::s_serials_with_serial_events[CNT_HARDWARE_SERIAL];
uint8_t HardwareSerial::s_count_serials_with_serial_events = 0;

// simple helper function that add us to the list of Serial ports that have
// their own serialEvent code defined that needs to be called at yield.
void HardwareSerial::addToSerialEventsList() {
s_serials_with_serial_events[s_count_serials_with_serial_events++] = this;
yield_active_check_flags |= YIELD_CHECK_HARDWARE_SERIAL;
}


+ 33
- 13
teensy3/HardwareSerial.h 查看文件

@@ -253,8 +253,13 @@ void serial6_clear(void);
class HardwareSerial : public Stream
{
public:
constexpr HardwareSerial() {}
virtual void begin(uint32_t baud) { serial_begin(BAUD2DIV(baud)); }
constexpr HardwareSerial(void (* const se)()) : _serialEvent(se) {}
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
enum {CNT_HARDWARE_SERIAL = 6};
#else //(__MK64FX512__) || defined(__MK66FX1M0__)
enum {CNT_HARDWARE_SERIAL = 3};
#endif
virtual void begin(uint32_t baud);
virtual void begin(uint32_t baud, uint32_t format) {
serial_begin(BAUD2DIV(baud));
serial_format(format); }
@@ -283,6 +288,21 @@ public:
return len; }
virtual size_t write9bit(uint32_t c) { serial_putchar(c); return 1; }
operator bool() { return true; }

static inline void processSerialEventsList() {
for (uint8_t i = 0; i < s_count_serials_with_serial_events; i++) {
s_serials_with_serial_events[i]->doYieldCode();
}
}
protected:
static HardwareSerial *s_serials_with_serial_events[CNT_HARDWARE_SERIAL];
static uint8_t s_count_serials_with_serial_events;
void (* const _serialEvent)();
void addToSerialEventsList();
inline void doYieldCode() {
if (available()) (*_serialEvent)();
}

};
extern HardwareSerial Serial1;
extern void serialEvent1(void);
@@ -290,8 +310,8 @@ extern void serialEvent1(void);
class HardwareSerial2 : public HardwareSerial
{
public:
constexpr HardwareSerial2() {}
virtual void begin(uint32_t baud) { serial2_begin(BAUD2DIV2(baud)); }
constexpr HardwareSerial2(void (* const se)()) : HardwareSerial(se) {}
virtual void begin(uint32_t baud);
virtual void begin(uint32_t baud, uint32_t format) {
serial2_begin(BAUD2DIV2(baud));
serial2_format(format); }
@@ -327,8 +347,8 @@ extern void serialEvent2(void);
class HardwareSerial3 : public HardwareSerial
{
public:
constexpr HardwareSerial3() {}
virtual void begin(uint32_t baud) { serial3_begin(BAUD2DIV3(baud)); }
constexpr HardwareSerial3(void (* const se)()) : HardwareSerial(se) {}
virtual void begin(uint32_t baud);
virtual void begin(uint32_t baud, uint32_t format) {
serial3_begin(BAUD2DIV3(baud));
serial3_format(format); }
@@ -364,8 +384,8 @@ extern void serialEvent3(void);
class HardwareSerial4 : public HardwareSerial
{
public:
constexpr HardwareSerial4() {}
virtual void begin(uint32_t baud) { serial4_begin(BAUD2DIV3(baud)); }
constexpr HardwareSerial4(void (* const se)()) : HardwareSerial(se) {}
virtual void begin(uint32_t baud);
virtual void begin(uint32_t baud, uint32_t format) {
serial4_begin(BAUD2DIV3(baud));
serial4_format(format); }
@@ -401,8 +421,8 @@ extern void serialEvent4(void);
class HardwareSerial5 : public HardwareSerial
{
public:
constexpr HardwareSerial5() {}
virtual void begin(uint32_t baud) { serial5_begin(BAUD2DIV3(baud)); }
constexpr HardwareSerial5(void (* const se)()) : HardwareSerial(se) {}
virtual void begin(uint32_t baud);
virtual void begin(uint32_t baud, uint32_t format) {
serial5_begin(BAUD2DIV3(baud));
serial5_format(format); }
@@ -438,14 +458,14 @@ extern void serialEvent5(void);
class HardwareSerial6 : public HardwareSerial
{
public:
constexpr HardwareSerial6() {}
constexpr HardwareSerial6(void (* const se)()) : HardwareSerial(se) {}
#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);
virtual void begin(uint32_t baud, uint32_t format) {
serial6_begin(baud);
serial6_format(format); }
#else
virtual void begin(uint32_t baud) { serial6_begin(BAUD2DIV3(baud)); }
virtual void begin(uint32_t baud);
virtual void begin(uint32_t baud, uint32_t format) {
serial6_begin(BAUD2DIV3(baud));
serial6_format(format); }

+ 10
- 3
teensy3/HardwareSerial1.cpp 查看文件

@@ -28,9 +28,16 @@
* SOFTWARE.
*/

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

HardwareSerial Serial1;

void serialEvent1() __attribute__((weak));
void serialEvent1() {}
uint8_t _serialEvent1_default __attribute__((weak)) PROGMEM = 0 ;

HardwareSerial Serial1(&serialEvent1);

void HardwareSerial::begin(uint32_t baud) {
serial_begin(BAUD2DIV(baud));
if (!_serialEvent1_default) addToSerialEventsList();
}


+ 8
- 4
teensy3/HardwareSerial2.cpp 查看文件

@@ -27,10 +27,14 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <Arduino.h>
#include "HardwareSerial.h"

HardwareSerial2 Serial2;
HardwareSerial2 Serial2(&serialEvent2);

uint8_t _serialEvent2_default __attribute__((weak)) PROGMEM = 0 ;

void serialEvent2() __attribute__((weak));
void serialEvent2() {}
void HardwareSerial2::begin(uint32_t baud) {
serial2_begin(BAUD2DIV2(baud));
if (!_serialEvent2_default) addToSerialEventsList();
}

+ 8
- 3
teensy3/HardwareSerial3.cpp 查看文件

@@ -28,9 +28,14 @@
* SOFTWARE.
*/

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

HardwareSerial3 Serial3;
HardwareSerial3 Serial3(&serialEvent3);

void serialEvent3() __attribute__((weak));
void serialEvent3() {}
uint8_t _serialEvent3_default __attribute__((weak)) PROGMEM = 0 ;

void HardwareSerial3::begin(uint32_t baud) {
serial3_begin(BAUD2DIV3(baud));
if (!_serialEvent3_default) addToSerialEventsList();
}

+ 8
- 3
teensy3/HardwareSerial4.cpp 查看文件

@@ -28,13 +28,18 @@
* SOFTWARE.
*/

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

#ifdef HAS_KINETISK_UART3

HardwareSerial4 Serial4;
HardwareSerial4 Serial4(&serialEvent4);

void serialEvent4() __attribute__((weak));
void serialEvent4() {}
uint8_t _serialEvent4_default __attribute__((weak)) PROGMEM = 0 ;

void HardwareSerial4::begin(uint32_t baud) {
serial4_begin(BAUD2DIV3(baud));
if (!_serialEvent4_default) addToSerialEventsList();
}

#endif

+ 8
- 3
teensy3/HardwareSerial5.cpp 查看文件

@@ -28,13 +28,18 @@
* SOFTWARE.
*/

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

#ifdef HAS_KINETISK_UART4

HardwareSerial5 Serial5;
HardwareSerial5 Serial5(&serialEvent5);

void serialEvent5() __attribute__((weak));
void serialEvent5() {}
uint8_t _serialEvent5_default __attribute__((weak)) PROGMEM = 0 ;

void HardwareSerial5::begin(uint32_t baud) {
serial5_begin(BAUD2DIV3(baud));
if (!_serialEvent5_default) addToSerialEventsList();
}

#endif

+ 12
- 3
teensy3/HardwareSerial6.cpp 查看文件

@@ -28,13 +28,22 @@
* SOFTWARE.
*/

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

#if defined(HAS_KINETISK_UART5) || defined (HAS_KINETISK_LPUART0)

HardwareSerial6 Serial6;
HardwareSerial6 Serial6(&serialEvent6);

void serialEvent6() __attribute__((weak));
void serialEvent6() {}
uint8_t _serialEvent6_default __attribute__((weak)) PROGMEM = 0 ;

void HardwareSerial6::begin(uint32_t baud) {
#if defined(__MK66FX1M0__) // For LPUART just pass baud straight in.
serial6_begin(baud);
#else
serial6_begin(BAUD2DIV3(baud));
#endif
if (!_serialEvent6_default) addToSerialEventsList();
}

#endif

+ 1
- 1
teensy3/IPAddress.cpp 查看文件

@@ -17,7 +17,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

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

size_t IPAddress::printTo(Print& p) const

+ 1
- 1
teensy3/Makefile 查看文件

@@ -53,7 +53,7 @@ endif
OPTIONS = -DF_CPU=48000000 -DUSB_SERIAL -DLAYOUT_US_ENGLISH -DUSING_MAKEFILE

# options needed by many Arduino libraries to configure for Teensy 3.x
OPTIONS += -D__$(MCU)__ -DARDUINO=10805 -DTEENSYDUINO=141
OPTIONS += -D__$(MCU)__ -DARDUINO=10805 -DTEENSYDUINO=144

# use "cortex-m4" for Teensy 3.x
# use "cortex-m0plus" for Teensy LC

+ 34
- 5
teensy3/Print.cpp 查看文件

@@ -34,15 +34,12 @@
// developed for Teensyduino have made their way back into
// Arduino's code base. :-)

#include <inttypes.h>
#include <math.h>

#include "Print.h"

#include <Arduino.h>


size_t Print::write(const uint8_t *buffer, size_t size)
{
if (buffer == nullptr) return 0;
size_t count = 0;
while (size--) count += write(*buffer++);
return count;
@@ -290,6 +287,38 @@ size_t Print::printNumber(unsigned long n, uint8_t base, uint8_t sign)

#endif

size_t Print::print(int64_t n)
{
if (n < 0) return printNumber64(-n, 10, 1);
return printNumber64(n, 10, 0);
}

size_t Print::printNumber64(uint64_t n, uint8_t base, uint8_t sign)
{
uint8_t buf[66];
uint8_t digit, i;

if (base < 2) return 0;
if (n == 0) {
buf[sizeof(buf) - 1] = '0';
i = sizeof(buf) - 1;
} else {
i = sizeof(buf) - 1;
while (1) {
digit = n % base;
buf[i] = ((digit < 10) ? '0' + digit : 'A' + digit - 10);
n /= base;
if (n == 0) break;
i--;
}
}
if (sign) {
i--;
buf[i] = '-';
}
return write(buf + i, sizeof(buf) - i);
}

size_t Print::printFloat(double number, uint8_t digits)
{
uint8_t sign=0;

+ 15
- 4
teensy3/Print.h 查看文件

@@ -45,9 +45,9 @@

// 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
//#ifndef BYTE
//#define BYTE 0
//#endif

class __FlashStringHelper;

@@ -71,12 +71,16 @@ class Print
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(int64_t n);
size_t print(uint64_t n) { return printNumber64(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(int64_t n, int base) { return (base == 10) ? print(n) : printNumber64(n, base, 0); }
size_t print(uint64_t n, int base) { return printNumber64(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); }
@@ -91,18 +95,24 @@ class Print
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(int64_t n) { return print(n) + println(); }
size_t println(uint64_t 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(int64_t n, int base) { return print(n, base) + println(); }
size_t println(uint64_t 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, ...);
// format warnings are too pedantic - disable until newer toolchain offers better...
// https://forum.pjrc.com/threads/62473?p=256873&viewfull=1#post256873
int printf(const char *format, ...) /*__attribute__ ((format (printf, 2, 3)))*/;
int printf(const __FlashStringHelper *format, ...);
protected:
void setWriteError(int err = 1) { write_error = err; }
@@ -126,6 +136,7 @@ class Print
#else
size_t printNumber(unsigned long n, uint8_t base, uint8_t sign);
#endif
size_t printNumber64(uint64_t n, uint8_t base, uint8_t sign);
};



+ 10
- 1
teensy3/SPIFIFO.h 查看文件

@@ -37,7 +37,16 @@

// The preferred way to set SPI speed is with SPI.beginTransaction()

#if F_BUS == 120000000
#if F_BUS == 128000000
#define HAS_SPIFIFO
#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0)) //(128 / 3) * ((1+0)/2) = 21.3MHz
#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2)) //(128 / 2) * ((1+0)/4)
#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(2)) //(128 / 3) * ((1+0)/4) = 10.6 MHz
#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(6)) //(128 / 2) * ((1+0)/8)
#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(6)) //(128 / 3) * ((1+0)/8) = 5.3 MHz
#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(6)) //(128 / 5) * ((1+0)/8) = 3.2MHz

#elif F_BUS == 120000000
#define HAS_SPIFIFO
#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(120 / 5) * ((1+1)/2)
#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2)) //(120 / 2) * ((1+0)/4) = 15 MHz

+ 9
- 5
teensy3/Stream.cpp 查看文件

@@ -20,8 +20,7 @@
parsing functions based on TextFinder library by Michael Margolis
*/

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

#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field
@@ -90,7 +89,9 @@ bool Stream::find(const char *target, size_t length)
// as find but search ends if the terminator string is found
bool Stream::findUntil(const char *target, const char *terminator)
{
return findUntil(target, strlen(target), terminator, strlen(terminator));
if(target == nullptr) return true;
size_t tlen = (terminator==nullptr)?0:strlen(terminator);
return findUntil(target, strlen(target), terminator, tlen);
}

// reads data from the stream until the target string of the given length is found
@@ -101,9 +102,10 @@ bool Stream::findUntil(const char *target, size_t targetLen, const char *termina
size_t index = 0; // maximum target string length is 64k bytes!
size_t termIndex = 0;
int c;
if( target == nullptr) return true;
if( *target == 0) return true; // return true if target is a null string
if (terminator == nullptr) termLen = 0;

if( *target == 0)
return true; // return true if target is a null string
while( (c = timedRead()) > 0){
if( c == target[index]){
//////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
@@ -216,6 +218,7 @@ float Stream::parseFloat(char skipChar){
//
size_t Stream::readBytes(char *buffer, size_t length)
{
if (buffer == nullptr) return 0;
size_t count = 0;
while (count < length) {
int c = timedRead();
@@ -236,6 +239,7 @@ size_t Stream::readBytes(char *buffer, size_t length)

size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
{
if (buffer == nullptr) return 0;
if (length < 1) return 0;
length--;
size_t index = 0;

+ 1
- 4
teensy3/Tone.cpp 查看文件

@@ -28,10 +28,7 @@
* SOFTWARE.
*/

#include "core_pins.h"
#include "pins_arduino.h"
#include "HardwareSerial.h"
#include "IntervalTimer.h"
#include <Arduino.h>

// IntervalTimer based tone. This allows tone() to share the timers with other
// libraries, rather than permanently hogging one PIT timer even for projects

+ 1
- 0
teensy3/Udp.h 查看文件

@@ -44,6 +44,7 @@ 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

+ 2
- 2
teensy3/WCharacter.h 查看文件

@@ -61,7 +61,7 @@ inline boolean isAlpha(int c)
// that fits into the ASCII character set.
inline boolean isAscii(int c)
{
return ( isascii (c) == 0 ? false : true);
return ((c & ~0x7F) != 0 ? false : true);
}


@@ -143,7 +143,7 @@ inline boolean isHexadecimalDigit(int c)
// ASCII character set, by clearing the high-order bits.
inline int toAscii(int c)
{
return toascii (c);
return (c & 0x7F);
}



+ 2
- 0
teensy3/WProgram.h 查看文件

@@ -52,6 +52,8 @@

#include "avr_emulation.h"
#include "usb_serial.h"
#include "usb_serial2.h"
#include "usb_serial3.h"
#include "usb_seremu.h"
#include "usb_keyboard.h"
#include "usb_mouse.h"

+ 3
- 1
teensy3/WString.cpp 查看文件

@@ -19,7 +19,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

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


/*********************************************/
@@ -484,6 +484,8 @@ unsigned char String::endsWith( const String &s2 ) const
/* Character Access */
/*********************************************/

const char String::zerotermination = 0;

char String::charAt(unsigned int loc) const
{
return operator[](loc);

+ 5
- 1
teensy3/WString.h 查看文件

@@ -164,7 +164,10 @@ public:
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; }
const char * c_str() const {
if (!buffer) return &zerotermination; // https://forum.pjrc.com/threads/63842
return buffer;
}

// search
int indexOf( char ch ) const;
@@ -205,6 +208,7 @@ private:
// for more information http://www.artima.com/cppsource/safebool.html
typedef void (String::*StringIfHelperType)() const;
void StringIfHelper() const {}
static const char zerotermination;
public:
operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; }
};

+ 9
- 7
teensy3/analog.c 查看文件

@@ -40,8 +40,12 @@ static uint8_t analog_reference_internal = 0;
// the alternate clock is connected to OSCERCLK (16 MHz).
// datasheet says ADC clock should be 2 to 12 MHz for 16 bit mode
// datasheet says ADC clock should be 1 to 18 MHz for 8-12 bit mode

#if F_BUS == 120000000
#if F_BUS == 128000000
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(3) + ADC_CFG1_ADICLK(1) // 8 MHz
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 16 MHz
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 16 MHz
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 16 MHz
#elif F_BUS == 120000000
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(3) + ADC_CFG1_ADICLK(1) // 7.5 MHz
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 15 MHz
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 15 MHz
@@ -127,7 +131,7 @@ static uint8_t analog_reference_internal = 0;
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 2 MHz
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 2 MHz
#else
#error "F_BUS must be 120, 108, 96, 90, 80, 72, 64, 60, 56, 54, 48, 40, 36, 24, 4 or 2 MHz"
#error "F_BUS must be 128, 120, 108, 96, 90, 80, 72, 64, 60, 56, 54, 48, 40, 36, 24, 4 or 2 MHz"
#endif

void analog_init(void)
@@ -524,8 +528,7 @@ void analogWriteDAC0(int val)
} else {
DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2
}
if (val < 0) val = 0; // TODO: saturate instruction?
else if (val > 4095) val = 4095;
__asm__ ("usat %[value], #12, %[value]\n\t" : [value] "+r" (val)); // 0 <= val <= 4095

*(volatile aliased_int16_t *)&(DAC0_DAT0L) = val;
#elif defined(__MKL26Z64__)
@@ -554,8 +557,7 @@ void analogWriteDAC1(int val)
} else {
DAC1_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2
}
if (val < 0) val = 0; // TODO: saturate instruction?
else if (val > 4095) val = 4095;
__asm__ ("usat %[value], #12, %[value]\n\t" : [value] "+r" (val)); // 0 <= val <= 4095

*(volatile aliased_int16_t *)&(DAC1_DAT0L) = val;
}

+ 3
- 0
teensy3/avr/eeprom.h 查看文件

@@ -20,6 +20,9 @@
* THE SOFTWARE.
*/

// Guidelines for editing this file:
// https://forum.pjrc.com/threads/34537-Teensy-LC-Increase-EEPROM-Size/page2

#ifndef _AVR_EEPROM_H_
#define _AVR_EEPROM_H_ 1


+ 1
- 0
teensy3/avr/pgmspace.h 查看文件

@@ -26,6 +26,7 @@
#include <inttypes.h>

#define PROGMEM
#define FLASHMEM
#define PGM_P const char *
#define PSTR(str) (str)


+ 1
- 1
teensy3/avr_emulation.cpp 查看文件

@@ -29,7 +29,7 @@
*/


#include "avr_emulation.h"
#include <Arduino.h>
#include "SPIFIFO.h"

uint8_t SPCRemulation::pinout = 0;

+ 1
- 1
teensy3/avr_emulation.h 查看文件

@@ -602,7 +602,7 @@ public:
int ret = 0;
if (digitalReadFast(14)) ret |= (1<<0);
if (digitalReadFast(15)) ret |= (1<<1);
if (digitalReadFast(15)) ret |= (1<<2);
if (digitalReadFast(16)) ret |= (1<<2);
if (digitalReadFast(17)) ret |= (1<<3);
if (digitalReadFast(18)) ret |= (1<<4);
if (digitalReadFast(19)) ret |= (1<<5);

+ 1
- 1
teensy3/avr_functions.h 查看文件

@@ -95,7 +95,7 @@ static inline void eeprom_update_block(const void *buf, void *addr, uint32_t 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)
#if defined(__STRICT_ANSI__) || (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));

+ 448
- 5
teensy3/core_pins.h 查看文件

@@ -292,6 +292,41 @@
#define CORE_PIN32_PORTSET GPIOB_PSOR
#define CORE_PIN33_PORTSET GPIOA_PSOR

#define CORE_PIN0_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN1_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN2_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN3_PORTTOGGLE GPIOA_PTOR
#define CORE_PIN4_PORTTOGGLE GPIOA_PTOR
#define CORE_PIN5_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN6_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN7_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN8_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN9_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN10_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN11_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN12_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN13_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN14_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN15_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN16_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN17_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN18_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN19_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN20_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN21_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN22_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN23_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN24_PORTTOGGLE GPIOA_PTOR
#define CORE_PIN25_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN26_PORTTOGGLE GPIOE_PTOR
#define CORE_PIN27_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN28_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN29_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN30_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN31_PORTTOGGLE GPIOE_PTOR
#define CORE_PIN32_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN33_PORTTOGGLE GPIOA_PTOR

#define CORE_PIN0_PORTCLEAR GPIOB_PCOR
#define CORE_PIN1_PORTCLEAR GPIOB_PCOR
#define CORE_PIN2_PORTCLEAR GPIOD_PCOR
@@ -605,6 +640,34 @@
#define CORE_PIN25_PORTSET FGPIOE_PSOR
#define CORE_PIN26_PORTSET FGPIOE_PSOR

#define CORE_PIN0_PORTTOGGLE FGPIOB_PTOR
#define CORE_PIN1_PORTTOGGLE FGPIOB_PTOR
#define CORE_PIN2_PORTTOGGLE FGPIOD_PTOR
#define CORE_PIN3_PORTTOGGLE FGPIOA_PTOR
#define CORE_PIN4_PORTTOGGLE FGPIOA_PTOR
#define CORE_PIN5_PORTTOGGLE FGPIOD_PTOR
#define CORE_PIN6_PORTTOGGLE FGPIOD_PTOR
#define CORE_PIN7_PORTTOGGLE FGPIOD_PTOR
#define CORE_PIN8_PORTTOGGLE FGPIOD_PTOR
#define CORE_PIN9_PORTTOGGLE FGPIOC_PTOR
#define CORE_PIN10_PORTTOGGLE FGPIOC_PTOR
#define CORE_PIN11_PORTTOGGLE FGPIOC_PTOR
#define CORE_PIN12_PORTTOGGLE FGPIOC_PTOR
#define CORE_PIN13_PORTTOGGLE FGPIOC_PTOR
#define CORE_PIN14_PORTTOGGLE FGPIOD_PTOR
#define CORE_PIN15_PORTTOGGLE FGPIOC_PTOR
#define CORE_PIN16_PORTTOGGLE FGPIOB_PTOR
#define CORE_PIN17_PORTTOGGLE FGPIOB_PTOR
#define CORE_PIN18_PORTTOGGLE FGPIOB_PTOR
#define CORE_PIN19_PORTTOGGLE FGPIOB_PTOR
#define CORE_PIN20_PORTTOGGLE FGPIOD_PTOR
#define CORE_PIN21_PORTTOGGLE FGPIOD_PTOR
#define CORE_PIN22_PORTTOGGLE FGPIOC_PTOR
#define CORE_PIN23_PORTTOGGLE FGPIOC_PTOR
#define CORE_PIN24_PORTTOGGLE FGPIOE_PTOR
#define CORE_PIN25_PORTTOGGLE FGPIOE_PTOR
#define CORE_PIN26_PORTTOGGLE FGPIOE_PTOR

#define CORE_PIN0_PORTCLEAR FGPIOB_PCOR
#define CORE_PIN1_PORTCLEAR FGPIOB_PCOR
#define CORE_PIN2_PORTCLEAR FGPIOD_PCOR
@@ -1021,6 +1084,71 @@
#define CORE_PIN62_PORTSET GPIOE_PSOR
#define CORE_PIN63_PORTSET GPIOE_PSOR

#define CORE_PIN0_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN1_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN2_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN3_PORTTOGGLE GPIOA_PTOR
#define CORE_PIN4_PORTTOGGLE GPIOA_PTOR
#define CORE_PIN5_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN6_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN7_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN8_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN9_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN10_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN11_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN12_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN13_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN14_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN15_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN16_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN17_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN18_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN19_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN20_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN21_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN22_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN23_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN24_PORTTOGGLE GPIOE_PTOR
#define CORE_PIN25_PORTTOGGLE GPIOA_PTOR
#define CORE_PIN26_PORTTOGGLE GPIOA_PTOR
#define CORE_PIN27_PORTTOGGLE GPIOA_PTOR
#define CORE_PIN28_PORTTOGGLE GPIOA_PTOR
#define CORE_PIN29_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN30_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN31_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN32_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN33_PORTTOGGLE GPIOE_PTOR
#define CORE_PIN34_PORTTOGGLE GPIOE_PTOR
#define CORE_PIN35_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN36_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN37_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN38_PORTTOGGLE GPIOC_PTOR
#define CORE_PIN39_PORTTOGGLE GPIOA_PTOR
#define CORE_PIN40_PORTTOGGLE GPIOA_PTOR
#define CORE_PIN41_PORTTOGGLE GPIOA_PTOR
#define CORE_PIN42_PORTTOGGLE GPIOA_PTOR
#define CORE_PIN43_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN44_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN45_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN46_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN47_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN48_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN49_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN50_PORTTOGGLE GPIOB_PTOR
#define CORE_PIN51_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN52_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN53_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN54_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN55_PORTTOGGLE GPIOD_PTOR
#define CORE_PIN56_PORTTOGGLE GPIOE_PTOR
#define CORE_PIN57_PORTTOGGLE GPIOE_PTOR
#define CORE_PIN58_PORTTOGGLE GPIOE_PTOR
#define CORE_PIN59_PORTTOGGLE GPIOE_PTOR
#define CORE_PIN60_PORTTOGGLE GPIOE_PTOR
#define CORE_PIN61_PORTTOGGLE GPIOE_PTOR
#define CORE_PIN62_PORTTOGGLE GPIOE_PTOR
#define CORE_PIN63_PORTTOGGLE GPIOE_PTOR

#define CORE_PIN0_PORTCLEAR GPIOB_PCOR
#define CORE_PIN1_PORTCLEAR GPIOB_PCOR
#define CORE_PIN2_PORTCLEAR GPIOD_PCOR
@@ -1762,6 +1890,213 @@ static inline void digitalWriteFast(uint8_t pin, uint8_t val)
}
}

void digitalToggle(uint8_t pin);
static inline void digitalToggleFast(uint8_t pin) __attribute__((always_inline, unused));
static inline void digitalToggleFast(uint8_t pin)
{
if (__builtin_constant_p(pin)) {
if (pin == 0) {
CORE_PIN0_PORTTOGGLE = CORE_PIN0_BITMASK;
}
else if (pin == 1) {
CORE_PIN1_PORTTOGGLE = CORE_PIN1_BITMASK;
}
else if (pin == 2) {
CORE_PIN2_PORTTOGGLE = CORE_PIN2_BITMASK;
}
else if (pin == 3) {
CORE_PIN3_PORTTOGGLE = CORE_PIN3_BITMASK;
}
else if (pin == 4) {
CORE_PIN4_PORTTOGGLE = CORE_PIN4_BITMASK;
}
else if (pin == 5) {
CORE_PIN5_PORTTOGGLE = CORE_PIN5_BITMASK;
}
else if (pin == 6) {
CORE_PIN6_PORTTOGGLE = CORE_PIN6_BITMASK;
}
else if (pin == 7) {
CORE_PIN7_PORTTOGGLE = CORE_PIN7_BITMASK;
}
else if (pin == 8) {
CORE_PIN8_PORTTOGGLE = CORE_PIN8_BITMASK;
}
else if (pin == 9) {
CORE_PIN9_PORTTOGGLE = CORE_PIN9_BITMASK;
}
else if (pin == 10) {
CORE_PIN10_PORTTOGGLE = CORE_PIN10_BITMASK;
}
else if (pin == 11) {
CORE_PIN11_PORTTOGGLE = CORE_PIN11_BITMASK;
}
else if (pin == 12) {
CORE_PIN12_PORTTOGGLE = CORE_PIN12_BITMASK;
}
else if (pin == 13) {
CORE_PIN13_PORTTOGGLE = CORE_PIN13_BITMASK;
}
else if (pin == 14) {
CORE_PIN14_PORTTOGGLE = CORE_PIN14_BITMASK;
}
else if (pin == 15) {
CORE_PIN15_PORTTOGGLE = CORE_PIN15_BITMASK;
}
else if (pin == 16) {
CORE_PIN16_PORTTOGGLE = CORE_PIN16_BITMASK;
}
else if (pin == 17) {
CORE_PIN17_PORTTOGGLE = CORE_PIN17_BITMASK;
}
else if (pin == 18) {
CORE_PIN18_PORTTOGGLE = CORE_PIN18_BITMASK;
}
else if (pin == 19) {
CORE_PIN19_PORTTOGGLE = CORE_PIN19_BITMASK;
}
else if (pin == 20) {
CORE_PIN20_PORTTOGGLE = CORE_PIN20_BITMASK;
}
else if (pin == 21) {
CORE_PIN21_PORTTOGGLE = CORE_PIN21_BITMASK;
}
else if (pin == 22) {
CORE_PIN22_PORTTOGGLE = CORE_PIN22_BITMASK;
}
else if (pin == 23) {
CORE_PIN23_PORTTOGGLE = CORE_PIN23_BITMASK;
}
else if (pin == 24) {
CORE_PIN24_PORTTOGGLE = CORE_PIN24_BITMASK;
}
else if (pin == 25) {
CORE_PIN25_PORTTOGGLE = CORE_PIN25_BITMASK;
}
else if (pin == 26) {
CORE_PIN26_PORTTOGGLE = CORE_PIN26_BITMASK;
}
#if defined(CORE_PIN27_PORTTOGGLE)
else if (pin == 27) {
CORE_PIN27_PORTTOGGLE = CORE_PIN27_BITMASK;
}
else if (pin == 28) {
CORE_PIN28_PORTTOGGLE = CORE_PIN28_BITMASK;
}
else if (pin == 29) {
CORE_PIN29_PORTTOGGLE = CORE_PIN29_BITMASK;
}
else if (pin == 30) {
CORE_PIN30_PORTTOGGLE = CORE_PIN30_BITMASK;
}
else if (pin == 31) {
CORE_PIN31_PORTTOGGLE = CORE_PIN31_BITMASK;
}
else if (pin == 32) {
CORE_PIN32_PORTTOGGLE = CORE_PIN32_BITMASK;
}
else if (pin == 33) {
CORE_PIN33_PORTTOGGLE = CORE_PIN33_BITMASK;
}
#endif
#if defined(CORE_PIN34_PORTSET)
else if (pin == 34) {
CORE_PIN34_PORTTOGGLE = CORE_PIN34_BITMASK;
}
else if (pin == 35) {
CORE_PIN35_PORTTOGGLE = CORE_PIN35_BITMASK;
}
else if (pin == 36) {
CORE_PIN36_PORTTOGGLE = CORE_PIN36_BITMASK;
}
else if (pin == 37) {
CORE_PIN37_PORTTOGGLE = CORE_PIN37_BITMASK;
}
else if (pin == 38) {
CORE_PIN38_PORTTOGGLE = CORE_PIN38_BITMASK;
}
else if (pin == 39) {
CORE_PIN39_PORTTOGGLE = CORE_PIN39_BITMASK;
}
else if (pin == 40) {
CORE_PIN40_PORTTOGGLE = CORE_PIN40_BITMASK;
}
else if (pin == 41) {
CORE_PIN41_PORTTOGGLE = CORE_PIN41_BITMASK;
}
else if (pin == 42) {
CORE_PIN42_PORTTOGGLE = CORE_PIN42_BITMASK;
}
else if (pin == 43) {
CORE_PIN43_PORTTOGGLE = CORE_PIN43_BITMASK;
}
else if (pin == 44) {
CORE_PIN44_PORTTOGGLE = CORE_PIN44_BITMASK;
}
else if (pin == 45) {
CORE_PIN45_PORTTOGGLE = CORE_PIN45_BITMASK;
}
else if (pin == 46) {
CORE_PIN46_PORTTOGGLE = CORE_PIN46_BITMASK;
}
else if (pin == 47) {
CORE_PIN47_PORTTOGGLE = CORE_PIN47_BITMASK;
}
else if (pin == 48) {
CORE_PIN48_PORTTOGGLE = CORE_PIN48_BITMASK;
}
else if (pin == 49) {
CORE_PIN49_PORTTOGGLE = CORE_PIN49_BITMASK;
}
else if (pin == 50) {
CORE_PIN50_PORTTOGGLE = CORE_PIN50_BITMASK;
}
else if (pin == 51) {
CORE_PIN51_PORTTOGGLE = CORE_PIN51_BITMASK;
}
else if (pin == 52) {
CORE_PIN52_PORTTOGGLE = CORE_PIN52_BITMASK;
}
else if (pin == 53) {
CORE_PIN53_PORTTOGGLE = CORE_PIN53_BITMASK;
}
else if (pin == 54) {
CORE_PIN54_PORTTOGGLE = CORE_PIN54_BITMASK;
}
else if (pin == 55) {
CORE_PIN55_PORTTOGGLE = CORE_PIN55_BITMASK;
}
else if (pin == 56) {
CORE_PIN56_PORTTOGGLE = CORE_PIN56_BITMASK;
}
else if (pin == 57) {
CORE_PIN57_PORTTOGGLE = CORE_PIN57_BITMASK;
}
else if (pin == 58) {
CORE_PIN58_PORTTOGGLE = CORE_PIN58_BITMASK;
}
else if (pin == 59) {
CORE_PIN59_PORTTOGGLE = CORE_PIN59_BITMASK;
}
else if (pin == 60) {
CORE_PIN60_PORTTOGGLE = CORE_PIN60_BITMASK;
}
else if (pin == 61) {
CORE_PIN61_PORTTOGGLE = CORE_PIN61_BITMASK;
}
else if (pin == 62) {
CORE_PIN62_PORTTOGGLE = CORE_PIN62_BITMASK;
}
else if (pin == 63) {
CORE_PIN63_PORTTOGGLE = CORE_PIN63_BITMASK;
}
#endif
}
else {
*portToggleRegister(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)
@@ -1996,6 +2331,16 @@ static inline uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrde
void _reboot_Teensyduino_(void) __attribute__((noreturn));
void _restart_Teensyduino_(void) __attribute__((noreturn));

// Define a set of flags to know which things yield should check when called.
// Probably should be in a better spot.
extern uint8_t yield_active_check_flags;

#define YIELD_CHECK_USB_SERIAL 0x1 // check the USB for Serial.available()
#define YIELD_CHECK_HARDWARE_SERIAL 0x2 // check Hardware Serial ports available
#define YIELD_CHECK_EVENT_RESPONDER 0x4 // User has created eventResponders that use yield
#define YIELD_CHECK_USB_SERIALUSB1 0x8 // Check for SerialUSB1
#define YIELD_CHECK_USB_SERIALUSB2 0x10 // Check for SerialUSB2

void yield(void);

void delay(uint32_t msec);
@@ -2023,7 +2368,9 @@ uint32_t micros(void);
static inline void delayMicroseconds(uint32_t) __attribute__((always_inline, unused));
static inline void delayMicroseconds(uint32_t usec)
{
#if F_CPU == 240000000
#if F_CPU == 256000000
uint32_t n = usec * 85;
#elif F_CPU == 240000000
uint32_t n = usec * 80;
#elif F_CPU == 216000000
uint32_t n = usec * 72;
@@ -2063,11 +2410,13 @@ static inline void delayMicroseconds(uint32_t usec)
#endif
#ifdef KINETISL
"sub %0, #1" "\n\t"
"bne L_%=_delayMicroseconds" "\n"
: "+l" (n) :
#else
"subs %0, #1" "\n\t"
#endif
"bne L_%=_delayMicroseconds" "\n"
: "+r" (n) :
#endif
);
}

@@ -2075,9 +2424,103 @@ static inline void delayMicroseconds(uint32_t usec)
}
#endif




static inline void delayNanoseconds(uint32_t) __attribute__((always_inline, unused));
static inline void delayNanoseconds(uint32_t nsec)
{
if (__builtin_constant_p(nsec)) {
// use NOPs for the common usage of a constexpr input and short delay
if (nsec == 0) return;
if (nsec <= 1000 / (F_CPU / 1000000)) {
__asm__ volatile("nop");
return;
}
if (nsec <= 2000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop");
return;
}
if (nsec <= 3000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop");
return;
}
if (nsec <= 4000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop");
return;
}
if (nsec <= 5000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
return;
}
if (nsec <= 6000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop");
return;
}
if (nsec <= 7000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop");
return;
}
if (nsec <= 8000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop");
return;
}
if (nsec <= 9000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop\n nop");
return;
}
if (nsec <= 10000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
return;
}
if (nsec <= 11000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop");
return;
}
if (nsec <= 12000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop");
return;
}
if (nsec <= 13000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop");
return;
}
if (nsec <= 14000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop\n nop");
return;
}
if (nsec <= 15000 / (F_CPU / 1000000)) {
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
__asm__ volatile("nop\n nop\n nop\n nop\n nop");
return;
}
}
uint32_t n = nsec * (F_CPU / 45776) >> 16;
if (n == 0) return;
__asm__ volatile(
"L_%=_delayNanoseconds:" "\n\t"
#ifdef KINETISL
"sub %0, #1" "\n\t"
"bne L_%=_delayNanoseconds" "\n"
: "+l" (n) :
#else
"subs %0, #1" "\n\t"
"bne L_%=_delayNanoseconds" "\n"
: "+r" (n) :
#endif
);
}




+ 8
- 0
teensy3/eeprom.c 查看文件

@@ -28,6 +28,14 @@
* SOFTWARE.
*/

// To configure the EEPROM size, edit E2END in avr/eeprom.h.
//
// Do *NOT* edit EEPROM_SIZE in this file. It will automatically
// change based on your changes to E2END in avr/eeprom.h.
//
// Generally you should avoid editing this code, unless you really
// know what you're doing.

#include "kinetis.h"
#include <avr/eeprom.h>
//#include "HardwareSerial.h"

+ 2
- 2
teensy3/keylayouts.h 查看文件

@@ -1451,7 +1451,7 @@ extern "C"{
#define ASCII_20 KEY_SPACE // 32
#define ASCII_21 KEY_1 + SHIFT_MASK // 33 !
#define ASCII_22 KEY_2 + SHIFT_MASK // 34 "
#define ASCII_23 KEY_BACKSPACE // 35 #
#define ASCII_23 KEY_BACKSLASH // 35 #
#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $
#define ASCII_25 KEY_5 + SHIFT_MASK // 37 %
#define ASCII_26 KEY_7 + SHIFT_MASK // 38 &
@@ -4533,7 +4533,7 @@ extern "C"{
#define ASCII_20 KEY_SPACE // 32
#define ASCII_21 KEY_1 + SHIFT_MASK // 33 !
#define ASCII_22 KEY_2 + SHIFT_MASK // 34 "
#define ASCII_23 KEY_BACKSPACE // 35 #
#define ASCII_23 KEY_BACKSLASH // 35 #
#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $
#define ASCII_25 KEY_5 + SHIFT_MASK // 37 %
#define ASCII_26 KEY_7 + SHIFT_MASK // 38 &

+ 36
- 21
teensy3/kinetis.h 查看文件

@@ -761,8 +761,14 @@ enum IRQ_NUMBER_t {

#endif // end of board-specific definitions


#if (F_CPU == 240000000)
#if (F_CPU == 256000000)
#define F_PLL 256000000
#ifndef F_BUS
#define F_BUS 64000000
//#define F_BUS 128000000 // all the usual overclocking caveats apply...
#endif
#define F_MEM 32000000
#elif (F_CPU == 240000000)
#define F_PLL 240000000
#ifndef F_BUS
#define F_BUS 60000000
@@ -864,6 +870,7 @@ enum IRQ_NUMBER_t {

#define PORTA_PCR0 (*(volatile uint32_t *)0x40049000) // Pin Control Register n
#define PORT_PCR_ISF ((uint32_t)0x01000000) // Interrupt Status Flag
// how to use PORT_PCR_ISF with polling: https://forum.pjrc.com/threads/58193
#define PORT_PCR_IRQC(n) ((uint32_t)(((n) & 15) << 16)) // Interrupt Configuration
#define PORT_PCR_IRQC_MASK ((uint32_t)0x000F0000)
#define PORT_PCR_LK ((uint32_t)0x00008000) // Lock Register
@@ -3329,8 +3336,8 @@ typedef struct {
#define FTM0_CONF (*(volatile uint32_t *)0x40038084) // Configuration
#define FTM_CONF_GTBEOUT 0x400 // Global Time Base Output
#define FTM_CONF_GTBEEN 0x200 // Global Time Base Enable
#define FTM_CONF_BDMMODE (((n) & 3) << 6) // Behavior when in debug mode
#define FTM_CONF_NUMTOF (((n) & 31) << 0) // ratio of counter overflows to TOF bit set
#define FTM_CONF_BDMMODE(n) (((n) & 3) << 6) // Behavior when in debug mode
#define FTM_CONF_NUMTOF(n) (((n) & 31) << 0) // ratio of counter overflows to TOF bit set
#define FTM0_FLTPOL (*(volatile uint32_t *)0x40038088) // FTM Fault Input Polarity
#define FTM_FLTPOL_FLT3POL 0x08 // Fault Input 3 Polarity
#define FTM_FLTPOL_FLT2POL 0x04 // Fault Input 2 Polarity
@@ -3621,22 +3628,22 @@ typedef struct {
#define ENET_EIR_TS_AVAIL ((uint32_t)0x00010000) // Transmit Timestamp Available
#define ENET_EIR_TS_TIMER ((uint32_t)0x00008000) // Timestamp Timer
#define ENET_EIMR (*(volatile uint32_t *)0x400C0008) // Interrupt Mask Register
#define ENET_EIRM_BABR ((uint32_t)0x40000000) // Babbling Receive Error Mask
#define ENET_EIRM_BABT ((uint32_t)0x20000000) // Babbling Transmit Error Mask
#define ENET_EIRM_GRA ((uint32_t)0x10000000) // Graceful Stop Complete Mask
#define ENET_EIRM_TXF ((uint32_t)0x08000000) // Transmit Frame Interrupt Mask
#define ENET_EIRM_TXB ((uint32_t)0x04000000) // Transmit Buffer Interrupt Mask
#define ENET_EIRM_RXF ((uint32_t)0x02000000) // Receive Frame Interrupt Mask
#define ENET_EIRM_RXB ((uint32_t)0x01000000) // Receive Buffer Interrupt Mask
#define ENET_EIRM_MII ((uint32_t)0x00800000) // MII Interrupt Mask
#define ENET_EIRM_EBERR ((uint32_t)0x00400000) // Ethernet Bus Error Mask
#define ENET_EIRM_LC ((uint32_t)0x00200000) // Late Collision Mask
#define ENET_EIRM_RL ((uint32_t)0x00100000) // Collision Retry Limit Mask
#define ENET_EIRM_UN ((uint32_t)0x00080000) // Transmit FIFO Underrun Mask
#define ENET_EIRM_PLR ((uint32_t)0x00040000) // Payload Receive Error Mask
#define ENET_EIRM_WAKEUP ((uint32_t)0x00020000) // Node Wakeup Request Indication Mask
#define ENET_EIRM_TS_AVAIL ((uint32_t)0x00010000) // Transmit Timestamp Available Mask
#define ENET_EIRM_TS_TIMER ((uint32_t)0x00008000) // Timestamp Timer Mask
#define ENET_EIMR_BABR ((uint32_t)0x40000000) // Babbling Receive Error Mask
#define ENET_EIMR_BABT ((uint32_t)0x20000000) // Babbling Transmit Error Mask
#define ENET_EIMR_GRA ((uint32_t)0x10000000) // Graceful Stop Complete Mask
#define ENET_EIMR_TXF ((uint32_t)0x08000000) // Transmit Frame Interrupt Mask
#define ENET_EIMR_TXB ((uint32_t)0x04000000) // Transmit Buffer Interrupt Mask
#define ENET_EIMR_RXF ((uint32_t)0x02000000) // Receive Frame Interrupt Mask
#define ENET_EIMR_RXB ((uint32_t)0x01000000) // Receive Buffer Interrupt Mask
#define ENET_EIMR_MII ((uint32_t)0x00800000) // MII Interrupt Mask
#define ENET_EIMR_EBERR ((uint32_t)0x00400000) // Ethernet Bus Error Mask
#define ENET_EIMR_LC ((uint32_t)0x00200000) // Late Collision Mask
#define ENET_EIMR_RL ((uint32_t)0x00100000) // Collision Retry Limit Mask
#define ENET_EIMR_UN ((uint32_t)0x00080000) // Transmit FIFO Underrun Mask
#define ENET_EIMR_PLR ((uint32_t)0x00040000) // Payload Receive Error Mask
#define ENET_EIMR_WAKEUP ((uint32_t)0x00020000) // Node Wakeup Request Indication Mask
#define ENET_EIMR_TS_AVAIL ((uint32_t)0x00010000) // Transmit Timestamp Available Mask
#define ENET_EIMR_TS_TIMER ((uint32_t)0x00008000) // Timestamp Timer Mask
#define ENET_RDAR (*(volatile uint32_t *)0x400C0010) // Receive Descriptor Active Register
#define ENET_RDAR_RDAR ((uint32_t)0x01000000)
#define ENET_TDAR (*(volatile uint32_t *)0x400C0014) // Transmit Descriptor Active Register
@@ -4545,7 +4552,7 @@ typedef struct {
#define SPI1_MH (KINETISL_SPI1.MH) // Match High
#define SPI1_DL (KINETISL_SPI1.DL) // Data Low
#define SPI1_DH (KINETISL_SPI1.DH) // Data High
#define SPI1_CI (KINETISL_SPI1.CI) // Dlear Interrupt
#define SPI1_CI (KINETISL_SPI1.CI) // Clear Interrupt
#define SPI1_C3 (KINETISL_SPI1.C3) // Control Register 3
#endif

@@ -5851,6 +5858,14 @@ extern void software_isr(void);
extern void (* _VectorsRam[NVIC_NUM_INTERRUPTS+16])(void);
extern void (* const _VectorsFlash[NVIC_NUM_INTERRUPTS+16])(void);

// Cache management functions for compatibility with Teensy 4.0
__attribute__((always_inline, unused))
static inline void arm_dcache_flush(void *addr, uint32_t size) { }
__attribute__((always_inline, unused))
static inline void arm_dcache_delete(void *addr, uint32_t size) { }
__attribute__((always_inline, unused))
static inline void arm_dcache_flush_delete(void *addr, uint32_t size) { }

#ifdef __cplusplus
}
#endif

+ 1
- 1
teensy3/main.cpp 查看文件

@@ -28,7 +28,7 @@
* SOFTWARE.
*/

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

extern "C" int main(void)
{

+ 49
- 10
teensy3/mk20dx128.c 查看文件

@@ -745,8 +745,10 @@ void ResetHandler(void)
UART0_C2 = UART_C2_TE;
PORTB_PCR17 = PORT_PCR_MUX(3);
#endif
#ifdef KINETISK
// if the RTC oscillator isn't enabled, get it started early
#if defined(KINETISK) && !defined(__MK66FX1M0__)
// If the RTC oscillator isn't enabled, get it started early.
// But don't do this early on Teensy 3.6 - RTC_CR depends on 3.3V+VBAT
// which may be ~0.4V "behind" 3.3V if the power ramps up slowly.
if (!(RTC_CR & RTC_CR_OSCE)) {
RTC_SR = 0;
RTC_CR = RTC_CR_SC16P | RTC_CR_SC4P | RTC_CR_OSCE;
@@ -841,7 +843,12 @@ void ResetHandler(void)
SMC_PMCTRL = SMC_PMCTRL_RUNM(3); // enter HSRUN mode
while (SMC_PMSTAT != SMC_PMSTAT_HSRUN) ; // wait for HSRUN
#endif
#if F_CPU == 240000000
#if F_CPU == 256000000
//See table in 27.4.6 MCG Control 6 Register (MCG_C6)
//16 -> Multiply factor 32. 32*8MHz =256MHz
MCG_C5 = MCG_C5_PRDIV0(0);
MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(16);
#elif F_CPU == 240000000
MCG_C5 = MCG_C5_PRDIV0(0);
MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(14);
#elif F_CPU == 216000000
@@ -900,7 +907,18 @@ void ResetHandler(void)
#endif
#endif
// now program the clock dividers
#if F_CPU == 240000000
#if F_CPU == 256000000
// config divisors: 256 MHz core, 64 MHz bus, 32 MHz flash, USB = IRC48M
// TODO: gradual ramp-up for HSRUN mode
#if F_BUS == 64000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(3) | SIM_CLKDIV1_OUTDIV4(7);
#elif F_BUS == 128000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(7);
#else
#error "This F_CPU & F_BUS combination is not supported"
#endif
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(0);
#elif F_CPU == 240000000
// config divisors: 240 MHz core, 60 MHz bus, 30 MHz flash, USB = 240 / 5
// TODO: gradual ramp-up for HSRUN mode
#if F_BUS == 60000000
@@ -921,7 +939,8 @@ void ResetHandler(void)
#elif F_BUS == 72000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(2) | SIM_CLKDIV1_OUTDIV4(7);
#elif F_BUS == 108000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(7);
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(7);
#else
#error "This F_CPU & F_BUS combination is not supported"
#endif
@@ -1046,7 +1065,7 @@ void ResetHandler(void)
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV4(1);
#endif
#else
#error "Error, F_CPU must be 192, 180, 168, 144, 120, 96, 72, 48, 24, 16, 8, 4, or 2 MHz"
#error "Error, F_CPU must be 256, 240, 216, 192, 180, 168, 144, 120, 96, 72, 48, 24, 16, 8, 4, or 2 MHz"
#endif

#if F_CPU > 16000000
@@ -1055,11 +1074,13 @@ void ResetHandler(void)
// wait for PLL clock to be used
while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(3)) ;
// now we're in PEE mode
// USB uses PLL clock, trace is CPU clock, CLKOUT=OSCERCLK0
// trace is CPU clock, CLKOUT=OSCERCLK0
#if defined(KINETISK)
#if F_CPU == 216000000 || F_CPU == 180000000
#if F_CPU == 256000000 || F_CPU == 216000000 || F_CPU == 180000000
// USB uses IRC48
SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_IRC48SEL | SIM_SOPT2_TRACECLKSEL | SIM_SOPT2_CLKOUTSEL(6);
#else
// USB uses PLL clock
SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_PLLFLLSEL | SIM_SOPT2_TRACECLKSEL | SIM_SOPT2_CLKOUTSEL(6);
#endif
#elif defined(KINETISL)
@@ -1081,6 +1102,15 @@ void ResetHandler(void)
SMC_PMCTRL = SMC_PMCTRL_RUNM(2); // VLPR mode :-)
#endif

#if defined(__MK66FX1M0__)
// If the RTC oscillator isn't enabled, get it started. For Teensy 3.6
// we don't do this early. See comment above about slow rising power.
if (!(RTC_CR & RTC_CR_OSCE)) {
RTC_SR = 0;
RTC_CR = RTC_CR_SC16P | RTC_CR_SC4P | RTC_CR_OSCE;
}
#endif

// initialize the SysTick counter
SYST_RVR = (F_CPU / 1000) - 1;
SYST_CVR = 0;
@@ -1128,6 +1158,7 @@ void ResetHandler(void)

startup_late_hook();
main();
while (1) ;
}

@@ -1259,7 +1290,11 @@ int kinetis_hsrun_disable(void)
// the peripheral speed (F_BUS). Serial1 & Serial2 baud
// rates will be impacted, but most other peripherals
// will continue functioning at the same speed.
#if F_CPU == 240000000 && F_BUS == 60000000
#if F_CPU == 256000000 && F_BUS == 64000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // TODO: TEST
#elif F_CPU == 256000000 && F_BUS == 128000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // TODO: TEST
#elif F_CPU == 240000000 && F_BUS == 60000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // ok
#elif F_CPU == 240000000 && F_BUS == 80000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok
@@ -1305,7 +1340,11 @@ int kinetis_hsrun_enable(void)
SMC_PMCTRL = SMC_PMCTRL_RUNM(3);
while (SMC_PMSTAT != SMC_PMSTAT_HSRUN) {;} // wait
// Then configure clock for full speed
#if F_CPU == 240000000 && F_BUS == 60000000
#if F_CPU == 256000000 && F_BUS == 64000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7);
#elif F_CPU == 256000000 && F_BUS == 128000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 7);
#elif F_CPU == 240000000 && F_BUS == 60000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7);
#elif F_CPU == 240000000 && F_BUS == 80000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 7);

+ 2
- 0
teensy3/mk20dx128.ld 查看文件

@@ -34,6 +34,7 @@ MEMORY
RAM (rwx) : ORIGIN = 0x1FFFE000, LENGTH = 16K
}

ENTRY(_VectorsFlash)

SECTIONS
{
@@ -107,6 +108,7 @@ SECTIONS
} > RAM

_estack = ORIGIN(RAM) + LENGTH(RAM);
_teensy_model_identifier = 0x1D;
}



+ 2
- 0
teensy3/mk20dx256.ld 查看文件

@@ -34,6 +34,7 @@ MEMORY
RAM (rwx) : ORIGIN = 0x1FFF8000, LENGTH = 64K
}

ENTRY(_VectorsFlash)

SECTIONS
{
@@ -107,6 +108,7 @@ SECTIONS
} > RAM

_estack = ORIGIN(RAM) + LENGTH(RAM);
_teensy_model_identifier = 0x21;
}



+ 3
- 1
teensy3/mk64fx512.ld 查看文件

@@ -31,9 +31,10 @@
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 512K
RAM (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 192K
RAM (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 262136
}

ENTRY(_VectorsFlash)

SECTIONS
{
@@ -107,6 +108,7 @@ SECTIONS
} > RAM

_estack = ORIGIN(RAM) + LENGTH(RAM);
_teensy_model_identifier = 0x1F;
}



+ 2
- 0
teensy3/mk66fx1m0.ld 查看文件

@@ -34,6 +34,7 @@ MEMORY
RAM (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 256K
}

ENTRY(_VectorsFlash)

SECTIONS
{
@@ -107,6 +108,7 @@ SECTIONS
} > RAM

_estack = ORIGIN(RAM) + LENGTH(RAM);
_teensy_model_identifier = 0x22;
}



+ 2
- 0
teensy3/mkl26z64.ld 查看文件

@@ -34,6 +34,7 @@ MEMORY
RAM (rwx) : ORIGIN = 0x1FFFF800, LENGTH = 8K
}

ENTRY(_VectorsFlash)

SECTIONS
{
@@ -107,6 +108,7 @@ SECTIONS
} > RAM

_estack = ORIGIN(RAM) + LENGTH(RAM);
_teensy_model_identifier = 0x20;
}



+ 6
- 3
teensy3/pins_arduino.h 查看文件

@@ -173,11 +173,14 @@ const static uint8_t SCL = 19;
#define analogInputToDigitalPin(p) (((p) <= 9) ? (p) + 14 : (((p) <= 12) ? (p) + 14 : -1))
#define digitalPinHasPWM(p) ((p) == 3 || (p) == 4 || (p) == 6 || (p) == 9 || (p) == 10 || (p) == 16 || (p) == 17 || (p) == 20 || (p) == 22 || (p) == 23)
#define digitalPinToInterrupt(p) ((((p) >= 2 && (p) <= 15) || ((p) >= 20 && (p) <= 23)) ? (p) : -1)
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
// TODO analogInputToDigitalPin needs update...
#define analogInputToDigitalPin(p) (((p) <= 9) ? (p) + 14 : (((p) >= 12 && (p) <= 20) ? (p) + 19 : -1))
#elif defined(__MK64FX512__)
#define analogInputToDigitalPin(p) (((p) <= 9) ? (p) + 14 : (((p) >= 12 && (p) <= 20) ? (p) + 19 : (((p) == 23 || (p) == 24) ? (p) + 26 : -1)))
#define digitalPinHasPWM(p) (((p) >= 2 && (p) <= 10) || (p) == 14 || ((p) >= 20 && (p) <= 23) || (p) == 29 || (p) == 30 || ((p) >= 35 && (p) <= 38))
#define digitalPinToInterrupt(p) ((p) < NUM_DIGITAL_PINS ? (p) : -1)
#elif defined(__MK66FX1M0__)
#define analogInputToDigitalPin(p) (((p) <= 9) ? (p) + 14 : (((p) >= 12 && (p) <= 20) ? (p) + 19 : (((p) == 23 || (p) == 24) ? (p) + 26 : -1)))
#define digitalPinHasPWM(p) (((p) >= 2 && (p) <= 10) || (p) == 14 || (p) == 16 || (p) == 17 || ((p) >= 20 && (p) <= 23) || (p) == 29 || (p) == 30 || ((p) >= 35 && (p) <= 38))
#define digitalPinToInterrupt(p) ((p) < NUM_DIGITAL_PINS ? (p) : -1)
#endif

#define digitalPinToPCICR(p) ((volatile uint8_t *)0)

+ 38
- 5
teensy3/pins_teensy.c 查看文件

@@ -166,7 +166,7 @@ voidFuncPtr isr_table_portE[CORE_MAX_PIN_PORTE+1] = { [0 ... CORE_MAX_PIN_PORTE]

// The Pin Config Register is used to look up the correct interrupt table
// for the corresponding port.
inline voidFuncPtr* getIsrTable(volatile uint32_t *config) {
static inline voidFuncPtr* getIsrTable(volatile uint32_t *config) {
voidFuncPtr* isr_table = NULL;
if(&PORTA_PCR0 <= config && config <= &PORTA_PCR31) isr_table = isr_table_portA;
else if(&PORTB_PCR0 <= config && config <= &PORTB_PCR31) isr_table = isr_table_portB;
@@ -456,7 +456,10 @@ extern void usb_init(void);

#endif

#if F_TIMER == 120000000
#if F_TIMER == 128000000
#define DEFAULT_FTM_MOD (65536 - 1)
#define DEFAULT_FTM_PRESCALE 2
#elif F_TIMER == 120000000
#define DEFAULT_FTM_MOD (61440 - 1)
#define DEFAULT_FTM_PRESCALE 2
#elif F_TIMER == 108000000
@@ -580,12 +583,30 @@ void _init_Teensyduino_internal_(void)
TPM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0);
#endif
analog_init();

#if !defined(TEENSY_INIT_USB_DELAY_BEFORE)
#if TEENSYDUINO >= 142
#define TEENSY_INIT_USB_DELAY_BEFORE 25
#else
#define TEENSY_INIT_USB_DELAY_BEFORE 50
#endif
#endif

#if !defined(TEENSY_INIT_USB_DELAY_AFTER)
#if TEENSYDUINO >= 142
#define TEENSY_INIT_USB_DELAY_AFTER 275
#else
#define TEENSY_INIT_USB_DELAY_AFTER 350
#endif
#endif

// for background about this startup delay, please see these conversations
// https://forum.pjrc.com/threads/36606-startup-time-(400ms)?p=113980&viewfull=1#post113980
// https://forum.pjrc.com/threads/31290-Teensey-3-2-Teensey-Loader-1-24-Issues?p=87273&viewfull=1#post87273
delay(50);

delay(TEENSY_INIT_USB_DELAY_BEFORE);
usb_init();
delay(350);
delay(TEENSY_INIT_USB_DELAY_AFTER);
}


@@ -1044,6 +1065,16 @@ void digitalWrite(uint8_t pin, uint8_t val)

}

void digitalToggle(uint8_t pin)
{
if (pin >= CORE_NUM_DIGITAL) return;
#ifdef KINETISK
*portToggleRegister(pin) = 1;
#else
*portToggleRegister(pin) = digitalPinToBitMask(pin);
#endif
}

uint8_t digitalRead(uint8_t pin)
{
if (pin >= CORE_NUM_DIGITAL) return 0;
@@ -1200,7 +1231,9 @@ void delay(uint32_t ms)
}

// TODO: verify these result in correct timeouts...
#if F_CPU == 240000000
#if F_CPU == 256000000
#define PULSEIN_LOOPS_PER_USEC 34
#elif F_CPU == 240000000
#define PULSEIN_LOOPS_PER_USEC 33
#elif F_CPU == 216000000
#define PULSEIN_LOOPS_PER_USEC 31

+ 10
- 2
teensy3/serial1.c 查看文件

@@ -79,14 +79,20 @@ static volatile uint8_t transmitting = 0;
#define rts_assert() *(rts_pin+8) = rts_mask;
#define rts_deassert() *(rts_pin+4) = rts_mask;
#endif
#if SERIAL1_TX_BUFFER_SIZE > 255
#if SERIAL1_TX_BUFFER_SIZE > 65535
static volatile uint32_t tx_buffer_head = 0;
static volatile uint32_t tx_buffer_tail = 0;
#elif SERIAL1_TX_BUFFER_SIZE > 255
static volatile uint16_t tx_buffer_head = 0;
static volatile uint16_t tx_buffer_tail = 0;
#else
static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0;
#endif
#if SERIAL1_RX_BUFFER_SIZE > 255
#if SERIAL1_RX_BUFFER_SIZE > 65535
static volatile uint32_t rx_buffer_head = 0;
static volatile uint32_t rx_buffer_tail = 0;
#elif SERIAL1_RX_BUFFER_SIZE > 255
static volatile uint16_t rx_buffer_head = 0;
static volatile uint16_t rx_buffer_tail = 0;
#else
@@ -222,6 +228,8 @@ void serial_end(void)
case 26: CORE_PIN26_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break;
#endif
}
UART0_S1;
UART0_D; // clear leftover error status
rx_buffer_head = 0;
rx_buffer_tail = 0;
if (rts_pin) rts_deassert();

+ 10
- 2
teensy3/serial2.c 查看文件

@@ -78,14 +78,20 @@ static volatile uint8_t transmitting = 0;
#define rts_assert() *(rts_pin+8) = rts_mask;
#define rts_deassert() *(rts_pin+4) = rts_mask;
#endif
#if SERIAL2_TX_BUFFER_SIZE > 255
#if SERIAL2_TX_BUFFER_SIZE > 65535
static volatile uint32_t tx_buffer_head = 0;
static volatile uint32_t tx_buffer_tail = 0;
#elif SERIAL2_TX_BUFFER_SIZE > 255
static volatile uint16_t tx_buffer_head = 0;
static volatile uint16_t tx_buffer_tail = 0;
#else
static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0;
#endif
#if SERIAL2_RX_BUFFER_SIZE > 255
#if SERIAL2_RX_BUFFER_SIZE > 65535
static volatile uint32_t rx_buffer_head = 0;
static volatile uint32_t rx_buffer_tail = 0;
#elif SERIAL2_RX_BUFFER_SIZE > 255
static volatile uint16_t rx_buffer_head = 0;
static volatile uint16_t rx_buffer_tail = 0;
#else
@@ -221,6 +227,8 @@ void serial2_end(void)
CORE_PIN9_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); // PTC3
CORE_PIN10_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); // PTC4
#endif
UART1_S1;
UART1_D; // clear leftover error status
rx_buffer_head = 0;
rx_buffer_tail = 0;
if (rts_pin) rts_deassert();

+ 10
- 2
teensy3/serial3.c 查看文件

@@ -79,14 +79,20 @@ static volatile uint8_t transmitting = 0;
#define rts_assert() *(rts_pin+8) = rts_mask;
#define rts_deassert() *(rts_pin+4) = rts_mask;
#endif
#if SERIAL3_TX_BUFFER_SIZE > 255
#if SERIAL3_TX_BUFFER_SIZE > 65535
static volatile uint32_t tx_buffer_head = 0;
static volatile uint32_t tx_buffer_tail = 0;
#elif SERIAL3_TX_BUFFER_SIZE > 255
static volatile uint16_t tx_buffer_head = 0;
static volatile uint16_t tx_buffer_tail = 0;
#else
static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0;
#endif
#if SERIAL3_RX_BUFFER_SIZE > 255
#if SERIAL3_RX_BUFFER_SIZE > 65535
static volatile uint32_t rx_buffer_head = 0;
static volatile uint32_t rx_buffer_tail = 0;
#elif SERIAL3_RX_BUFFER_SIZE > 255
static volatile uint16_t rx_buffer_head = 0;
static volatile uint16_t rx_buffer_tail = 0;
#else
@@ -196,6 +202,8 @@ void serial3_end(void)
case 20: CORE_PIN20_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break;
}
#endif
UART2_S1;
UART2_D; // clear leftover error status
rx_buffer_head = 0;
rx_buffer_tail = 0;
if (rts_pin) rts_deassert();

+ 10
- 2
teensy3/serial4.c 查看文件

@@ -70,14 +70,20 @@ static volatile uint8_t *transmit_pin=NULL;
static volatile uint8_t *rts_pin=NULL;
#define rts_assert() *rts_pin = 0
#define rts_deassert() *rts_pin = 1
#if SERIAL4_TX_BUFFER_SIZE > 255
#if SERIAL4_TX_BUFFER_SIZE > 65535
static volatile uint32_t tx_buffer_head = 0;
static volatile uint32_t tx_buffer_tail = 0;
#elif SERIAL4_TX_BUFFER_SIZE > 255
static volatile uint16_t tx_buffer_head = 0;
static volatile uint16_t tx_buffer_tail = 0;
#else
static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0;
#endif
#if SERIAL4_RX_BUFFER_SIZE > 255
#if SERIAL4_RX_BUFFER_SIZE > 65535
static volatile uint32_t rx_buffer_head = 0;
static volatile uint32_t rx_buffer_tail = 0;
#elif SERIAL4_RX_BUFFER_SIZE > 255
static volatile uint16_t rx_buffer_head = 0;
static volatile uint16_t rx_buffer_tail = 0;
#else
@@ -168,6 +174,8 @@ void serial4_end(void)
case 32: CORE_PIN32_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; // PTC4
case 62: CORE_PIN62_CONFIG = 0; break;
}
UART3_S1;
UART3_D; // clear leftover error status
rx_buffer_head = 0;
rx_buffer_tail = 0;
if (rts_pin) rts_deassert();

+ 10
- 2
teensy3/serial5.c 查看文件

@@ -70,14 +70,20 @@ static volatile uint8_t *transmit_pin=NULL;
static volatile uint8_t *rts_pin=NULL;
#define rts_assert() *rts_pin = 0
#define rts_deassert() *rts_pin = 1
#if SERIAL5_TX_BUFFER_SIZE > 255
#if SERIAL5_TX_BUFFER_SIZE > 65535
static volatile uint32_t tx_buffer_head = 0;
static volatile uint32_t tx_buffer_tail = 0;
#elif SERIAL5_TX_BUFFER_SIZE > 255
static volatile uint16_t tx_buffer_head = 0;
static volatile uint16_t tx_buffer_tail = 0;
#else
static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0;
#endif
#if SERIAL5_RX_BUFFER_SIZE > 255
#if SERIAL5_RX_BUFFER_SIZE > 65535
static volatile uint32_t rx_buffer_head = 0;
static volatile uint32_t rx_buffer_tail = 0;
#elif SERIAL5_RX_BUFFER_SIZE > 255
static volatile uint16_t rx_buffer_head = 0;
static volatile uint16_t rx_buffer_tail = 0;
#else
@@ -153,6 +159,8 @@ void serial5_end(void)
UART4_C2 = 0;
CORE_PIN34_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
CORE_PIN33_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
UART4_S1;
UART4_D; // clear leftover error status
rx_buffer_head = 0;
rx_buffer_tail = 0;
if (rts_pin) rts_deassert();

+ 10
- 2
teensy3/serial6.c 查看文件

@@ -70,14 +70,20 @@ static volatile uint8_t *transmit_pin=NULL;
static volatile uint8_t *rts_pin=NULL;
#define rts_assert() *rts_pin = 0
#define rts_deassert() *rts_pin = 1
#if SERIAL6_TX_BUFFER_SIZE > 255
#if SERIAL6_TX_BUFFER_SIZE > 65535
static volatile uint32_t tx_buffer_head = 0;
static volatile uint32_t tx_buffer_tail = 0;
#elif SERIAL6_TX_BUFFER_SIZE > 255
static volatile uint16_t tx_buffer_head = 0;
static volatile uint16_t tx_buffer_tail = 0;
#else
static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0;
#endif
#if SERIAL6_RX_BUFFER_SIZE > 255
#if SERIAL6_RX_BUFFER_SIZE > 65535
static volatile uint32_t rx_buffer_head = 0;
static volatile uint32_t rx_buffer_tail = 0;
#elif SERIAL6_RX_BUFFER_SIZE > 255
static volatile uint16_t rx_buffer_head = 0;
static volatile uint16_t rx_buffer_tail = 0;
#else
@@ -153,6 +159,8 @@ void serial6_end(void)
UART5_C2 = 0;
CORE_PIN47_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
CORE_PIN48_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
UART5_S1;
UART5_D; // clear leftover error status
rx_buffer_head = 0;
rx_buffer_tail = 0;
if (rts_pin) rts_deassert();

+ 1
- 1
teensy3/serial6_lpuart.c 查看文件

@@ -460,4 +460,4 @@ void lpuart0_status_isr(void)
}
}

#endif // HAS_KINETISK_UART4
#endif // HAS_KINETISK_LPUART0

+ 6
- 0
teensy3/serialEvent.cpp 查看文件

@@ -0,0 +1,6 @@

#include <Arduino.h>
void serialEvent() __attribute__((weak));
void serialEvent() {
}
uint8_t _serialEvent_default PROGMEM = 1;

+ 6
- 0
teensy3/serialEvent1.cpp 查看文件

@@ -0,0 +1,6 @@

#include <Arduino.h>
#include "HardwareSerial.h"
void serialEvent1() __attribute__((weak));
void serialEvent1() {} // No use calling this so disable if called...
uint8_t _serialEvent1_default PROGMEM = 1;

+ 6
- 0
teensy3/serialEvent2.cpp 查看文件

@@ -0,0 +1,6 @@

#include <Arduino.h>
#include "HardwareSerial.h"
void serialEvent2() __attribute__((weak));
void serialEvent2() {} // No use calling this so disable if called...
uint8_t _serialEvent2_default PROGMEM = 1;

+ 6
- 0
teensy3/serialEvent3.cpp 查看文件

@@ -0,0 +1,6 @@

#include <Arduino.h>
#include "HardwareSerial.h"
void serialEvent3() __attribute__((weak));
void serialEvent3() {} // No use calling this so disable if called...
uint8_t _serialEvent3_default PROGMEM = 1;

+ 8
- 0
teensy3/serialEvent4.cpp 查看文件

@@ -0,0 +1,8 @@

#include <Arduino.h>
#include "HardwareSerial.h"
#ifdef HAS_KINETISK_UART3
void serialEvent4() __attribute__((weak));
void serialEvent4() {} // No use calling this so disable if called...
uint8_t _serialEvent4_default PROGMEM = 1;
#endif

+ 8
- 0
teensy3/serialEvent5.cpp 查看文件

@@ -0,0 +1,8 @@

#include <Arduino.h>
#include "HardwareSerial.h"
#ifdef HAS_KINETISK_UART4
void serialEvent5() __attribute__((weak));
void serialEvent5() {} // No use calling this so disable if called...
uint8_t _serialEvent5_default PROGMEM = 1;
#endif

+ 8
- 0
teensy3/serialEvent6.cpp 查看文件

@@ -0,0 +1,8 @@

#include <Arduino.h>
#include "HardwareSerial.h"
#if defined(HAS_KINETISK_UART5) || defined (HAS_KINETISK_LPUART0)
void serialEvent6() __attribute__((weak));
void serialEvent6() {} // No use calling this so disable if called...
uint8_t _serialEvent6_default PROGMEM = 1;
#endif

+ 5
- 0
teensy3/serialEventUSB1.cpp 查看文件

@@ -0,0 +1,5 @@

#include <Arduino.h>
void serialEventUSB1() __attribute__((weak));
void serialEventUSB1() {}
uint8_t _serialEventUSB1_default PROGMEM = 1;

+ 5
- 0
teensy3/serialEventUSB2.cpp 查看文件

@@ -0,0 +1,5 @@

#include <Arduino.h>
void serialEventUSB2() __attribute__((weak));
void serialEventUSB2() {}
uint8_t _serialEventUSB2_default PROGMEM = 1;

+ 1
- 3
teensy3/usb_audio.cpp 查看文件

@@ -28,10 +28,8 @@
* SOFTWARE.
*/

#include <Arduino.h>
#include "usb_dev.h"
#include "usb_audio.h"
#include "HardwareSerial.h"
#include <string.h> // for memcpy()

#ifdef AUDIO_INTERFACE // defined by usb_dev.h -> usb_desc.h
#if F_CPU >= 20000000

+ 187
- 3
teensy3/usb_desc.c 查看文件

@@ -90,7 +90,22 @@ static uint8_t device_descriptor[] = {
#ifdef BCD_DEVICE
LSB(BCD_DEVICE), MSB(BCD_DEVICE), // bcdDevice
#else
// For USB types that don't explicitly define BCD_DEVICE,
// use the minor version number to help teensy_ports
// identify which Teensy model is used.
#if defined(__MKL26Z64__)
0x73, 0x02,
#elif defined(__MK20DX128__)
0x74, 0x02,
#elif defined(__MK20DX256__)
0x75, 0x02,
#elif defined(__MK64FX512__)
0x76, 0x02,
#elif defined(__MK66FX1M0__)
0x77, 0x02,
#else
0x00, 0x02,
#endif
#endif
1, // iManufacturer
2, // iProduct
@@ -379,6 +394,11 @@ static uint8_t multitouch_report_desc[] = {
0x95, 0x01, // Report Count (1)
0x09, 0x56, // Usage (Scan Time)
0x81, 0x02, // Input (variable,absolute)
0x09, 0x54, // USAGE (Contact count)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x0D, // Usage Page (Digitizers)
0x09, 0x55, // Usage (Contact Count Maximum)
0x25, MULTITOUCH_FINGERS, // Logical Maximum (10)
@@ -469,7 +489,21 @@ static uint8_t flightsim_report_desc[] = {
#define CDC_DATA_INTERFACE_DESC_SIZE 0
#endif

#define MIDI_INTERFACE_DESC_POS CDC_DATA_INTERFACE_DESC_POS+CDC_DATA_INTERFACE_DESC_SIZE
#define CDC2_DATA_INTERFACE_DESC_POS CDC_DATA_INTERFACE_DESC_POS+CDC_DATA_INTERFACE_DESC_SIZE
#ifdef CDC2_DATA_INTERFACE
#define CDC2_DATA_INTERFACE_DESC_SIZE 8 + 9+5+5+4+5+7+9+7+7
#else
#define CDC2_DATA_INTERFACE_DESC_SIZE 0
#endif

#define CDC3_DATA_INTERFACE_DESC_POS CDC2_DATA_INTERFACE_DESC_POS+CDC2_DATA_INTERFACE_DESC_SIZE
#ifdef CDC3_DATA_INTERFACE
#define CDC3_DATA_INTERFACE_DESC_SIZE 8 + 9+5+5+4+5+7+9+7+7
#else
#define CDC3_DATA_INTERFACE_DESC_SIZE 0
#endif

#define MIDI_INTERFACE_DESC_POS CDC3_DATA_INTERFACE_DESC_POS+CDC3_DATA_INTERFACE_DESC_SIZE
#ifdef MIDI_INTERFACE
#if !defined(MIDI_NUM_CABLES) || MIDI_NUM_CABLES < 1 || MIDI_NUM_CABLES > 16
#error "MIDI_NUM_CABLES must be defined between 1 to 16"
@@ -588,7 +622,7 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
0x02, // bFunctionClass
0x02, // bFunctionSubClass
0x01, // bFunctionProtocol
4, // iFunction
0, // iFunction
#endif

#ifdef CDC_DATA_INTERFACE
@@ -657,6 +691,156 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
0, // bInterval
#endif // CDC_DATA_INTERFACE

#ifdef CDC2_DATA_INTERFACE
// interface association descriptor, USB ECN, Table 9-Z
8, // bLength
11, // bDescriptorType
CDC2_STATUS_INTERFACE, // bFirstInterface
2, // bInterfaceCount
0x02, // bFunctionClass
0x02, // bFunctionSubClass
0x01, // bFunctionProtocol
0, // iFunction
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
4, // bDescriptorType
CDC2_STATUS_INTERFACE, // bInterfaceNumber
0, // bAlternateSetting
1, // bNumEndpoints
0x02, // bInterfaceClass
0x02, // bInterfaceSubClass
0x01, // bInterfaceProtocol
0, // iInterface
// CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26
5, // bFunctionLength
0x24, // bDescriptorType
0x00, // bDescriptorSubtype
0x10, 0x01, // bcdCDC
// Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27
5, // bFunctionLength
0x24, // bDescriptorType
0x01, // bDescriptorSubtype
0x01, // bmCapabilities
1, // bDataInterface
// Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28
4, // bFunctionLength
0x24, // bDescriptorType
0x02, // bDescriptorSubtype
0x06, // bmCapabilities
// Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33
5, // bFunctionLength
0x24, // bDescriptorType
0x06, // bDescriptorSubtype
CDC2_STATUS_INTERFACE, // bMasterInterface
CDC2_DATA_INTERFACE, // bSlaveInterface0
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
CDC2_ACM_ENDPOINT | 0x80, // bEndpointAddress
0x03, // bmAttributes (0x03=intr)
CDC2_ACM_SIZE, 0, // wMaxPacketSize
64, // bInterval
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
4, // bDescriptorType
CDC2_DATA_INTERFACE, // bInterfaceNumber
0, // bAlternateSetting
2, // bNumEndpoints
0x0A, // bInterfaceClass
0x00, // bInterfaceSubClass
0x00, // bInterfaceProtocol
0, // iInterface
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
CDC2_RX_ENDPOINT, // bEndpointAddress
0x02, // bmAttributes (0x02=bulk)
CDC2_RX_SIZE, 0, // wMaxPacketSize
0, // bInterval
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
CDC2_TX_ENDPOINT | 0x80, // bEndpointAddress
0x02, // bmAttributes (0x02=bulk)
CDC2_TX_SIZE, 0, // wMaxPacketSize
0, // bInterval
#endif // CDC2_DATA_INTERFACE

#ifdef CDC3_DATA_INTERFACE
// interface association descriptor, USB ECN, Table 9-Z
8, // bLength
11, // bDescriptorType
CDC3_STATUS_INTERFACE, // bFirstInterface
2, // bInterfaceCount
0x02, // bFunctionClass
0x02, // bFunctionSubClass
0x01, // bFunctionProtocol
0, // iFunction
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
4, // bDescriptorType
CDC3_STATUS_INTERFACE, // bInterfaceNumber
0, // bAlternateSetting
1, // bNumEndpoints
0x02, // bInterfaceClass
0x02, // bInterfaceSubClass
0x01, // bInterfaceProtocol
0, // iInterface
// CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26
5, // bFunctionLength
0x24, // bDescriptorType
0x00, // bDescriptorSubtype
0x10, 0x01, // bcdCDC
// Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27
5, // bFunctionLength
0x24, // bDescriptorType
0x01, // bDescriptorSubtype
0x01, // bmCapabilities
1, // bDataInterface
// Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28
4, // bFunctionLength
0x24, // bDescriptorType
0x02, // bDescriptorSubtype
0x06, // bmCapabilities
// Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33
5, // bFunctionLength
0x24, // bDescriptorType
0x06, // bDescriptorSubtype
CDC3_STATUS_INTERFACE, // bMasterInterface
CDC3_DATA_INTERFACE, // bSlaveInterface0
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
CDC3_ACM_ENDPOINT | 0x80, // bEndpointAddress
0x03, // bmAttributes (0x03=intr)
CDC3_ACM_SIZE, 0, // wMaxPacketSize
64, // bInterval
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
4, // bDescriptorType
CDC3_DATA_INTERFACE, // bInterfaceNumber
0, // bAlternateSetting
2, // bNumEndpoints
0x0A, // bInterfaceClass
0x00, // bInterfaceSubClass
0x00, // bInterfaceProtocol
0, // iInterface
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
CDC3_RX_ENDPOINT, // bEndpointAddress
0x02, // bmAttributes (0x02=bulk)
CDC3_RX_SIZE, 0, // wMaxPacketSize
0, // bInterval
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
CDC3_TX_ENDPOINT | 0x80, // bEndpointAddress
0x02, // bmAttributes (0x02=bulk)
CDC3_TX_SIZE, 0, // wMaxPacketSize
0, // bInterval
#endif // CDC3_DATA_INTERFACE

#ifdef MIDI_INTERFACE
// Standard MS Interface Descriptor,
9, // bLength
@@ -1086,7 +1270,7 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
0x06, // bInterfaceClass (0x06 = still image)
0x01, // bInterfaceSubClass
0x01, // bInterfaceProtocol
4, // iInterface
0, // iInterface
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType

+ 151
- 68
teensy3/usb_desc.h 查看文件

@@ -40,7 +40,7 @@
#include <stddef.h>

#define ENDPOINT_UNUSED 0x00
#define ENDPOINT_TRANSIMIT_ONLY 0x15
#define ENDPOINT_TRANSMIT_ONLY 0x15
#define ENDPOINT_RECEIVE_ONLY 0x19
#define ENDPOINT_TRANSMIT_AND_RECEIVE 0x1D
#define ENDPOINT_RECEIVE_ISOCHRONOUS 0x18
@@ -136,9 +136,90 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define CDC_ACM_SIZE 16
#define CDC_RX_SIZE 64
#define CDC_TX_SIZE 64
#define ENDPOINT2_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY

#elif defined(USB_DUAL_SERIAL)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x048B
#define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'}
#define MANUFACTURER_NAME_LEN 11
#define PRODUCT_NAME {'D','u','a','l',' ','S','e','r','i','a','l'}
#define PRODUCT_NAME_LEN 11
#define EP0_SIZE 64
#define NUM_ENDPOINTS 7
#define NUM_USB_BUFFERS 22
#define NUM_INTERFACE 4
#define CDC_IAD_DESCRIPTOR 1 // Serial
#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 CDC2_STATUS_INTERFACE 2 // SerialUSB1
#define CDC2_DATA_INTERFACE 3
#define CDC2_ACM_ENDPOINT 5
#define CDC2_RX_ENDPOINT 6
#define CDC2_TX_ENDPOINT 7
#define CDC2_ACM_SIZE 16
#define CDC2_RX_SIZE 64
#define CDC2_TX_SIZE 64
#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_RECEIVE_ONLY
#define ENDPOINT7_CONFIG ENDPOINT_TRANSMIT_ONLY

#elif defined(USB_TRIPLE_SERIAL)
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x048C
#define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'}
#define MANUFACTURER_NAME_LEN 11
#define PRODUCT_NAME {'T','r','i','p','l','e',' ','S','e','r','i','a','l'}
#define PRODUCT_NAME_LEN 13
#define EP0_SIZE 64
#define NUM_ENDPOINTS 10
#define NUM_USB_BUFFERS 32
#define NUM_INTERFACE 6
#define CDC_IAD_DESCRIPTOR 1 // Serial
#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 CDC2_STATUS_INTERFACE 2 // SerialUSB1
#define CDC2_DATA_INTERFACE 3
#define CDC2_ACM_ENDPOINT 5
#define CDC2_RX_ENDPOINT 6
#define CDC2_TX_ENDPOINT 7
#define CDC2_ACM_SIZE 16
#define CDC2_RX_SIZE 64
#define CDC2_TX_SIZE 64
#define CDC3_STATUS_INTERFACE 4 // SerialUSB2
#define CDC3_DATA_INTERFACE 5
#define CDC3_ACM_ENDPOINT 8
#define CDC3_RX_ENDPOINT 9
#define CDC3_TX_ENDPOINT 10
#define CDC3_ACM_SIZE 16
#define CDC3_RX_SIZE 64
#define CDC3_TX_SIZE 64
#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_RECEIVE_ONLY
#define ENDPOINT7_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT8_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT9_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT10_CONFIG ENDPOINT_TRANSMIT_ONLY

#elif defined(USB_KEYBOARDONLY)
#define VENDOR_ID 0x16C0
@@ -166,12 +247,12 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define KEYMEDIA_ENDPOINT 4
#define KEYMEDIA_SIZE 8
#define KEYMEDIA_INTERVAL 4
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSIMIT_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
@@ -207,12 +288,12 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define JOYSTICK_ENDPOINT 4
#define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick
#define JOYSTICK_INTERVAL 2
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSIMIT_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
@@ -253,13 +334,13 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define JOYSTICK_ENDPOINT 6
#define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick
#define JOYSTICK_INTERVAL 1
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT7_CONFIG ENDPOINT_TRANSIMIT_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
@@ -289,13 +370,13 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define KEYMEDIA_INTERVAL 4
#define MULTITOUCH_INTERFACE 3 // Touchscreen
#define MULTITOUCH_ENDPOINT 5
#define MULTITOUCH_SIZE 8
#define MULTITOUCH_SIZE 16
#define MULTITOUCH_FINGERS 10
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY
#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
@@ -329,14 +410,14 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define MOUSE_INTERVAL 2
#define MULTITOUCH_INTERFACE 4 // Touchscreen
#define MULTITOUCH_ENDPOINT 5
#define MULTITOUCH_SIZE 8
#define MULTITOUCH_SIZE 16
#define MULTITOUCH_FINGERS 10
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSIMIT_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
@@ -362,9 +443,9 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 4
#define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY

#elif defined(USB_MIDI4)
@@ -392,9 +473,9 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 4
#define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY

#elif defined(USB_MIDI16)
@@ -422,9 +503,9 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 4
#define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY

#elif defined(USB_MIDI_SERIAL)
@@ -453,10 +534,10 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 5
#define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY

#elif defined(USB_MIDI4_SERIAL)
@@ -486,10 +567,10 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 5
#define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY

#elif defined(USB_MIDI16_SERIAL)
@@ -519,10 +600,10 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 5
#define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY

#elif defined(USB_RAWHID)
@@ -552,9 +633,9 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define SEREMU_RX_ENDPOINT 2
#define SEREMU_RX_SIZE 32
#define SEREMU_RX_INTERVAL 2
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY

#elif defined(USB_FLIGHTSIM)
@@ -582,14 +663,15 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define SEREMU_RX_ENDPOINT 2
#define SEREMU_RX_SIZE 32
#define SEREMU_RX_INTERVAL 2
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_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 0x04D9
#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'}
@@ -616,11 +698,11 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define JOYSTICK_ENDPOINT 5
#define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick
#define JOYSTICK_INTERVAL 1
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY


#elif defined(USB_MTPDISK)
@@ -649,9 +731,10 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define SEREMU_RX_ENDPOINT 2
#define SEREMU_RX_SIZE 32
#define SEREMU_RX_INTERVAL 2
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE
// TODO: Should ENDPOINT4_CONFIG be ENDPOINT_TRANSMIT_ONLY ???
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY

#elif defined(USB_AUDIO)
@@ -678,7 +761,7 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define AUDIO_RX_ENDPOINT 4
#define AUDIO_RX_SIZE 180
#define AUDIO_SYNC_ENDPOINT 5
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ISOCHRONOUS
@@ -716,10 +799,10 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define AUDIO_RX_ENDPOINT 7
#define AUDIO_RX_SIZE 180
#define AUDIO_SYNC_ENDPOINT 8
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_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
@@ -758,10 +841,10 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define AUDIO_RX_ENDPOINT 7
#define AUDIO_RX_SIZE 180
#define AUDIO_SYNC_ENDPOINT 8
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_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
@@ -848,21 +931,21 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
#define MULTITOUCH_ENDPOINT 15
#define MULTITOUCH_SIZE 8
#define MULTITOUCH_FINGERS 10
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY
#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_TRANSIMIT_ONLY
#define ENDPOINT8_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT9_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE
#define ENDPOINT10_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT10_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT11_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE
#define ENDPOINT12_CONFIG ENDPOINT_TRANSIMIT_ONLY
#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_TRANSIMIT_ONLY
#define ENDPOINT15_CONFIG ENDPOINT_TRANSMIT_ONLY

#endif


+ 77
- 15
teensy3/usb_dev.c 查看文件

@@ -45,6 +45,14 @@
#include "usb_mem.h"
#include <string.h> // for memset

// This code has a known bug with compiled with -O2 optimization on gcc 5.4.1
// https://forum.pjrc.com/threads/53574-Teensyduino-1-43-Beta-2?p=186177&viewfull=1#post186177
#if defined(__MKL26Z64__)
#pragma GCC optimize ("Os")
#else
#pragma GCC optimize ("O3")
#endif

// buffer descriptor table

typedef struct {
@@ -345,12 +353,30 @@ static void usb_setup(void)
//serial_print("desc: not found\n");
endpoint0_stall();
return;
#if defined(CDC_STATUS_INTERFACE)
case 0x2221: // CDC_SET_CONTROL_LINE_STATE
usb_cdc_line_rtsdtr_millis = systick_millis_count;
usb_cdc_line_rtsdtr = setup.wValue;
switch (setup.wIndex) {
#ifdef CDC_STATUS_INTERFACE
case CDC_STATUS_INTERFACE:
usb_cdc_line_rtsdtr_millis = systick_millis_count;
usb_cdc_line_rtsdtr = setup.wValue;
break;
#endif
#ifdef CDC2_STATUS_INTERFACE
case CDC2_STATUS_INTERFACE:
usb_cdc2_line_rtsdtr_millis = systick_millis_count;
usb_cdc2_line_rtsdtr = setup.wValue;
break;
#endif
#ifdef CDC3_STATUS_INTERFACE
case CDC3_STATUS_INTERFACE:
usb_cdc3_line_rtsdtr_millis = systick_millis_count;
usb_cdc3_line_rtsdtr = setup.wValue;
break;
#endif
}
//serial_print("set control line state\n");
break;
#ifdef CDC_STATUS_INTERFACE
case 0x2321: // CDC_SEND_BREAK
break;
case 0x2021: // CDC_SET_LINE_CODING
@@ -586,21 +612,39 @@ static void usb_control(uint32_t stat)
case 0x01: // OUT transaction received from host
case 0x02:
//serial_print("PID=OUT\n");
#ifdef CDC_STATUS_INTERFACE
if (setup.wRequestAndType == 0x2021 /*CDC_SET_LINE_CODING*/) {
int i;
uint8_t *dst = (uint8_t *)usb_cdc_line_coding;
//serial_print("set line coding ");
for (i=0; i<7; i++) {
//serial_phex(*buf);
*dst++ = *buf++;
uint32_t *line_coding = NULL;
switch (setup.wIndex) {
#ifdef CDC_STATUS_INTERFACE
case CDC_STATUS_INTERFACE:
line_coding = usb_cdc_line_coding;
break;
#endif
#ifdef CDC2_STATUS_INTERFACE
case CDC2_STATUS_INTERFACE:
line_coding = usb_cdc2_line_coding;
break;
#endif
#ifdef CDC3_STATUS_INTERFACE
case CDC3_STATUS_INTERFACE:
line_coding = usb_cdc3_line_coding;
break;
#endif
}
if (line_coding) {
uint8_t *dst = (uint8_t *)line_coding;
//serial_print("set line coding ");
for (i=0; i<7; i++) {
//serial_phex(*buf);
*dst++ = *buf++;
}
//serial_phex32(line_coding[0]);
//serial_print("\n");
if (line_coding[0] == 134) usb_reboot_timer = 15;
}
//serial_phex32(usb_cdc_line_coding[0]);
//serial_print("\n");
if (usb_cdc_line_coding[0] == 134) usb_reboot_timer = 15;
endpoint0_transmit(NULL, 0);
}
#endif
#ifdef KEYBOARD_INTERFACE
if (setup.word1 == 0x02000921 && setup.word2 == ((1<<16)|KEYBOARD_INTERFACE)) {
keyboard_leds = buf[0];
@@ -711,6 +755,9 @@ uint32_t usb_tx_byte_count(uint32_t endpoint)
return usb_queue_byte_count(tx_first[endpoint]);
}

// Discussion about using this function and USB transmit latency
// https://forum.pjrc.com/threads/58663?p=223513&viewfull=1#post223513
//
uint32_t usb_tx_packet_count(uint32_t endpoint)
{
const usb_packet_t *p;
@@ -848,6 +895,7 @@ void _reboot_Teensyduino_(void)
{
// TODO: initialize R0 with a code....
__asm__ volatile("bkpt");
__builtin_unreachable();
}


@@ -877,6 +925,20 @@ void usb_isr(void)
if (t == 0) usb_serial_flush_callback();
}
#endif
#ifdef CDC2_DATA_INTERFACE
t = usb_cdc2_transmit_flush_timer;
if (t) {
usb_cdc2_transmit_flush_timer = --t;
if (t == 0) usb_serial2_flush_callback();
}
#endif
#ifdef CDC3_DATA_INTERFACE
t = usb_cdc3_transmit_flush_timer;
if (t) {
usb_cdc3_transmit_flush_timer = --t;
if (t == 0) usb_serial3_flush_callback();
}
#endif
#ifdef SEREMU_INTERFACE
t = usb_seremu_transmit_flush_timer;
if (t) {
@@ -1107,7 +1169,7 @@ void usb_init(void)

usb_init_serialnumber();

for (i=0; i <= NUM_ENDPOINTS*4; i++) {
for (i=0; i < (NUM_ENDPOINTS+1)*4; i++) {
table[i].desc = 0;
table[i].addr = 0;
}
@@ -1121,7 +1183,7 @@ void usb_init(void)
#ifdef HAS_KINETIS_MPU
MPU_RGDAAC0 |= 0x03000000;
#endif
#if F_CPU == 180000000 || F_CPU == 216000000
#if F_CPU == 180000000 || F_CPU == 216000000 || F_CPU == 256000000
// if using IRC48M, turn on the USB clock recovery hardware
USB0_CLK_RECOVER_IRC_EN = USB_CLK_RECOVER_IRC_EN_IRC_EN | USB_CLK_RECOVER_IRC_EN_REG_EN;
USB0_CLK_RECOVER_CTRL = USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN |

+ 12
- 9
teensy3/usb_dev.h 查看文件

@@ -67,15 +67,6 @@ static inline uint32_t usb_rx_byte_count(uint32_t endpoint)
return usb_rx_byte_count_data[endpoint];
}

#ifdef CDC_DATA_INTERFACE
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 void usb_serial_flush_callback(void);
#endif

#ifdef SEREMU_INTERFACE
extern volatile uint8_t usb_seremu_transmit_flush_timer;
extern void usb_seremu_flush_callback(void);
@@ -119,6 +110,18 @@ extern void usb_touchscreen_update_callback(void);
}
#endif

#ifdef CDC_DATA_INTERFACE
#include "usb_serial.h"
#endif

#ifdef CDC2_DATA_INTERFACE
#include "usb_serial2.h"
#endif

#ifdef CDC3_DATA_INTERFACE
#include "usb_serial3.h"
#endif

#else // F_CPU < 20000000

#ifdef __cplusplus

+ 172
- 0
teensy3/usb_flightsim.cpp 查看文件

@@ -42,6 +42,12 @@ FlightSimInteger * FlightSimInteger::first = NULL;
FlightSimInteger * FlightSimInteger::last = NULL;
FlightSimFloat * FlightSimFloat::first = NULL;
FlightSimFloat * FlightSimFloat::last = NULL;
/// JB
FlightSimEvent * FlightSimEvent::first = NULL;
FlightSimEvent * FlightSimEvent::last = NULL;
FlightSimData * FlightSimData::first = NULL;
FlightSimData * FlightSimData::last = NULL;
/// JB End

uint8_t FlightSimClass::enabled = 0;
uint8_t FlightSimClass::request_id_messages = 0;
@@ -92,6 +98,146 @@ void FlightSimCommand::sendcmd(uint8_t n)
FlightSimClass::xmit(buf, 4, NULL, 0);
}

/// JB
FlightSimEvent::FlightSimEvent()
{
id = unassigned_id++;
if (!first) {
first = this;
} else {
last->next = this;
}
last = this;
name = NULL;
next = NULL;
occur_callback = NULL;
occurredFlag = 0;
callbackInfo = NULL;
hasCallbackInfo = 0;
value = 0;
FlightSimClass::request_id_messages = 1;
}

void FlightSimEvent::identify(void)
{
uint8_t len, buf[6];

if (!FlightSim.enabled || !name) return;
len = strlen((const char *)name);
buf[0] = len + 6;
buf[1] = 1;
buf[2] = id;
buf[3] = id >> 8;
buf[4] = 3;
buf[5] = 0;
FlightSimClass::xmit(buf, 6, name, len);
}

void FlightSimEvent::send(unsigned int data, unsigned int flags)
{
uint8_t buf[4];
uint32_t txData[2];

if (!FlightSim.enabled || !name) return;
buf[0] = 12;
buf[1] = 7;
buf[2] = id;
buf[3] = id >> 8;
value = data;
txData[0] = data;
txData[1] = flags;
FlightSimClass::xmit(buf, 4, (uint8_t *)&txData, 8);
}

void FlightSimEvent::update(long val)
{
value = (unsigned int) val;
occurredFlag = true;
if (occur_callback) {
if (!hasCallbackInfo) {
(*occur_callback)(val);
} else {
(*(void(*)(long,void*))occur_callback)(val,callbackInfo);
}
}
}

FlightSimEvent * FlightSimEvent::find(unsigned int n)
{
for (FlightSimEvent *p = first; p; p = p->next) {
if (p->id == n) return p;
}
return NULL;
}


FlightSimData::FlightSimData()
{
id = unassigned_id++;
if (!first) {
first = this;
} else {
last->next = this;
}
last = this;
name = NULL;
next = NULL;
valueLen = 0;
hasCallbackInfo = 0;
callbackWithObject = 0;
callbackInfo = NULL;
change_callback = NULL;
FlightSimClass::request_id_messages = 1;
}

void FlightSimData::identify(void)
{
uint8_t len, buf[6];

if (!FlightSim.enabled || !name) return;
len = strlen((const char *)name);
buf[0] = len + 6;
buf[1] = 1;
buf[2] = id;
buf[3] = id >> 8;
buf[4] = 4;
buf[5] = 0;
FlightSimClass::xmit(buf, 6, name, len);
}

void FlightSimData::update(char *val, size_t len)
{
valueLen = len;
memcpy(value, val, len);
if (len<FLIGHTSIM_DATA_MAXLEN) {
memset(value+len,0,FLIGHTSIM_DATA_MAXLEN-len);
}
if (change_callback) {
if (!callbackWithObject) {
if (!hasCallbackInfo) {
(*change_callback)(value);
} else {
(*(void(*)(char*,void*))change_callback)(value,callbackInfo);
}
} else {
if (!hasCallbackInfo) {
(*(void(*)(FlightSimData*))change_callback)(this);
} else {
(*(void(*)(FlightSimData*,void*))change_callback)(this,callbackInfo);
}
}
}
}

FlightSimData * FlightSimData::find(unsigned int n)
{
for (FlightSimData *p = first; p; p = p->next) {
if (p->id == n) return p;
}
return NULL;
}
/// JB End


FlightSimInteger::FlightSimInteger()
{
@@ -287,6 +433,24 @@ void FlightSimClass::update(void)
data.b[2] = p[8];
data.b[3] = p[9];
item->update(data.f);
/// JB
} else if (type == 3) {
FlightSimEvent *item = FlightSimEvent::find(id);
if (!item) break;
#ifdef KINETISK
data.l = *(long *)(p + 6);
#else
data.b[0] = p[6];
data.b[1] = p[7];
data.b[2] = p[8];
data.b[3] = p[9];
#endif
item->update(data.f);
} else if (type == 4) {
FlightSimData *item = FlightSimData::find(id);
if (!item) break;
item->update(((char*)p)+6,len-6);
/// JB End
}
break;
case 0x03: // enable/disable
@@ -313,6 +477,14 @@ void FlightSimClass::update(void)
for (FlightSimCommand *p = FlightSimCommand::first; p; p = p->next) {
p->identify();
}
/// JB
for (FlightSimEvent *p = FlightSimEvent::first; p; p = p->next) {
p->identify();
}
for (FlightSimData *p = FlightSimData::first; p; p=p->next) {
p->identify();
}
/// JB End
for (FlightSimInteger *p = FlightSimInteger::first; p; p = p->next) {
p->identify();
// TODO: send any dirty data

+ 99
- 0
teensy3/usb_flightsim.h 查看文件

@@ -70,6 +70,10 @@ private:
friend class FlightSimCommand;
friend class FlightSimInteger;
friend class FlightSimFloat;
/// JB
friend class FlightSimEvent;
friend class FlightSimData;
/// JB End
};


@@ -94,6 +98,101 @@ private:
friend class FlightSimClass;
};

/// JB
class FlightSimEvent
{
public:
FlightSimEvent();
void assign(const _XpRefStr_ *s) { name = s; if (FlightSimClass::enabled) identify(); }
FlightSimEvent & operator = (const _XpRefStr_ *s) { assign(s); return *this; }
void send() { send(0,0); }
void send(int data) { send(data,0); }
void sendOnce() { send(0,0); }
void sendOnce(int data) { send(data,0); }
void sendRepeat(int data, uint16_t initialDelay, uint16_t repeatDelay) { send(data, initialDelay<<16 | repeatDelay); }
void sendRepeat(uint16_t initialDelay, uint16_t repeatDelay) { send(0, initialDelay<<16 | repeatDelay); }
void stopRepeat() { send(0,-1); }
FlightSimEvent & operator = (int n) { send(n,0); return *this; }
bool occurred() { bool hasOccurred = occurredFlag; occurredFlag = 0; return hasOccurred; }
void identify();
static FlightSimEvent * find(unsigned int n);
void update(long val);
void onOccur(void (*fptr)(long)) {
hasCallbackInfo=false;
occur_callback = fptr;
}
void onOccur(void (*fptr)(long,void*), void* info) {
hasCallbackInfo=true;
occur_callback = (void (*)(long))fptr;
callbackInfo = info;
}
private:
void send(unsigned int data, unsigned int flags);
unsigned int id;
const _XpRefStr_ *name;
bool occurredFlag;
unsigned int value;
FlightSimEvent *next;
void (*occur_callback)(long);
void* callbackInfo;
bool hasCallbackInfo;
static FlightSimEvent *first;
static FlightSimEvent *last;
friend class FlightSimClass;
};

#define FLIGHTSIM_DATA_MAXLEN 58

class FlightSimData
{
public:
FlightSimData();
void assign(const _XpRefStr_ *s) { name = s; if (FlightSimClass::enabled) identify(); }
FlightSimData & operator = (const _XpRefStr_ *s) { assign(s); return *this; }
char *read() { return value; }
operator char* () { return value; }
void identify();
void update(char *val, size_t len);
size_t len() { return valueLen; }
static FlightSimData * find(unsigned int n);
void onChange(void (*fptr)(char *)) {
hasCallbackInfo = false;
change_callback = fptr;
}
void onChange(void (*fptr)(char *,void *), void *info) {
hasCallbackInfo = true;
change_callback = (void (*)(char*)) fptr;
callbackInfo = info;
}
void onChange(void (*fptr)(FlightSimData *)) {
callbackWithObject = true;
hasCallbackInfo = false;
change_callback = (void (*)(char*)) fptr;
}
void onChange(void (*fptr)(FlightSimData *, void*), void* info) {
callbackWithObject = true;
hasCallbackInfo = true;
change_callback = (void (*)(char*)) fptr;
callbackInfo = info;
}
private:
unsigned int id;
const _XpRefStr_ *name;
char value[FLIGHTSIM_DATA_MAXLEN];
size_t valueLen;
void (*change_callback)(char *);
void* callbackInfo;
bool hasCallbackInfo;
bool callbackWithObject;
FlightSimData *next;
static FlightSimData *first;
static FlightSimData *last;
friend class FlightSimClass;
};
/// JB End


class FlightSimInteger
{

+ 15
- 5
teensy3/usb_inst.cpp 查看文件

@@ -28,7 +28,7 @@
* SOFTWARE.
*/

#include "WProgram.h"
#include <Arduino.h>
#include "usb_desc.h"

#if F_CPU >= 20000000
@@ -39,6 +39,18 @@ usb_serial_class Serial;
#endif
#endif

#ifdef CDC2_DATA_INTERFACE
#ifdef CDC2_STATUS_INTERFACE
usb_serial2_class SerialUSB1;
#endif
#endif

#ifdef CDC3_DATA_INTERFACE
#ifdef CDC3_STATUS_INTERFACE
usb_serial3_class SerialUSB2;
#endif
#endif

#ifdef MIDI_INTERFACE
usb_midi_class usbMIDI;
#endif
@@ -75,7 +87,8 @@ usb_serial_class Serial;

#else // F_CPU < 20 MHz

#if defined(USB_SERIAL) || defined(USB_SERIAL_HID)
#if defined(USB_SERIAL) || defined(USB_DUAL_SERIAL) || \
defined(USB_TRIPLE_SERIAL) || defined(USB_SERIAL_HID)
usb_serial_class Serial;
#elif (USB_DISABLED)
usb_serial_class Serial;
@@ -84,6 +97,3 @@ usb_seremu_class Serial;
#endif

#endif // F_CPU

void serialEvent() __attribute__((weak));
void serialEvent() {}

+ 3
- 2
teensy3/usb_joystick.c 查看文件

@@ -48,8 +48,9 @@ static uint8_t transmit_previous_timeout=0;

// When the PC isn't listening, how long do we wait before discarding data?
#define TX_TIMEOUT_MSEC 30

#if F_CPU == 240000000
#if F_CPU == 256000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1706)
#elif F_CPU == 240000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1600)
#elif F_CPU == 216000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440)

+ 3
- 2
teensy3/usb_keyboard.c 查看文件

@@ -496,8 +496,9 @@ static uint8_t transmit_previous_timeout=0;

// When the PC isn't listening, how long do we wait before discarding data?
#define TX_TIMEOUT_MSEC 50

#if F_CPU == 240000000
#if F_CPU == 256000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1706)
#elif F_CPU == 240000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1600)
#elif F_CPU == 216000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440)

+ 2
- 0
teensy3/usb_keyboard.h 查看文件

@@ -87,6 +87,7 @@ public:
void set_key4(uint8_t c) { keyboard_keys[3] = c; }
void set_key5(uint8_t c) { keyboard_keys[4] = c; }
void set_key6(uint8_t c) { keyboard_keys[5] = c; }
#ifdef KEYMEDIA_INTERFACE
void set_media(uint16_t c) {
if (c == 0) {
usb_keymedia_release_all();
@@ -94,6 +95,7 @@ public:
press(c);
}
}
#endif
void send_now(void) { usb_keyboard_send(); }
void press(uint16_t n) { usb_keyboard_press_keycode(n); }
void release(uint16_t n) { usb_keyboard_release_keycode(n); }

+ 12
- 4
teensy3/usb_midi.c 查看文件

@@ -76,8 +76,9 @@ static uint8_t tx_noautoflush=0;

// When the PC isn't listening, how long do we wait before discarding data?
#define TX_TIMEOUT_MSEC 40

#if F_CPU == 240000000
#if F_CPU == 256000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1706)
#elif F_CPU == 240000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1600)
#elif F_CPU == 216000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440)
@@ -102,6 +103,13 @@ static uint8_t tx_noautoflush=0;
#endif


// This 32 bit input format is documented in the "Universal Serial Bus Device Class
// Definition for MIDI Devices" specification, version 1.0, Nov 1, 1999. It can be
// downloaded from www.usb.org. https://www.usb.org/sites/default/files/midi10.pdf
// If the USB-IF reorganizes their website and this link no longer works, Google
// search the name to find it. This data format is shown on page 16 in Figure #8.
// Byte 0 (shown on the left hand side of Figure #8) is the least significant byte
// of this 32 bit input.
void usb_midi_write_packed(uint32_t n)
{
uint32_t index, wait_count=0;
@@ -133,7 +141,7 @@ void usb_midi_write_packed(uint32_t n)
} else {
tx_packet->len = MIDI_TX_SIZE;
usb_tx(MIDI_TX_ENDPOINT, tx_packet);
tx_packet = usb_malloc();
tx_packet = NULL;
}
tx_noautoflush = 0;
}
@@ -189,7 +197,7 @@ void usb_midi_flush_output(void)
if (tx_noautoflush == 0 && tx_packet && tx_packet->index > 0) {
tx_packet->len = tx_packet->index * 4;
usb_tx(MIDI_TX_ENDPOINT, tx_packet);
tx_packet = usb_malloc();
tx_packet = NULL;
}
}


+ 3
- 2
teensy3/usb_mouse.c 查看文件

@@ -116,8 +116,9 @@ static uint8_t transmit_previous_timeout=0;

// When the PC isn't listening, how long do we wait before discarding data?
#define TX_TIMEOUT_MSEC 30

#if F_CPU == 240000000
#if F_CPU == 256000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1706)
#elif F_CPU == 240000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1600)
#elif F_CPU == 216000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440)

+ 3
- 2
teensy3/usb_seremu.c 查看文件

@@ -138,8 +138,9 @@ void usb_seremu_flush_input(void)
// too short, we risk losing data during the stalls that are common with ordinary desktop
// software. If it's too long, we stall the user's program when no software is running.
#define TX_TIMEOUT_MSEC 30

#if F_CPU == 240000000
#if F_CPU == 256000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1706)
#elif F_CPU == 240000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1600)
#elif F_CPU == 216000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440)

+ 3
- 2
teensy3/usb_serial.c 查看文件

@@ -148,8 +148,9 @@ void usb_serial_flush_input(void)
// 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
#if F_CPU == 256000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1706)
#elif F_CPU == 240000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1600)
#elif F_CPU == 216000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440)

+ 5
- 3
teensy3/usb_serial.h 查看文件

@@ -39,6 +39,8 @@

#if F_CPU >= 20000000 && !defined(USB_DISABLED)

#include "core_pins.h" // for millis()

// C language implementation
#ifdef __cplusplus
extern "C" {
@@ -52,6 +54,7 @@ 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);
void usb_serial_flush_callback(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;
@@ -106,9 +109,8 @@ public:
uint8_t numbits(void) { return usb_cdc_line_coding[1] >> 16; }
uint8_t dtr(void) { return (usb_cdc_line_rtsdtr & USB_SERIAL_DTR) ? 1 : 0; }
uint8_t rts(void) { return (usb_cdc_line_rtsdtr & USB_SERIAL_RTS) ? 1 : 0; }
operator bool() { return usb_configuration &&
(usb_cdc_line_rtsdtr & (USB_SERIAL_DTR | USB_SERIAL_RTS)) &&
((uint32_t)(systick_millis_count - usb_cdc_line_rtsdtr_millis) >= 25);
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;

+ 306
- 0
teensy3/usb_serial2.c 查看文件

@@ -0,0 +1,306 @@
/* 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_serial2.h"
#include "core_pins.h" // for yield()
//#include "HardwareSerial.h"
#include <string.h> // for memcpy()

// defined by usb_dev.h -> usb_desc.h
#if defined(CDC2_STATUS_INTERFACE) && defined(CDC2_DATA_INTERFACE)
#if F_CPU >= 20000000

uint32_t usb_cdc2_line_coding[2];
volatile uint32_t usb_cdc2_line_rtsdtr_millis;
volatile uint8_t usb_cdc2_line_rtsdtr=0;
volatile uint8_t usb_cdc2_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_serial2_getchar(void)
{
unsigned int i;
int c;

if (!rx_packet) {
if (!usb_configuration) return -1;
rx_packet = usb_rx(CDC2_RX_ENDPOINT);
if (!rx_packet) return -1;
}
i = rx_packet->index;
c = rx_packet->buf[i++];
if (i >= rx_packet->len) {
usb_free(rx_packet);
rx_packet = NULL;
} else {
rx_packet->index = i;
}
return c;
}

// peek at the next character, or -1 if nothing received
int usb_serial2_peekchar(void)
{
if (!rx_packet) {
if (!usb_configuration) return -1;
rx_packet = usb_rx(CDC2_RX_ENDPOINT);
if (!rx_packet) return -1;
}
if (!rx_packet) return -1;
return rx_packet->buf[rx_packet->index];
}

// number of bytes available in the receive buffer
int usb_serial2_available(void)
{
int count;
count = usb_rx_byte_count(CDC2_RX_ENDPOINT);
if (rx_packet) count += rx_packet->len - rx_packet->index;
return count;
}

// read a block of bytes to a buffer
int usb_serial2_read(void *buffer, uint32_t size)
{
uint8_t *p = (uint8_t *)buffer;
uint32_t qty, count=0;

while (size) {
if (!usb_configuration) break;
if (!rx_packet) {
rx:
rx_packet = usb_rx(CDC2_RX_ENDPOINT);
if (!rx_packet) break;
if (rx_packet->len == 0) {
usb_free(rx_packet);
goto rx;
}
}
qty = rx_packet->len - rx_packet->index;
if (qty > size) qty = size;
memcpy(p, rx_packet->buf + rx_packet->index, qty);
p += qty;
count += qty;
size -= qty;
rx_packet->index += qty;
if (rx_packet->index >= rx_packet->len) {
usb_free(rx_packet);
rx_packet = NULL;
}
}
return count;
}

// discard any buffered input
void usb_serial2_flush_input(void)
{
usb_packet_t *rx;

if (!usb_configuration) return;
if (rx_packet) {
usb_free(rx_packet);
rx_packet = NULL;
}
while (1) {
rx = usb_rx(CDC2_RX_ENDPOINT);
if (!rx) break;
usb_free(rx);
}
}

// Maximum number of transmit packets to queue so we don't starve other endpoints for memory
#define TX_PACKET_LIMIT 8

// When the PC isn't listening, how long do we wait before discarding data? If this is
// too short, we risk losing data during the stalls that are common with ordinary desktop
// software. If it's too long, we stall the user's program when no software is running.
#define TX_TIMEOUT_MSEC 70
#if F_CPU == 256000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1706)
#elif 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_serial2_putchar(uint8_t c)
{
return usb_serial2_write(&c, 1);
}


int usb_serial2_write(const void *buffer, uint32_t size)
{
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(CDC2_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 = CDC2_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 >= CDC2_TX_SIZE) {
tx_packet->len = CDC2_TX_SIZE;
usb_tx(CDC2_TX_ENDPOINT, tx_packet);
tx_packet = NULL;
}
usb_cdc2_transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
}
tx_noautoflush = 0;
return ret;
}

int usb_serial2_write_buffer_free(void)
{
uint32_t len;

tx_noautoflush = 1;
if (!tx_packet) {
if (!usb_configuration ||
usb_tx_packet_count(CDC2_TX_ENDPOINT) >= TX_PACKET_LIMIT ||
(tx_packet = usb_malloc()) == NULL) {
tx_noautoflush = 0;
return 0;
}
}
len = CDC2_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;
}

void usb_serial2_flush_output(void)
{
if (!usb_configuration) return;
tx_noautoflush = 1;
if (tx_packet) {
usb_cdc2_transmit_flush_timer = 0;
tx_packet->len = tx_packet->index;
usb_tx(CDC2_TX_ENDPOINT, tx_packet);
tx_packet = NULL;
} else {
usb_packet_t *tx = usb_malloc();
if (tx) {
usb_cdc2_transmit_flush_timer = 0;
usb_tx(CDC2_TX_ENDPOINT, tx);
} else {
usb_cdc2_transmit_flush_timer = 1;
}
}
tx_noautoflush = 0;
}

void usb_serial2_flush_callback(void)
{
if (tx_noautoflush) return;
if (tx_packet) {
tx_packet->len = tx_packet->index;
usb_tx(CDC2_TX_ENDPOINT, tx_packet);
tx_packet = NULL;
} else {
usb_packet_t *tx = usb_malloc();
if (tx) {
usb_tx(CDC2_TX_ENDPOINT, tx);
} else {
usb_cdc2_transmit_flush_timer = 1;
}
}
}




#endif // F_CPU
#endif // CDC2_STATUS_INTERFACE && CDC2_DATA_INTERFACE

+ 139
- 0
teensy3/usb_serial2.h 查看文件

@@ -0,0 +1,139 @@
/* 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 USBserial2_h_
#define USBserial2_h_

#include "usb_desc.h"

#if defined(CDC2_STATUS_INTERFACE) && defined(CDC2_DATA_INTERFACE)

#include <inttypes.h>

#if F_CPU >= 20000000

#include "core_pins.h" // for millis()

// C language implementation
#ifdef __cplusplus
extern "C" {
#endif
int usb_serial2_getchar(void);
int usb_serial2_peekchar(void);
int usb_serial2_available(void);
int usb_serial2_read(void *buffer, uint32_t size);
void usb_serial2_flush_input(void);
int usb_serial2_putchar(uint8_t c);
int usb_serial2_write(const void *buffer, uint32_t size);
int usb_serial2_write_buffer_free(void);
void usb_serial2_flush_output(void);
void usb_serial2_flush_callback(void);
extern uint32_t usb_cdc2_line_coding[2];
extern volatile uint32_t usb_cdc2_line_rtsdtr_millis;
extern volatile uint32_t systick_millis_count;
extern volatile uint8_t usb_cdc2_line_rtsdtr;
extern volatile uint8_t usb_cdc2_transmit_flush_timer;
extern volatile uint8_t usb_configuration;
#ifdef __cplusplus
}
#endif

#ifndef USB_SERIAL_DTR
#define USB_SERIAL_DTR 0x01
#endif
#ifndef USB_SERIAL_RTS
#define USB_SERIAL_RTS 0x02
#endif

// C++ interface
#ifdef __cplusplus
#include "Stream.h"
class usb_serial2_class : public Stream
{
public:
constexpr usb_serial2_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_serial2_available(); }
virtual int read() { return usb_serial2_getchar(); }
virtual int peek() { return usb_serial2_peekchar(); }
virtual void flush() { usb_serial2_flush_output(); } // TODO: actually wait for data to leave USB...
virtual void clear(void) { usb_serial2_flush_input(); }
virtual size_t write(uint8_t c) { return usb_serial2_putchar(c); }
virtual size_t write(const uint8_t *buffer, size_t size) { return usb_serial2_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_serial2_write_buffer_free(); }
using Print::write;
void send_now(void) { usb_serial2_flush_output(); }
uint32_t baud(void) { return usb_cdc2_line_coding[0]; }
uint8_t stopbits(void) { uint8_t b = usb_cdc2_line_coding[1]; if (!b) b = 1; return b; }
uint8_t paritytype(void) { return usb_cdc2_line_coding[1] >> 8; } // 0=none, 1=odd, 2=even
uint8_t numbits(void) { return usb_cdc2_line_coding[1] >> 16; }
uint8_t dtr(void) { return (usb_cdc2_line_rtsdtr & USB_SERIAL_DTR) ? 1 : 0; }
uint8_t rts(void) { return (usb_cdc2_line_rtsdtr & USB_SERIAL_RTS) ? 1 : 0; }
operator bool() { return usb_configuration && (usb_cdc2_line_rtsdtr & USB_SERIAL_DTR) &&
((uint32_t)(systick_millis_count - usb_cdc2_line_rtsdtr_millis) >= 15);
}
size_t readBytes(char *buffer, size_t length) {
size_t count=0;
unsigned long startMillis = millis();
do {
count += usb_serial2_read(buffer + count, length - count);
if (count >= length) return count;
} while(millis() - startMillis < _timeout);
setReadError();
return count;
}

};
extern usb_serial2_class SerialUSB1;
extern void serialEventUSB1(void);
#endif // __cplusplus

#endif // F_CPU

#endif // CDC2_STATUS_INTERFACE && CDC2_DATA_INTERFACE

#endif // USBserial2_h_

+ 306
- 0
teensy3/usb_serial3.c 查看文件

@@ -0,0 +1,306 @@
/* 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_serial3.h"
#include "core_pins.h" // for yield()
//#include "HardwareSerial.h"
#include <string.h> // for memcpy()

// defined by usb_dev.h -> usb_desc.h
#if defined(CDC3_STATUS_INTERFACE) && defined(CDC3_DATA_INTERFACE)
#if F_CPU >= 20000000

uint32_t usb_cdc3_line_coding[2];
volatile uint32_t usb_cdc3_line_rtsdtr_millis;
volatile uint8_t usb_cdc3_line_rtsdtr=0;
volatile uint8_t usb_cdc3_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_serial3_getchar(void)
{
unsigned int i;
int c;

if (!rx_packet) {
if (!usb_configuration) return -1;
rx_packet = usb_rx(CDC3_RX_ENDPOINT);
if (!rx_packet) return -1;
}
i = rx_packet->index;
c = rx_packet->buf[i++];
if (i >= rx_packet->len) {
usb_free(rx_packet);
rx_packet = NULL;
} else {
rx_packet->index = i;
}
return c;
}

// peek at the next character, or -1 if nothing received
int usb_serial3_peekchar(void)
{
if (!rx_packet) {
if (!usb_configuration) return -1;
rx_packet = usb_rx(CDC3_RX_ENDPOINT);
if (!rx_packet) return -1;
}
if (!rx_packet) return -1;
return rx_packet->buf[rx_packet->index];
}

// number of bytes available in the receive buffer
int usb_serial3_available(void)
{
int count;
count = usb_rx_byte_count(CDC3_RX_ENDPOINT);
if (rx_packet) count += rx_packet->len - rx_packet->index;
return count;
}

// read a block of bytes to a buffer
int usb_serial3_read(void *buffer, uint32_t size)
{
uint8_t *p = (uint8_t *)buffer;
uint32_t qty, count=0;

while (size) {
if (!usb_configuration) break;
if (!rx_packet) {
rx:
rx_packet = usb_rx(CDC3_RX_ENDPOINT);
if (!rx_packet) break;
if (rx_packet->len == 0) {
usb_free(rx_packet);
goto rx;
}
}
qty = rx_packet->len - rx_packet->index;
if (qty > size) qty = size;
memcpy(p, rx_packet->buf + rx_packet->index, qty);
p += qty;
count += qty;
size -= qty;
rx_packet->index += qty;
if (rx_packet->index >= rx_packet->len) {
usb_free(rx_packet);
rx_packet = NULL;
}
}
return count;
}

// discard any buffered input
void usb_serial3_flush_input(void)
{
usb_packet_t *rx;

if (!usb_configuration) return;
if (rx_packet) {
usb_free(rx_packet);
rx_packet = NULL;
}
while (1) {
rx = usb_rx(CDC3_RX_ENDPOINT);
if (!rx) break;
usb_free(rx);
}
}

// Maximum number of transmit packets to queue so we don't starve other endpoints for memory
#define TX_PACKET_LIMIT 8

// When the PC isn't listening, how long do we wait before discarding data? If this is
// too short, we risk losing data during the stalls that are common with ordinary desktop
// software. If it's too long, we stall the user's program when no software is running.
#define TX_TIMEOUT_MSEC 70
#if F_CPU == 256000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1706)
#elif 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_serial3_putchar(uint8_t c)
{
return usb_serial3_write(&c, 1);
}


int usb_serial3_write(const void *buffer, uint32_t size)
{
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(CDC3_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 = CDC3_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 >= CDC3_TX_SIZE) {
tx_packet->len = CDC3_TX_SIZE;
usb_tx(CDC3_TX_ENDPOINT, tx_packet);
tx_packet = NULL;
}
usb_cdc3_transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
}
tx_noautoflush = 0;
return ret;
}

int usb_serial3_write_buffer_free(void)
{
uint32_t len;

tx_noautoflush = 1;
if (!tx_packet) {
if (!usb_configuration ||
usb_tx_packet_count(CDC3_TX_ENDPOINT) >= TX_PACKET_LIMIT ||
(tx_packet = usb_malloc()) == NULL) {
tx_noautoflush = 0;
return 0;
}
}
len = CDC3_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;
}

void usb_serial3_flush_output(void)
{
if (!usb_configuration) return;
tx_noautoflush = 1;
if (tx_packet) {
usb_cdc3_transmit_flush_timer = 0;
tx_packet->len = tx_packet->index;
usb_tx(CDC3_TX_ENDPOINT, tx_packet);
tx_packet = NULL;
} else {
usb_packet_t *tx = usb_malloc();
if (tx) {
usb_cdc3_transmit_flush_timer = 0;
usb_tx(CDC3_TX_ENDPOINT, tx);
} else {
usb_cdc3_transmit_flush_timer = 1;
}
}
tx_noautoflush = 0;
}

void usb_serial3_flush_callback(void)
{
if (tx_noautoflush) return;
if (tx_packet) {
tx_packet->len = tx_packet->index;
usb_tx(CDC3_TX_ENDPOINT, tx_packet);
tx_packet = NULL;
} else {
usb_packet_t *tx = usb_malloc();
if (tx) {
usb_tx(CDC3_TX_ENDPOINT, tx);
} else {
usb_cdc3_transmit_flush_timer = 1;
}
}
}




#endif // F_CPU
#endif // CDC3_STATUS_INTERFACE && CDC3_DATA_INTERFACE

+ 139
- 0
teensy3/usb_serial3.h 查看文件

@@ -0,0 +1,139 @@
/* 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 USBserial3_h_
#define USBserial3_h_

#include "usb_desc.h"

#if defined(CDC3_STATUS_INTERFACE) && defined(CDC3_DATA_INTERFACE)

#include <inttypes.h>

#if F_CPU >= 20000000

#include "core_pins.h" // for millis()

// C language implementation
#ifdef __cplusplus
extern "C" {
#endif
int usb_serial3_getchar(void);
int usb_serial3_peekchar(void);
int usb_serial3_available(void);
int usb_serial3_read(void *buffer, uint32_t size);
void usb_serial3_flush_input(void);
int usb_serial3_putchar(uint8_t c);
int usb_serial3_write(const void *buffer, uint32_t size);
int usb_serial3_write_buffer_free(void);
void usb_serial3_flush_output(void);
void usb_serial3_flush_callback(void);
extern uint32_t usb_cdc3_line_coding[2];
extern volatile uint32_t usb_cdc3_line_rtsdtr_millis;
extern volatile uint32_t systick_millis_count;
extern volatile uint8_t usb_cdc3_line_rtsdtr;
extern volatile uint8_t usb_cdc3_transmit_flush_timer;
extern volatile uint8_t usb_configuration;
#ifdef __cplusplus
}
#endif

#ifndef USB_SERIAL_DTR
#define USB_SERIAL_DTR 0x01
#endif
#ifndef USB_SERIAL_RTS
#define USB_SERIAL_RTS 0x02
#endif

// C++ interface
#ifdef __cplusplus
#include "Stream.h"
class usb_serial3_class : public Stream
{
public:
constexpr usb_serial3_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_serial3_available(); }
virtual int read() { return usb_serial3_getchar(); }
virtual int peek() { return usb_serial3_peekchar(); }
virtual void flush() { usb_serial3_flush_output(); } // TODO: actually wait for data to leave USB...
virtual void clear(void) { usb_serial3_flush_input(); }
virtual size_t write(uint8_t c) { return usb_serial3_putchar(c); }
virtual size_t write(const uint8_t *buffer, size_t size) { return usb_serial3_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_serial3_write_buffer_free(); }
using Print::write;
void send_now(void) { usb_serial3_flush_output(); }
uint32_t baud(void) { return usb_cdc3_line_coding[0]; }
uint8_t stopbits(void) { uint8_t b = usb_cdc3_line_coding[1]; if (!b) b = 1; return b; }
uint8_t paritytype(void) { return usb_cdc3_line_coding[1] >> 8; } // 0=none, 1=odd, 2=even
uint8_t numbits(void) { return usb_cdc3_line_coding[1] >> 16; }
uint8_t dtr(void) { return (usb_cdc3_line_rtsdtr & USB_SERIAL_DTR) ? 1 : 0; }
uint8_t rts(void) { return (usb_cdc3_line_rtsdtr & USB_SERIAL_RTS) ? 1 : 0; }
operator bool() { return usb_configuration && (usb_cdc3_line_rtsdtr & USB_SERIAL_DTR) &&
((uint32_t)(systick_millis_count - usb_cdc3_line_rtsdtr_millis) >= 15);
}
size_t readBytes(char *buffer, size_t length) {
size_t count=0;
unsigned long startMillis = millis();
do {
count += usb_serial3_read(buffer + count, length - count);
if (count >= length) return count;
} while(millis() - startMillis < _timeout);
setReadError();
return count;
}

};
extern usb_serial3_class SerialUSB2;
extern void serialEventUSB2(void);
#endif // __cplusplus

#endif // F_CPU

#endif // CDC3_STATUS_INTERFACE && CDC3_DATA_INTERFACE

#endif // USBserial3_h_

+ 14
- 2
teensy3/usb_touch.c 查看文件

@@ -86,12 +86,14 @@ void usb_touchscreen_release(uint8_t finger)
// 5: Y msb
// 6: scan time lsb
// 7: scan time msb
// 8: contact count

// Called by the start-of-frame interrupt.
//
void usb_touchscreen_update_callback(void)
{
uint8_t contact_count = 0;

if (scan_index == 0) {
if (usb_tx_packet_count(MULTITOUCH_ENDPOINT) > 1) {
// wait to begin another scan if if more than
@@ -100,7 +102,16 @@ void usb_touchscreen_update_callback(void)
}
scan_timestamp = millis() * 10;
scan_count = 0;

// Get the contact count (usage 0x54)
// Only set this value on first contact
// Subsequent concurrent contacts should report 0
for (uint8_t i = 0; i < MULTITOUCH_FINGERS; i++)
{
if (contactid[i]) contact_count++;
}
}

while (scan_index < MULTITOUCH_FINGERS) {
uint32_t press = pressure[scan_index];
uint32_t id = contactid[scan_index];
@@ -123,7 +134,8 @@ void usb_touchscreen_update_callback(void)
*(tx_packet->buf + 5) = ypos[scan_index] >> 8;
*(tx_packet->buf + 6) = scan_timestamp;
*(tx_packet->buf + 7) = scan_timestamp >> 8;
tx_packet->len = 8;
*(tx_packet->buf + 8) = contact_count;
tx_packet->len = 9;
usb_tx(MULTITOUCH_ENDPOINT, tx_packet);
scan_index++;
return;

+ 50
- 2
teensy3/usb_undef.h 查看文件

@@ -41,8 +41,8 @@
#ifdef ENDPOINT_UNUSED
#undef ENDPOINT_UNUSED
#endif
#ifdef ENDPOINT_TRANSIMIT_ONLY
#undef ENDPOINT_TRANSIMIT_ONLY
#ifdef ENDPOINT_TRANSMIT_ONLY
#undef ENDPOINT_TRANSMIT_ONLY
#endif
#ifdef ENDPOINT_RECEIVE_ONLY
#undef ENDPOINT_RECEIVE_ONLY
@@ -110,6 +110,54 @@
#ifdef CDC_TX_SIZE
#undef CDC_TX_SIZE
#endif
#ifdef CDC2_STATUS_INTERFACE
#undef CDC2_STATUS_INTERFACE
#endif
#ifdef CDC2_DATA_INTERFACE
#undef CDC2_DATA_INTERFACE
#endif
#ifdef CDC2_ACM_ENDPOINT
#undef CDC2_ACM_ENDPOINT
#endif
#ifdef CDC2_RX_ENDPOINT
#undef CDC2_RX_ENDPOINT
#endif
#ifdef CDC2_TX_ENDPOINT
#undef CDC2_TX_ENDPOINT
#endif
#ifdef CDC2_ACM_SIZE
#undef CDC2_ACM_SIZE
#endif
#ifdef CDC2_RX_SIZE
#undef CDC2_RX_SIZE
#endif
#ifdef CDC2_TX_SIZE
#undef CDC2_TX_SIZE
#endif
#ifdef CDC3_STATUS_INTERFACE
#undef CDC3_STATUS_INTERFACE
#endif
#ifdef CDC3_DATA_INTERFACE
#undef CDC3_DATA_INTERFACE
#endif
#ifdef CDC3_ACM_ENDPOINT
#undef CDC3_ACM_ENDPOINT
#endif
#ifdef CDC3_RX_ENDPOINT
#undef CDC3_RX_ENDPOINT
#endif
#ifdef CDC3_TX_ENDPOINT
#undef CDC3_TX_ENDPOINT
#endif
#ifdef CDC3_ACM_SIZE
#undef CDC3_ACM_SIZE
#endif
#ifdef CDC3_RX_SIZE
#undef CDC3_RX_SIZE
#endif
#ifdef CDC3_TX_SIZE
#undef CDC3_TX_SIZE
#endif
#ifdef SEREMU_INTERFACE
#undef SEREMU_INTERFACE
#endif

+ 25
- 6
teensy3/wiring.h 查看文件

@@ -33,6 +33,7 @@

#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include "binary.h"
#include "core_id.h"
#include "core_pins.h"
@@ -48,15 +49,35 @@ long map(T _x, A _in_min, B _in_max, C _out_min, D _out_max, typename std::enabl
{
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;
#if 0
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
#endif
#if 0
// 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;
}
#endif
long in_range = in_max - in_min;
long out_range = out_max - out_min;
if (in_range == 0) return out_min + out_range / 2;
long num = (x - in_min) * out_range;
if (out_range >= 0) {
num += in_range / 2;
} else {
num -= in_range / 2;
}
long result = num / in_range + out_min;
if (out_range >= 0) {
if (in_range * num < 0) return result - 1;
} else {
if (in_range * num >= 0) return result + 1;
}
return result;
// more conversation:
// https://forum.pjrc.com/threads/44503-map()-function-improvements
}
// 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>
@@ -64,7 +85,7 @@ T map(T x, A in_min, B in_max, C out_min, D out_max, typename std::enable_if<std
{
return (x - (T)in_min) * ((T)out_max - (T)out_min) / ((T)in_max - (T)in_min) + (T)out_min;
}
#include <algorithm> // c++ min, max
//#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>
@@ -190,8 +211,6 @@ void loop(void);
typedef bool boolean;
#else
typedef uint8_t boolean;
#define false 0
#define true (!false)
#endif

#endif

+ 41
- 17
teensy3/yield.cpp 查看文件

@@ -28,32 +28,56 @@
* SOFTWARE.
*/

#include "core_pins.h"
#include "HardwareSerial.h"
#include "usb_serial.h"
#include "usb_seremu.h"
#include <Arduino.h>
#include "EventResponder.h"

#ifdef USB_TRIPLE_SERIAL
uint8_t yield_active_check_flags = YIELD_CHECK_USB_SERIAL | YIELD_CHECK_USB_SERIALUSB1 | YIELD_CHECK_USB_SERIALUSB2; // default to check USB.
extern const uint8_t _serialEventUSB2_default;
extern const uint8_t _serialEventUSB1_default;

#elif defined(USB_DUAL_SERIAL)
uint8_t yield_active_check_flags = YIELD_CHECK_USB_SERIAL | YIELD_CHECK_USB_SERIALUSB1; // default to check USB.
extern const uint8_t _serialEventUSB1_default;

#else
uint8_t yield_active_check_flags = YIELD_CHECK_USB_SERIAL; // default to check USB.
#endif

extern const uint8_t _serialEvent_default;

void yield(void) __attribute__ ((weak));
void yield(void)
{
static uint8_t running=0;

if (!yield_active_check_flags) return; // nothing to do
if (running) return; // TODO: does this need to be atomic?
running = 1;
if (Serial.available()) serialEvent();
if (Serial1.available()) serialEvent1();
if (Serial2.available()) serialEvent2();
if (Serial3.available()) serialEvent3();
#ifdef HAS_KINETISK_UART3
if (Serial4.available()) serialEvent4();
#endif
#ifdef HAS_KINETISK_UART4
if (Serial5.available()) serialEvent5();


// USB Serail - Add hack to minimize impact...
if (yield_active_check_flags & YIELD_CHECK_USB_SERIAL) {
if (Serial.available()) serialEvent();
if (_serialEvent_default) yield_active_check_flags &= ~YIELD_CHECK_USB_SERIAL;
}
// Current workaround until integrate with EventResponder.

#if defined(USB_DUAL_SERIAL) || defined(USB_TRIPLE_SERIAL)
if (yield_active_check_flags & YIELD_CHECK_USB_SERIALUSB1) {
if (SerialUSB1.available()) serialEventUSB1();
if (_serialEventUSB1_default) yield_active_check_flags &= ~YIELD_CHECK_USB_SERIALUSB1;
}
#endif
#if defined(HAS_KINETISK_UART5) || defined (HAS_KINETISK_LPUART0)
if (Serial6.available()) serialEvent6();
#ifdef USB_TRIPLE_SERIAL
if (yield_active_check_flags & YIELD_CHECK_USB_SERIALUSB2) {
if (SerialUSB2.available()) serialEventUSB2();
if (_serialEventUSB2_default) yield_active_check_flags &= ~YIELD_CHECK_USB_SERIALUSB2;
}
#endif
if (yield_active_check_flags & YIELD_CHECK_HARDWARE_SERIAL) {
HardwareSerial::processSerialEventsList();
}
running = 0;
EventResponder::runFromYield();
if (yield_active_check_flags & YIELD_CHECK_EVENT_RESPONDER) EventResponder::runFromYield();
};

+ 9
- 0
teensy4/Arduino.h 查看文件

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

#ifndef Arduino_h
#define Arduino_h

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

#endif

+ 337
- 0
teensy4/AudioStream.cpp 查看文件

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


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

#if defined(__IMXRT1062__)
#define MAX_AUDIO_MEMORY 229376
#endif

#define NUM_MASKS (((MAX_AUDIO_MEMORY / AUDIO_BLOCK_SAMPLES / 2) + 31) / 32)

audio_block_t * AudioStream::memory_pool;
uint32_t AudioStream::memory_pool_available_mask[NUM_MASKS];
uint16_t AudioStream::memory_pool_first_mask;

uint16_t AudioStream::cpu_cycles_total = 0;
uint16_t AudioStream::cpu_cycles_total_max = 0;
uint16_t AudioStream::memory_used = 0;
uint16_t AudioStream::memory_used_max = 0;

void software_isr(void);


// Set up the pool of audio data blocks
// placing them all onto the free list
FLASHMEM void AudioStream::initialize_memory(audio_block_t *data, unsigned int num)
{
unsigned int i;
unsigned int maxnum = MAX_AUDIO_MEMORY / AUDIO_BLOCK_SAMPLES / 2;

//Serial.println("AudioStream initialize_memory");
//delay(10);
if (num > maxnum) num = maxnum;
__disable_irq();
memory_pool = data;
memory_pool_first_mask = 0;
for (i=0; i < NUM_MASKS; i++) {
memory_pool_available_mask[i] = 0;
}
for (i=0; i < num; i++) {
memory_pool_available_mask[i >> 5] |= (1 << (i & 0x1F));
}
for (i=0; i < num; i++) {
data[i].memory_pool_index = i;
}
__enable_irq();

}

// Allocate 1 audio data block. If successful
// the caller is the only owner of this new block
audio_block_t * AudioStream::allocate(void)
{
uint32_t n, index, avail;
uint32_t *p, *end;
audio_block_t *block;
uint32_t used;

p = memory_pool_available_mask;
end = p + NUM_MASKS;
__disable_irq();
index = memory_pool_first_mask;
p += index;
while (1) {
if (p >= end) {
__enable_irq();
//Serial.println("alloc:null");
return NULL;
}
avail = *p;
if (avail) break;
index++;
p++;
}
n = __builtin_clz(avail);
avail &= ~(0x80000000 >> n);
*p = avail;
if (!avail) index++;
memory_pool_first_mask = index;
used = memory_used + 1;
memory_used = used;
__enable_irq();
index = p - memory_pool_available_mask;
block = memory_pool + ((index << 5) + (31 - n));
block->ref_count = 1;
if (used > memory_used_max) memory_used_max = used;
//Serial.print("alloc:");
//Serial.println((uint32_t)block, HEX);
return block;
}

// Release ownership of a data block. If no
// other streams have ownership, the block is
// returned to the free pool
void AudioStream::release(audio_block_t *block)
{
//if (block == NULL) return;
uint32_t mask = (0x80000000 >> (31 - (block->memory_pool_index & 0x1F)));
uint32_t index = block->memory_pool_index >> 5;

__disable_irq();
if (block->ref_count > 1) {
block->ref_count--;
} else {
//Serial.print("reles:");
//Serial.println((uint32_t)block, HEX);
memory_pool_available_mask[index] |= mask;
if (index < memory_pool_first_mask) memory_pool_first_mask = index;
memory_used--;
}
__enable_irq();
}

// Transmit an audio data block
// to all streams that connect to an output. The block
// becomes owned by all the recepients, but also is still
// owned by this object. Normally, a block must be released
// by the caller after it's transmitted. This allows the
// caller to transmit to same block to more than 1 output,
// and then release it once after all transmit calls.
void AudioStream::transmit(audio_block_t *block, unsigned char index)
{
for (AudioConnection *c = destination_list; c != NULL; c = c->next_dest) {
if (c->src_index == index) {
if (c->dst.inputQueue[c->dest_index] == NULL) {
c->dst.inputQueue[c->dest_index] = block;
block->ref_count++;
}
}
}
}


// Receive block from an input. The block's data
// may be shared with other streams, so it must not be written
audio_block_t * AudioStream::receiveReadOnly(unsigned int index)
{
audio_block_t *in;

if (index >= num_inputs) return NULL;
in = inputQueue[index];
inputQueue[index] = NULL;
return in;
}

// Receive block from an input. The block will not
// be shared, so its contents may be changed.
audio_block_t * AudioStream::receiveWritable(unsigned int index)
{
audio_block_t *in, *p;

if (index >= num_inputs) return NULL;
in = inputQueue[index];
inputQueue[index] = NULL;
if (in && in->ref_count > 1) {
p = allocate();
if (p) memcpy(p->data, in->data, sizeof(p->data));
in->ref_count--;
in = p;
}
return in;
}


void AudioConnection::connect(void)
{
AudioConnection *p;

if (isConnected) return;
if (dest_index > dst.num_inputs) return;
__disable_irq();
p = src.destination_list;
if (p == NULL) {
src.destination_list = this;
} else {
while (p->next_dest) {
if (&p->src == &this->src && &p->dst == &this->dst
&& p->src_index == this->src_index && p->dest_index == this->dest_index) {
//Source and destination already connected through another connection, abort
__enable_irq();
return;
}
p = p->next_dest;
}
p->next_dest = this;
}
this->next_dest = NULL;
src.numConnections++;
src.active = true;

dst.numConnections++;
dst.active = true;

isConnected = true;

__enable_irq();
}

void AudioConnection::disconnect(void)
{
AudioConnection *p;

if (!isConnected) return;
if (dest_index > dst.num_inputs) return;
__disable_irq();
// Remove destination from source list
p = src.destination_list;
if (p == NULL) {
//>>> PAH re-enable the IRQ
__enable_irq();
return;
} else if (p == this) {
if (p->next_dest) {
src.destination_list = next_dest;
} else {
src.destination_list = NULL;
}
} else {
while (p) {
if (p == this) {
if (p->next_dest) {
p = next_dest;
break;
} else {
p = NULL;
break;
}
}
p = p->next_dest;
}
}
//>>> PAH release the audio buffer properly
//Remove possible pending src block from destination
if(dst.inputQueue[dest_index] != NULL) {
AudioStream::release(dst.inputQueue[dest_index]);
// release() re-enables the IRQ. Need it to be disabled a little longer
__disable_irq();
dst.inputQueue[dest_index] = NULL;
}

//Check if the disconnected AudioStream objects should still be active
src.numConnections--;
if (src.numConnections == 0) {
src.active = false;
}

dst.numConnections--;
if (dst.numConnections == 0) {
dst.active = false;
}

isConnected = false;

__enable_irq();
}


// When an object has taken responsibility for calling update_all()
// at each block interval (approx 2.9ms), this variable is set to
// true. Objects that are capable of calling update_all(), typically
// input and output based on interrupts, must check this variable in
// their constructors.
bool AudioStream::update_scheduled = false;

bool AudioStream::update_setup(void)
{
if (update_scheduled) return false;
attachInterruptVector(IRQ_SOFTWARE, software_isr);
NVIC_SET_PRIORITY(IRQ_SOFTWARE, 208); // 255 = lowest priority
NVIC_ENABLE_IRQ(IRQ_SOFTWARE);
update_scheduled = true;
return true;
}

void AudioStream::update_stop(void)
{
NVIC_DISABLE_IRQ(IRQ_SOFTWARE);
update_scheduled = false;
}

AudioStream * AudioStream::first_update = NULL;

void software_isr(void) // AudioStream::update_all()
{
AudioStream *p;

uint32_t totalcycles = ARM_DWT_CYCCNT;
//digitalWriteFast(2, HIGH);
for (p = AudioStream::first_update; p; p = p->next_update) {
if (p->active) {
uint32_t cycles = ARM_DWT_CYCCNT;
p->update();
// TODO: traverse inputQueueArray and release
// any input blocks that weren't consumed?
cycles = (ARM_DWT_CYCCNT - cycles) >> 6;
p->cpu_cycles = cycles;
if (cycles > p->cpu_cycles_max) p->cpu_cycles_max = cycles;
}
}
//digitalWriteFast(2, LOW);
totalcycles = (ARM_DWT_CYCCNT - totalcycles) >> 6;
AudioStream::cpu_cycles_total = totalcycles;
if (totalcycles > AudioStream::cpu_cycles_total_max)
AudioStream::cpu_cycles_total_max = totalcycles;

asm("DSB");
}


+ 0
- 0
teensy4/AudioStream.h 查看文件


部分文件因为文件数量过多而无法显示

正在加载...
取消
保存