Browse Source

Merge remote-tracking branch 'upstream/master'

main
Tino Hernandez 4 years ago
parent
commit
7cb39b2f4d
100 changed files with 3885 additions and 343 deletions
  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 View File

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: The latest stable version of Teensy's core library is always available in the Teensyduino installer, at this page:



+ 24
- 2
keywords.txt View File

noexcept LITERAL1 noexcept LITERAL1
static_assert LITERAL1 static_assert LITERAL1
thread_local LITERAL1 thread_local LITERAL1
size_t LITERAL1


# teensy specific functions # teensy specific functions
elapsedMillis LITERAL1 elapsedMillis LITERAL1
printf KEYWORD2 printf KEYWORD2
digitalWriteFast KEYWORD2 digitalWriteFast KEYWORD2
digitalReadFast KEYWORD2 digitalReadFast KEYWORD2
digitalToggleFast KEYWORD2
digitalToggle KEYWORD2
transmitterEnable KEYWORD2 transmitterEnable KEYWORD2
attachRts KEYWORD2 attachRts KEYWORD2
attachCts KEYWORD2 attachCts KEYWORD2
PROGMEM LITERAL1 PROGMEM LITERAL1
FLASHMEM LITERAL1
DMAMEM LITERAL1 DMAMEM LITERAL1
EXTMEM LITERAL1
FASTRUN LITERAL1 FASTRUN LITERAL1
Serial4 KEYWORD1 Serial4 KEYWORD1
Serial5 KEYWORD1 Serial5 KEYWORD1
Serial6 KEYWORD1 Serial6 KEYWORD1
Serial7 KEYWORD1
Serial8 KEYWORD1
SerialUSB1 KEYWORD1
SerialUSB2 KEYWORD1
setRX KEYWORD2 setRX KEYWORD2
setTX KEYWORD2 setTX KEYWORD2
write9bit KEYWORD2 write9bit KEYWORD2
addMemoryForRead KEYWORD2
addMemoryForWrite KEYWORD2
clear KEYWORD2 clear KEYWORD2
EventResponder LITERAL1 EventResponder LITERAL1
EventResponderRef LITERAL1 EventResponderRef LITERAL1
waitForEvent KEYWORD2 waitForEvent KEYWORD2
MillisTimer LITERAL1 MillisTimer LITERAL1
beginRepeating KEYWORD2 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 # Arduino constants
A0 LITERAL1 A0 LITERAL1
digitalPinHasPWM KEYWORD2 digitalPinHasPWM KEYWORD2
NOT_AN_INTERRUPT LITERAL1 NOT_AN_INTERRUPT LITERAL1
digitalPinToInterrupt KEYWORD2 digitalPinToInterrupt KEYWORD2
FILE_READ LITERAL1
FILE_WRITE LITERAL1
FILE_WRITE_BEGIN LITERAL1


# HardwareSerial modes # HardwareSerial modes
SERIAL_7E1 LITERAL1 SERIAL_7E1 LITERAL1
FlightSimInteger KEYWORD2 FlightSimInteger KEYWORD2
FlightSimFloat KEYWORD2 FlightSimFloat KEYWORD2
FlightSimElapsedFrames KEYWORD2 FlightSimElapsedFrames KEYWORD2
FlightSimData KEYWORD2
FlightSimEvent KEYWORD2
onChange KEYWORD2 onChange KEYWORD2
update KEYWORD2 update KEYWORD2
isEnabled KEYWORD2 isEnabled KEYWORD2

+ 183
- 0
teensy/FS.h View File

/* 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 View File

return write(p, sizeof(buf) - (p - buf)); 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) size_t Print::printFloat(double number, uint8_t digits)
{ {
uint8_t sign=0; uint8_t sign=0;

+ 12
- 3
teensy/Print.h View File



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


class __FlashStringHelper; class __FlashStringHelper;


size_t print(unsigned int n) { return printNumber(n, 0, 10); } size_t print(unsigned int n) { return printNumber(n, 0, 10); }
size_t print(long n); size_t print(long n);
size_t print(unsigned long n) { return printNumber(n, 0, 10); } 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(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(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(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(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(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(double n, int digits = 2) { return printFloat(n, digits); }
size_t print(const Printable &obj) { return obj.printTo(*this); } size_t print(const Printable &obj) { return obj.printTo(*this); }
size_t println(unsigned int n) { return print(n) + println(); } size_t println(unsigned int n) { return print(n) + println(); }
size_t println(long n) { return print(n) + println(); } size_t println(long n) { return print(n) + println(); }
size_t println(unsigned 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(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(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(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(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(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(double n, int digits = 2) { return print(n, digits) + println(); }
size_t println(const Printable &obj) { return obj.printTo(*this) + println(); } size_t println(const Printable &obj) { return obj.printTo(*this) + println(); }
if (base == 2) return printNumberBin(n); if (base == 2) return printNumberBin(n);
return printNumberAny(n, base); return printNumberAny(n, base);
} }
size_t printNumber64(uint64_t n, uint8_t base, uint8_t sign);
size_t printFloat(double n, uint8_t digits); size_t printFloat(double n, uint8_t digits);
}; };



+ 1
- 0
teensy/Udp.h View File



public: 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 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 virtual void stop() =0; // Finish with the UDP socket


// Sending UDP packets // Sending UDP packets

+ 335
- 0
teensy/core_pins.h View File

} }
} }


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 void _init_Teensyduino_internal_(void);
extern int analogRead(uint8_t); extern int analogRead(uint8_t);


} }




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 #ifdef __cplusplus

+ 2
- 2
teensy/keylayouts.h View File

#define ASCII_20 KEY_SPACE // 32 #define ASCII_20 KEY_SPACE // 32
#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! #define ASCII_21 KEY_1 + SHIFT_MASK // 33 !
#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " #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_24 KEY_4 + SHIFT_MASK // 36 $
#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % #define ASCII_25 KEY_5 + SHIFT_MASK // 37 %
#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & #define ASCII_26 KEY_7 + SHIFT_MASK // 38 &
#define ASCII_20 KEY_SPACE // 32 #define ASCII_20 KEY_SPACE // 32
#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! #define ASCII_21 KEY_1 + SHIFT_MASK // 33 !
#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " #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_24 KEY_4 + SHIFT_MASK // 36 $
#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % #define ASCII_25 KEY_5 + SHIFT_MASK // 37 %
#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & #define ASCII_26 KEY_7 + SHIFT_MASK // 38 &

+ 1
- 1
teensy/malloc.c View File

void * void *
malloc(size_t len) malloc(size_t len)
{ {
struct __freelist *fp1, *fp2, *sfp1, *sfp2;
struct __freelist *fp1, *fp2, *sfp1=NULL, *sfp2=NULL;
char *cp; char *cp;
size_t s, avail; size_t s, avail;



+ 6
- 0
teensy/pins_arduino.h View File

#define NUM_DIGITAL_PINS CORE_NUM_TOTAL_PINS #define NUM_DIGITAL_PINS CORE_NUM_TOTAL_PINS
#define NUM_ANALOG_INPUTS CORE_NUM_ANALOG #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 // This allows CapSense to work. Do any libraries
// depend on these to be zero? // depend on these to be zero?

+ 2
- 4
teensy/wiring.h View File



#include <avr/io.h> #include <avr/io.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <math.h> #include <math.h>
#include "binary.h" #include "binary.h"
#include "core_id.h" #include "core_id.h"
extern "C"{ extern "C"{
#endif #endif


#define true 1
#define false 0

#define PI 3.1415926535897932384626433832795 #define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398 #define HALF_PI 1.5707963267948966192313216916398
#define TWO_PI 6.283185307179586476925286766559 #define TWO_PI 6.283185307179586476925286766559


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


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


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

+ 5
- 0
teensy3/Arduino.h View File

// This header file is in the public domain. // This header file is in the public domain.


#ifndef Arduino_h
#define Arduino_h

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

#endif

+ 19
- 4
teensy3/AudioStream.cpp View File

*/ */




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


#if defined(__MKL26Z64__) #if defined(__MKL26Z64__)
#define MAX_AUDIO_MEMORY 6144 #define MAX_AUDIO_MEMORY 6144
// Remove destination from source list // Remove destination from source list
p = src.destination_list; p = src.destination_list;
if (p == NULL) { if (p == NULL) {
//>>> PAH re-enable the IRQ
__enable_irq();
return; return;
} else if (p == this) { } else if (p == this) {
if (p->next_dest) { if (p->next_dest) {
p = p->next_dest; p = p->next_dest;
} }
} }
//>>> PAH release the audio buffer properly
//Remove possible pending src block from destination //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 //Check if the disconnected AudioStream objects should still be active
src.numConnections--; src.numConnections--;
{ {
AudioStream *p; AudioStream *p;


#if defined(KINETISK)
ARM_DEMCR |= ARM_DEMCR_TRCENA; ARM_DEMCR |= ARM_DEMCR_TRCENA;
ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
uint32_t totalcycles = ARM_DWT_CYCCNT; uint32_t totalcycles = ARM_DWT_CYCCNT;
#elif defined(KINETISL)
uint32_t totalcycles = micros();
#endif
//digitalWriteFast(2, HIGH); //digitalWriteFast(2, HIGH);
for (p = AudioStream::first_update; p; p = p->next_update) { for (p = AudioStream::first_update; p; p = p->next_update) {
if (p->active) { if (p->active) {
} }
} }
//digitalWriteFast(2, LOW); //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; AudioStream::cpu_cycles_total = totalcycles;
if (totalcycles > AudioStream::cpu_cycles_total_max) if (totalcycles > AudioStream::cpu_cycles_total_max)
AudioStream::cpu_cycles_total_max = totalcycles; AudioStream::cpu_cycles_total_max = totalcycles;

+ 6
- 1
teensy3/AudioStream.h View File

#if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) #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 #define AUDIO_SAMPLE_RATE_EXACT 44117.64706 // 48 MHz / 1088, or 96 MHz * 2 / 17 / 256
#elif defined(__MKL26Z64__) #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
#endif #endif


AudioStream::initialize_memory(data, num); \ 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)) #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 AudioProcessorUsage() (CYCLE_COUNTER_APPROX_PERCENT(AudioStream::cpu_cycles_total))
#define AudioProcessorUsageMax() (CYCLE_COUNTER_APPROX_PERCENT(AudioStream::cpu_cycles_total_max)) #define AudioProcessorUsageMax() (CYCLE_COUNTER_APPROX_PERCENT(AudioStream::cpu_cycles_total_max))

+ 17
- 4
teensy3/DMAChannel.h View File

DMABaseClass() {} DMABaseClass() {}


static inline void copy_tcd(TCD_t *dst, const TCD_t *src) { static inline void copy_tcd(TCD_t *dst, const TCD_t *src) {
dst->CSR = 0;
const uint32_t *p = (const uint32_t *)src; const uint32_t *p = (const uint32_t *)src;
uint32_t *q = (uint32_t *)dst; uint32_t *q = (uint32_t *)dst;
uint32_t t1, t2, t3, t4; uint32_t t1, t2, t3, t4;
NVIC_ENABLE_IRQ(IRQ_DMA_CH0 + channel); 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) { void detachInterrupt(void) {
NVIC_DISABLE_IRQ(IRQ_DMA_CH0 + channel); NVIC_DISABLE_IRQ(IRQ_DMA_CH0 + channel);
} }
void transferSize(unsigned int len) { void transferSize(unsigned int len) {
uint32_t dcr = CFG->DCR & 0xF0C8FFFF; uint32_t dcr = CFG->DCR & 0xF0C8FFFF;
if (len == 4) { 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) { } 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 { } else {
CFG->DCR = dcr | DMA_DCR_DSIZE(1) | DMA_DCR_DSIZE(1);
CFG->DCR = dcr | DMA_DCR_SSIZE(1) | DMA_DCR_DSIZE(1);
} }
} }


_VectorsRam[channel + IRQ_DMA_CH0 + 16] = isr; _VectorsRam[channel + IRQ_DMA_CH0 + 16] = isr;
NVIC_ENABLE_IRQ(IRQ_DMA_CH0 + channel); 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) { void detachInterrupt(void) {
NVIC_DISABLE_IRQ(IRQ_DMA_CH0 + channel); NVIC_DISABLE_IRQ(IRQ_DMA_CH0 + channel);
} }

+ 12
- 0
teensy3/EventResponder.cpp View File

* https://forum.pjrc.com/threads/44723-Arduino-Events * https://forum.pjrc.com/threads/44723-Arduino-Events
*/ */


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


EventResponder * EventResponder::firstYield = nullptr; EventResponder * EventResponder::firstYield = nullptr;
bool EventResponder::runningFromYield = false; bool EventResponder::runningFromYield = false;


// TODO: interrupt disable/enable needed in many places!!! // 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() void EventResponder::triggerEventNotImmediate()
{ {
// with libraries using mid-to-high priority interrupts. // with libraries using mid-to-high priority interrupts.


extern "C" volatile uint32_t systick_millis_count; extern "C" volatile uint32_t systick_millis_count;

void systick_isr(void) void systick_isr(void)
{
systick_millis_count++;
}

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






+ 5
- 0
teensy3/EventResponder.h View File

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


class EventResponder; class EventResponder;
typedef EventResponder& EventResponderRef; typedef EventResponder& EventResponderRef;
detachNoInterrupts(); detachNoInterrupts();
_function = function; _function = function;
_type = EventTypeYield; _type = EventTypeYield;
yield_active_check_flags |= YIELD_CHECK_EVENT_RESPONDER; // user setup a yield type...
enableInterrupts(irq); enableInterrupts(irq);
} }


_function = function; _function = function;
_type = EventTypeInterrupt; _type = EventTypeInterrupt;
SCB_SHPR3 |= 0x00FF0000; // configure PendSV, lowest priority 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); enableInterrupts(irq);
} }


EventResponder * waitForEvent(EventResponder *list, int listsize, int timeout); EventResponder * waitForEvent(EventResponder *list, int listsize, int timeout);


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

+ 157
- 46
teensy3/FS.h View File

/* 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 #ifndef FS_H
#define FS_H #define FS_H
#ifdef __cplusplus #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 { class File : public Stream {
public: 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); 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) { size_t write(uint8_t b) {
return write(&b, 1); return write(&b, 1);
} }
size_t readBytes(char *buffer, size_t length) { size_t readBytes(char *buffer, size_t length) {
return read(buffer, 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: 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 // __cplusplus
#endif // FS_H #endif // FS_H

+ 45
- 0
teensy3/HardwareSerial.cpp View File

/* 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 View File

class HardwareSerial : public Stream class HardwareSerial : public Stream
{ {
public: 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) { virtual void begin(uint32_t baud, uint32_t format) {
serial_begin(BAUD2DIV(baud)); serial_begin(BAUD2DIV(baud));
serial_format(format); } serial_format(format); }
return len; } return len; }
virtual size_t write9bit(uint32_t c) { serial_putchar(c); return 1; } virtual size_t write9bit(uint32_t c) { serial_putchar(c); return 1; }
operator bool() { return true; } 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 HardwareSerial Serial1;
extern void serialEvent1(void); extern void serialEvent1(void);
class HardwareSerial2 : public HardwareSerial class HardwareSerial2 : public HardwareSerial
{ {
public: 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) { virtual void begin(uint32_t baud, uint32_t format) {
serial2_begin(BAUD2DIV2(baud)); serial2_begin(BAUD2DIV2(baud));
serial2_format(format); } serial2_format(format); }
class HardwareSerial3 : public HardwareSerial class HardwareSerial3 : public HardwareSerial
{ {
public: 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) { virtual void begin(uint32_t baud, uint32_t format) {
serial3_begin(BAUD2DIV3(baud)); serial3_begin(BAUD2DIV3(baud));
serial3_format(format); } serial3_format(format); }
class HardwareSerial4 : public HardwareSerial class HardwareSerial4 : public HardwareSerial
{ {
public: 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) { virtual void begin(uint32_t baud, uint32_t format) {
serial4_begin(BAUD2DIV3(baud)); serial4_begin(BAUD2DIV3(baud));
serial4_format(format); } serial4_format(format); }
class HardwareSerial5 : public HardwareSerial class HardwareSerial5 : public HardwareSerial
{ {
public: 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) { virtual void begin(uint32_t baud, uint32_t format) {
serial5_begin(BAUD2DIV3(baud)); serial5_begin(BAUD2DIV3(baud));
serial5_format(format); } serial5_format(format); }
class HardwareSerial6 : public HardwareSerial class HardwareSerial6 : public HardwareSerial
{ {
public: public:
constexpr HardwareSerial6() {}
constexpr HardwareSerial6(void (* const se)()) : HardwareSerial(se) {}
#if defined(__MK66FX1M0__) // For LPUART just pass baud straight in. #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) { virtual void begin(uint32_t baud, uint32_t format) {
serial6_begin(baud); serial6_begin(baud);
serial6_format(format); } serial6_format(format); }
#else #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) { virtual void begin(uint32_t baud, uint32_t format) {
serial6_begin(BAUD2DIV3(baud)); serial6_begin(BAUD2DIV3(baud));
serial6_format(format); } serial6_format(format); }

+ 10
- 3
teensy3/HardwareSerial1.cpp View File

* SOFTWARE. * SOFTWARE.
*/ */


#include <Arduino.h>
#include "HardwareSerial.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 View File

* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
#include <Arduino.h>
#include "HardwareSerial.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 View File

* SOFTWARE. * SOFTWARE.
*/ */


#include <Arduino.h>
#include "HardwareSerial.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 View File

* SOFTWARE. * SOFTWARE.
*/ */


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


#ifdef HAS_KINETISK_UART3 #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 #endif

+ 8
- 3
teensy3/HardwareSerial5.cpp View File

* SOFTWARE. * SOFTWARE.
*/ */


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


#ifdef HAS_KINETISK_UART4 #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 #endif

+ 12
- 3
teensy3/HardwareSerial6.cpp View File

* SOFTWARE. * SOFTWARE.
*/ */


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


#if defined(HAS_KINETISK_UART5) || defined (HAS_KINETISK_LPUART0) #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 #endif

+ 1
- 1
teensy3/IPAddress.cpp View File

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


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


size_t IPAddress::printTo(Print& p) const size_t IPAddress::printTo(Print& p) const

+ 1
- 1
teensy3/Makefile View File

OPTIONS = -DF_CPU=48000000 -DUSB_SERIAL -DLAYOUT_US_ENGLISH -DUSING_MAKEFILE OPTIONS = -DF_CPU=48000000 -DUSB_SERIAL -DLAYOUT_US_ENGLISH -DUSING_MAKEFILE


# options needed by many Arduino libraries to configure for Teensy 3.x # 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-m4" for Teensy 3.x
# use "cortex-m0plus" for Teensy LC # use "cortex-m0plus" for Teensy LC

+ 34
- 5
teensy3/Print.cpp View File

// developed for Teensyduino have made their way back into // developed for Teensyduino have made their way back into
// Arduino's code base. :-) // 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) size_t Print::write(const uint8_t *buffer, size_t size)
{ {
if (buffer == nullptr) return 0;
size_t count = 0; size_t count = 0;
while (size--) count += write(*buffer++); while (size--) count += write(*buffer++);
return count; return count;


#endif #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) size_t Print::printFloat(double number, uint8_t digits)
{ {
uint8_t sign=0; uint8_t sign=0;

+ 15
- 4
teensy3/Print.h View File



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


class __FlashStringHelper; class __FlashStringHelper;


size_t print(unsigned int n) { return printNumber(n, 10, 0); } size_t print(unsigned int n) { return printNumber(n, 10, 0); }
size_t print(long n); size_t print(long n);
size_t print(unsigned long n) { return printNumber(n, 10, 0); } 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(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(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(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(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(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(double n, int digits = 2) { return printFloat(n, digits); }
size_t print(const Printable &obj) { return obj.printTo(*this); } size_t print(const Printable &obj) { return obj.printTo(*this); }
size_t println(unsigned int n) { return print(n) + println(); } size_t println(unsigned int n) { return print(n) + println(); }
size_t println(long n) { return print(n) + println(); } size_t println(long n) { return print(n) + println(); }
size_t println(unsigned 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(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(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(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(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(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(double n, int digits = 2) { return print(n, digits) + println(); }
size_t println(const Printable &obj) { return obj.printTo(*this) + println(); } size_t println(const Printable &obj) { return obj.printTo(*this) + println(); }
int getWriteError() { return write_error; } int getWriteError() { return write_error; }
void clearWriteError() { setWriteError(0); } 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, ...); int printf(const __FlashStringHelper *format, ...);
protected: protected:
void setWriteError(int err = 1) { write_error = err; } void setWriteError(int err = 1) { write_error = err; }
#else #else
size_t printNumber(unsigned long n, uint8_t base, uint8_t sign); size_t printNumber(unsigned long n, uint8_t base, uint8_t sign);
#endif #endif
size_t printNumber64(uint64_t n, uint8_t base, uint8_t sign);
}; };





+ 10
- 1
teensy3/SPIFIFO.h View File



// The preferred way to set SPI speed is with SPI.beginTransaction() // 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 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_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 #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2)) //(120 / 2) * ((1+0)/4) = 15 MHz

+ 9
- 5
teensy3/Stream.cpp View File

parsing functions based on TextFinder library by Michael Margolis 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 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 #define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field
// as find but search ends if the terminator string is found // as find but search ends if the terminator string is found
bool Stream::findUntil(const char *target, const char *terminator) 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 // reads data from the stream until the target string of the given length is found
size_t index = 0; // maximum target string length is 64k bytes! size_t index = 0; // maximum target string length is 64k bytes!
size_t termIndex = 0; size_t termIndex = 0;
int c; 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){ while( (c = timedRead()) > 0){
if( c == target[index]){ if( c == target[index]){
//////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1); //////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
// //
size_t Stream::readBytes(char *buffer, size_t length) size_t Stream::readBytes(char *buffer, size_t length)
{ {
if (buffer == nullptr) return 0;
size_t count = 0; size_t count = 0;
while (count < length) { while (count < length) {
int c = timedRead(); int c = timedRead();


size_t Stream::readBytesUntil(char terminator, 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; if (length < 1) return 0;
length--; length--;
size_t index = 0; size_t index = 0;

+ 1
- 4
teensy3/Tone.cpp View File

* SOFTWARE. * 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 // IntervalTimer based tone. This allows tone() to share the timers with other
// libraries, rather than permanently hogging one PIT timer even for projects // libraries, rather than permanently hogging one PIT timer even for projects

+ 1
- 0
teensy3/Udp.h View File



public: 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 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 virtual void stop() =0; // Finish with the UDP socket


// Sending UDP packets // Sending UDP packets

+ 2
- 2
teensy3/WCharacter.h View File

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




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





+ 2
- 0
teensy3/WProgram.h View File



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

+ 3
- 1
teensy3/WString.cpp View File

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


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




/*********************************************/ /*********************************************/
/* Character Access */ /* Character Access */
/*********************************************/ /*********************************************/


const char String::zerotermination = 0;

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

+ 5
- 1
teensy3/WString.h View File

void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const; 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 void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const
{getBytes((unsigned char *)buf, bufsize, index);} {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 // search
int indexOf( char ch ) const; int indexOf( char ch ) const;
// for more information http://www.artima.com/cppsource/safebool.html // for more information http://www.artima.com/cppsource/safebool.html
typedef void (String::*StringIfHelperType)() const; typedef void (String::*StringIfHelperType)() const;
void StringIfHelper() const {} void StringIfHelper() const {}
static const char zerotermination;
public: public:
operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; } operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; }
}; };

+ 9
- 7
teensy3/analog.c View File

// the alternate clock is connected to OSCERCLK (16 MHz). // 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 2 to 12 MHz for 16 bit mode
// datasheet says ADC clock should be 1 to 18 MHz for 8-12 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_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_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 #define ADC_CFG1_10BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 15 MHz
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 2 MHz #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 #define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 2 MHz
#else #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 #endif


void analog_init(void) void analog_init(void)
} else { } else {
DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2 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; *(volatile aliased_int16_t *)&(DAC0_DAT0L) = val;
#elif defined(__MKL26Z64__) #elif defined(__MKL26Z64__)
} else { } else {
DAC1_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2 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; *(volatile aliased_int16_t *)&(DAC1_DAT0L) = val;
} }

+ 3
- 0
teensy3/avr/eeprom.h View File

* THE SOFTWARE. * THE SOFTWARE.
*/ */


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

#ifndef _AVR_EEPROM_H_ #ifndef _AVR_EEPROM_H_
#define _AVR_EEPROM_H_ 1 #define _AVR_EEPROM_H_ 1



+ 1
- 0
teensy3/avr/pgmspace.h View File

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


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



+ 1
- 1
teensy3/avr_emulation.cpp View File

*/ */




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


uint8_t SPCRemulation::pinout = 0; uint8_t SPCRemulation::pinout = 0;

+ 1
- 1
teensy3/avr_emulation.h View File

int ret = 0; int ret = 0;
if (digitalReadFast(14)) ret |= (1<<0); if (digitalReadFast(14)) ret |= (1<<0);
if (digitalReadFast(15)) ret |= (1<<1); 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(17)) ret |= (1<<3);
if (digitalReadFast(18)) ret |= (1<<4); if (digitalReadFast(18)) ret |= (1<<4);
if (digitalReadFast(19)) ret |= (1<<5); if (digitalReadFast(19)) ret |= (1<<5);

+ 1
- 1
teensy3/avr_functions.h View File

char * ultoa(unsigned long val, char *buf, int radix); char * ultoa(unsigned long val, char *buf, int radix);
char * ltoa(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) __attribute__((always_inline, unused));
static inline char * utoa(unsigned int val, char *buf, int radix) { return ultoa(val, buf, radix); } static inline char * utoa(unsigned int val, char *buf, int radix) { return ultoa(val, buf, radix); }
static inline char * itoa(int val, char *buf, int radix) __attribute__((always_inline, unused)); static inline char * itoa(int val, char *buf, int radix) __attribute__((always_inline, unused));

+ 448
- 5
teensy3/core_pins.h View File

#define CORE_PIN32_PORTSET GPIOB_PSOR #define CORE_PIN32_PORTSET GPIOB_PSOR
#define CORE_PIN33_PORTSET GPIOA_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_PIN0_PORTCLEAR GPIOB_PCOR
#define CORE_PIN1_PORTCLEAR GPIOB_PCOR #define CORE_PIN1_PORTCLEAR GPIOB_PCOR
#define CORE_PIN2_PORTCLEAR GPIOD_PCOR #define CORE_PIN2_PORTCLEAR GPIOD_PCOR
#define CORE_PIN25_PORTSET FGPIOE_PSOR #define CORE_PIN25_PORTSET FGPIOE_PSOR
#define CORE_PIN26_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_PIN0_PORTCLEAR FGPIOB_PCOR
#define CORE_PIN1_PORTCLEAR FGPIOB_PCOR #define CORE_PIN1_PORTCLEAR FGPIOB_PCOR
#define CORE_PIN2_PORTCLEAR FGPIOD_PCOR #define CORE_PIN2_PORTCLEAR FGPIOD_PCOR
#define CORE_PIN62_PORTSET GPIOE_PSOR #define CORE_PIN62_PORTSET GPIOE_PSOR
#define CORE_PIN63_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_PIN0_PORTCLEAR GPIOB_PCOR
#define CORE_PIN1_PORTCLEAR GPIOB_PCOR #define CORE_PIN1_PORTCLEAR GPIOB_PCOR
#define CORE_PIN2_PORTCLEAR GPIOD_PCOR #define CORE_PIN2_PORTCLEAR GPIOD_PCOR
} }
} }


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); 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) __attribute__((always_inline, unused));
static inline uint8_t digitalReadFast(uint8_t pin) static inline uint8_t digitalReadFast(uint8_t pin)
void _reboot_Teensyduino_(void) __attribute__((noreturn)); void _reboot_Teensyduino_(void) __attribute__((noreturn));
void _restart_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 yield(void);


void delay(uint32_t msec); void delay(uint32_t msec);
static inline void delayMicroseconds(uint32_t) __attribute__((always_inline, unused)); static inline void delayMicroseconds(uint32_t) __attribute__((always_inline, unused));
static inline void delayMicroseconds(uint32_t usec) 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; uint32_t n = usec * 80;
#elif F_CPU == 216000000 #elif F_CPU == 216000000
uint32_t n = usec * 72; uint32_t n = usec * 72;
#endif #endif
#ifdef KINETISL #ifdef KINETISL
"sub %0, #1" "\n\t" "sub %0, #1" "\n\t"
"bne L_%=_delayMicroseconds" "\n"
: "+l" (n) :
#else #else
"subs %0, #1" "\n\t" "subs %0, #1" "\n\t"
#endif
"bne L_%=_delayMicroseconds" "\n" "bne L_%=_delayMicroseconds" "\n"
: "+r" (n) : : "+r" (n) :
#endif
); );
} }


} }
#endif #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 View File

* SOFTWARE. * 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 "kinetis.h"
#include <avr/eeprom.h> #include <avr/eeprom.h>
//#include "HardwareSerial.h" //#include "HardwareSerial.h"

+ 2
- 2
teensy3/keylayouts.h View File

#define ASCII_20 KEY_SPACE // 32 #define ASCII_20 KEY_SPACE // 32
#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! #define ASCII_21 KEY_1 + SHIFT_MASK // 33 !
#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " #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_24 KEY_4 + SHIFT_MASK // 36 $
#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % #define ASCII_25 KEY_5 + SHIFT_MASK // 37 %
#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & #define ASCII_26 KEY_7 + SHIFT_MASK // 38 &
#define ASCII_20 KEY_SPACE // 32 #define ASCII_20 KEY_SPACE // 32
#define ASCII_21 KEY_1 + SHIFT_MASK // 33 ! #define ASCII_21 KEY_1 + SHIFT_MASK // 33 !
#define ASCII_22 KEY_2 + SHIFT_MASK // 34 " #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_24 KEY_4 + SHIFT_MASK // 36 $
#define ASCII_25 KEY_5 + SHIFT_MASK // 37 % #define ASCII_25 KEY_5 + SHIFT_MASK // 37 %
#define ASCII_26 KEY_7 + SHIFT_MASK // 38 & #define ASCII_26 KEY_7 + SHIFT_MASK // 38 &

+ 36
- 21
teensy3/kinetis.h View File



#endif // end of board-specific definitions #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 #define F_PLL 240000000
#ifndef F_BUS #ifndef F_BUS
#define F_BUS 60000000 #define F_BUS 60000000


#define PORTA_PCR0 (*(volatile uint32_t *)0x40049000) // Pin Control Register n #define PORTA_PCR0 (*(volatile uint32_t *)0x40049000) // Pin Control Register n
#define PORT_PCR_ISF ((uint32_t)0x01000000) // Interrupt Status Flag #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(n) ((uint32_t)(((n) & 15) << 16)) // Interrupt Configuration
#define PORT_PCR_IRQC_MASK ((uint32_t)0x000F0000) #define PORT_PCR_IRQC_MASK ((uint32_t)0x000F0000)
#define PORT_PCR_LK ((uint32_t)0x00008000) // Lock Register #define PORT_PCR_LK ((uint32_t)0x00008000) // Lock Register
#define FTM0_CONF (*(volatile uint32_t *)0x40038084) // Configuration #define FTM0_CONF (*(volatile uint32_t *)0x40038084) // Configuration
#define FTM_CONF_GTBEOUT 0x400 // Global Time Base Output #define FTM_CONF_GTBEOUT 0x400 // Global Time Base Output
#define FTM_CONF_GTBEEN 0x200 // Global Time Base Enable #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 FTM0_FLTPOL (*(volatile uint32_t *)0x40038088) // FTM Fault Input Polarity
#define FTM_FLTPOL_FLT3POL 0x08 // Fault Input 3 Polarity #define FTM_FLTPOL_FLT3POL 0x08 // Fault Input 3 Polarity
#define FTM_FLTPOL_FLT2POL 0x04 // Fault Input 2 Polarity #define FTM_FLTPOL_FLT2POL 0x04 // Fault Input 2 Polarity
#define ENET_EIR_TS_AVAIL ((uint32_t)0x00010000) // Transmit Timestamp Available #define ENET_EIR_TS_AVAIL ((uint32_t)0x00010000) // Transmit Timestamp Available
#define ENET_EIR_TS_TIMER ((uint32_t)0x00008000) // Timestamp Timer #define ENET_EIR_TS_TIMER ((uint32_t)0x00008000) // Timestamp Timer
#define ENET_EIMR (*(volatile uint32_t *)0x400C0008) // Interrupt Mask Register #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 (*(volatile uint32_t *)0x400C0010) // Receive Descriptor Active Register
#define ENET_RDAR_RDAR ((uint32_t)0x01000000) #define ENET_RDAR_RDAR ((uint32_t)0x01000000)
#define ENET_TDAR (*(volatile uint32_t *)0x400C0014) // Transmit Descriptor Active Register #define ENET_TDAR (*(volatile uint32_t *)0x400C0014) // Transmit Descriptor Active Register
#define SPI1_MH (KINETISL_SPI1.MH) // Match High #define SPI1_MH (KINETISL_SPI1.MH) // Match High
#define SPI1_DL (KINETISL_SPI1.DL) // Data Low #define SPI1_DL (KINETISL_SPI1.DL) // Data Low
#define SPI1_DH (KINETISL_SPI1.DH) // Data High #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 #define SPI1_C3 (KINETISL_SPI1.C3) // Control Register 3
#endif #endif


extern void (* _VectorsRam[NVIC_NUM_INTERRUPTS+16])(void); extern void (* _VectorsRam[NVIC_NUM_INTERRUPTS+16])(void);
extern void (* const _VectorsFlash[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 #ifdef __cplusplus
} }
#endif #endif

+ 1
- 1
teensy3/main.cpp View File

* SOFTWARE. * SOFTWARE.
*/ */


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


extern "C" int main(void) extern "C" int main(void)
{ {

+ 49
- 10
teensy3/mk20dx128.c View File

UART0_C2 = UART_C2_TE; UART0_C2 = UART_C2_TE;
PORTB_PCR17 = PORT_PCR_MUX(3); PORTB_PCR17 = PORT_PCR_MUX(3);
#endif #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)) { if (!(RTC_CR & RTC_CR_OSCE)) {
RTC_SR = 0; RTC_SR = 0;
RTC_CR = RTC_CR_SC16P | RTC_CR_SC4P | RTC_CR_OSCE; RTC_CR = RTC_CR_SC16P | RTC_CR_SC4P | RTC_CR_OSCE;
SMC_PMCTRL = SMC_PMCTRL_RUNM(3); // enter HSRUN mode SMC_PMCTRL = SMC_PMCTRL_RUNM(3); // enter HSRUN mode
while (SMC_PMSTAT != SMC_PMSTAT_HSRUN) ; // wait for HSRUN while (SMC_PMSTAT != SMC_PMSTAT_HSRUN) ; // wait for HSRUN
#endif #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_C5 = MCG_C5_PRDIV0(0);
MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(14); MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(14);
#elif F_CPU == 216000000 #elif F_CPU == 216000000
#endif #endif
#endif #endif
// now program the clock dividers // 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 // config divisors: 240 MHz core, 60 MHz bus, 30 MHz flash, USB = 240 / 5
// TODO: gradual ramp-up for HSRUN mode // TODO: gradual ramp-up for HSRUN mode
#if F_BUS == 60000000 #if F_BUS == 60000000
#elif F_BUS == 72000000 #elif F_BUS == 72000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(2) | SIM_CLKDIV1_OUTDIV4(7); SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(2) | SIM_CLKDIV1_OUTDIV4(7);
#elif F_BUS == 108000000 #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 #else
#error "This F_CPU & F_BUS combination is not supported" #error "This F_CPU & F_BUS combination is not supported"
#endif #endif
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV4(1); SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV4(1);
#endif #endif
#else #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 #endif


#if F_CPU > 16000000 #if F_CPU > 16000000
// wait for PLL clock to be used // wait for PLL clock to be used
while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(3)) ; while ((MCG_S & MCG_S_CLKST_MASK) != MCG_S_CLKST(3)) ;
// now we're in PEE mode // 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 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); SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_IRC48SEL | SIM_SOPT2_TRACECLKSEL | SIM_SOPT2_CLKOUTSEL(6);
#else #else
// USB uses PLL clock
SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_PLLFLLSEL | SIM_SOPT2_TRACECLKSEL | SIM_SOPT2_CLKOUTSEL(6); SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_PLLFLLSEL | SIM_SOPT2_TRACECLKSEL | SIM_SOPT2_CLKOUTSEL(6);
#endif #endif
#elif defined(KINETISL) #elif defined(KINETISL)
SMC_PMCTRL = SMC_PMCTRL_RUNM(2); // VLPR mode :-) SMC_PMCTRL = SMC_PMCTRL_RUNM(2); // VLPR mode :-)
#endif #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 // initialize the SysTick counter
SYST_RVR = (F_CPU / 1000) - 1; SYST_RVR = (F_CPU / 1000) - 1;
SYST_CVR = 0; SYST_CVR = 0;


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


// the peripheral speed (F_BUS). Serial1 & Serial2 baud // the peripheral speed (F_BUS). Serial1 & Serial2 baud
// rates will be impacted, but most other peripherals // rates will be impacted, but most other peripherals
// will continue functioning at the same speed. // 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 SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // ok
#elif F_CPU == 240000000 && F_BUS == 80000000 #elif F_CPU == 240000000 && F_BUS == 80000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok
SMC_PMCTRL = SMC_PMCTRL_RUNM(3); SMC_PMCTRL = SMC_PMCTRL_RUNM(3);
while (SMC_PMSTAT != SMC_PMSTAT_HSRUN) {;} // wait while (SMC_PMSTAT != SMC_PMSTAT_HSRUN) {;} // wait
// Then configure clock for full speed // 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); SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7);
#elif F_CPU == 240000000 && F_BUS == 80000000 #elif F_CPU == 240000000 && F_BUS == 80000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 7); SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 7);

+ 2
- 0
teensy3/mk20dx128.ld View File

RAM (rwx) : ORIGIN = 0x1FFFE000, LENGTH = 16K RAM (rwx) : ORIGIN = 0x1FFFE000, LENGTH = 16K
} }


ENTRY(_VectorsFlash)


SECTIONS SECTIONS
{ {
} > RAM } > RAM


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





+ 2
- 0
teensy3/mk20dx256.ld View File

RAM (rwx) : ORIGIN = 0x1FFF8000, LENGTH = 64K RAM (rwx) : ORIGIN = 0x1FFF8000, LENGTH = 64K
} }


ENTRY(_VectorsFlash)


SECTIONS SECTIONS
{ {
} > RAM } > RAM


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





+ 3
- 1
teensy3/mk64fx512.ld View File

MEMORY MEMORY
{ {
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 512K FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 512K
RAM (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 192K
RAM (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 262136
} }


ENTRY(_VectorsFlash)


SECTIONS SECTIONS
{ {
} > RAM } > RAM


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





+ 2
- 0
teensy3/mk66fx1m0.ld View File

RAM (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 256K RAM (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 256K
} }


ENTRY(_VectorsFlash)


SECTIONS SECTIONS
{ {
} > RAM } > RAM


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





+ 2
- 0
teensy3/mkl26z64.ld View File

RAM (rwx) : ORIGIN = 0x1FFFF800, LENGTH = 8K RAM (rwx) : ORIGIN = 0x1FFFF800, LENGTH = 8K
} }


ENTRY(_VectorsFlash)


SECTIONS SECTIONS
{ {
} > RAM } > RAM


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





+ 6
- 3
teensy3/pins_arduino.h View File

#define analogInputToDigitalPin(p) (((p) <= 9) ? (p) + 14 : (((p) <= 12) ? (p) + 14 : -1)) #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 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) #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 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) #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 #endif


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

+ 38
- 5
teensy3/pins_teensy.c View File



// The Pin Config Register is used to look up the correct interrupt table // The Pin Config Register is used to look up the correct interrupt table
// for the corresponding port. // for the corresponding port.
inline voidFuncPtr* getIsrTable(volatile uint32_t *config) {
static inline voidFuncPtr* getIsrTable(volatile uint32_t *config) {
voidFuncPtr* isr_table = NULL; voidFuncPtr* isr_table = NULL;
if(&PORTA_PCR0 <= config && config <= &PORTA_PCR31) isr_table = isr_table_portA; 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; else if(&PORTB_PCR0 <= config && config <= &PORTB_PCR31) isr_table = isr_table_portB;


#endif #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_MOD (61440 - 1)
#define DEFAULT_FTM_PRESCALE 2 #define DEFAULT_FTM_PRESCALE 2
#elif F_TIMER == 108000000 #elif F_TIMER == 108000000
TPM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0); TPM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0);
#endif #endif
analog_init(); 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 // 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/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 // 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(); usb_init();
delay(350);
delay(TEENSY_INIT_USB_DELAY_AFTER);
} }






} }


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) uint8_t digitalRead(uint8_t pin)
{ {
if (pin >= CORE_NUM_DIGITAL) return 0; if (pin >= CORE_NUM_DIGITAL) return 0;
} }


// TODO: verify these result in correct timeouts... // 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 #define PULSEIN_LOOPS_PER_USEC 33
#elif F_CPU == 216000000 #elif F_CPU == 216000000
#define PULSEIN_LOOPS_PER_USEC 31 #define PULSEIN_LOOPS_PER_USEC 31

+ 10
- 2
teensy3/serial1.c View File

#define rts_assert() *(rts_pin+8) = rts_mask; #define rts_assert() *(rts_pin+8) = rts_mask;
#define rts_deassert() *(rts_pin+4) = rts_mask; #define rts_deassert() *(rts_pin+4) = rts_mask;
#endif #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_head = 0;
static volatile uint16_t tx_buffer_tail = 0; static volatile uint16_t tx_buffer_tail = 0;
#else #else
static volatile uint8_t tx_buffer_head = 0; static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0; static volatile uint8_t tx_buffer_tail = 0;
#endif #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_head = 0;
static volatile uint16_t rx_buffer_tail = 0; static volatile uint16_t rx_buffer_tail = 0;
#else #else
case 26: CORE_PIN26_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; case 26: CORE_PIN26_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break;
#endif #endif
} }
UART0_S1;
UART0_D; // clear leftover error status
rx_buffer_head = 0; rx_buffer_head = 0;
rx_buffer_tail = 0; rx_buffer_tail = 0;
if (rts_pin) rts_deassert(); if (rts_pin) rts_deassert();

+ 10
- 2
teensy3/serial2.c View File

#define rts_assert() *(rts_pin+8) = rts_mask; #define rts_assert() *(rts_pin+8) = rts_mask;
#define rts_deassert() *(rts_pin+4) = rts_mask; #define rts_deassert() *(rts_pin+4) = rts_mask;
#endif #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_head = 0;
static volatile uint16_t tx_buffer_tail = 0; static volatile uint16_t tx_buffer_tail = 0;
#else #else
static volatile uint8_t tx_buffer_head = 0; static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0; static volatile uint8_t tx_buffer_tail = 0;
#endif #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_head = 0;
static volatile uint16_t rx_buffer_tail = 0; static volatile uint16_t rx_buffer_tail = 0;
#else #else
CORE_PIN9_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); // PTC3 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 CORE_PIN10_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); // PTC4
#endif #endif
UART1_S1;
UART1_D; // clear leftover error status
rx_buffer_head = 0; rx_buffer_head = 0;
rx_buffer_tail = 0; rx_buffer_tail = 0;
if (rts_pin) rts_deassert(); if (rts_pin) rts_deassert();

+ 10
- 2
teensy3/serial3.c View File

#define rts_assert() *(rts_pin+8) = rts_mask; #define rts_assert() *(rts_pin+8) = rts_mask;
#define rts_deassert() *(rts_pin+4) = rts_mask; #define rts_deassert() *(rts_pin+4) = rts_mask;
#endif #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_head = 0;
static volatile uint16_t tx_buffer_tail = 0; static volatile uint16_t tx_buffer_tail = 0;
#else #else
static volatile uint8_t tx_buffer_head = 0; static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0; static volatile uint8_t tx_buffer_tail = 0;
#endif #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_head = 0;
static volatile uint16_t rx_buffer_tail = 0; static volatile uint16_t rx_buffer_tail = 0;
#else #else
case 20: CORE_PIN20_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; case 20: CORE_PIN20_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break;
} }
#endif #endif
UART2_S1;
UART2_D; // clear leftover error status
rx_buffer_head = 0; rx_buffer_head = 0;
rx_buffer_tail = 0; rx_buffer_tail = 0;
if (rts_pin) rts_deassert(); if (rts_pin) rts_deassert();

+ 10
- 2
teensy3/serial4.c View File

static volatile uint8_t *rts_pin=NULL; static volatile uint8_t *rts_pin=NULL;
#define rts_assert() *rts_pin = 0 #define rts_assert() *rts_pin = 0
#define rts_deassert() *rts_pin = 1 #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_head = 0;
static volatile uint16_t tx_buffer_tail = 0; static volatile uint16_t tx_buffer_tail = 0;
#else #else
static volatile uint8_t tx_buffer_head = 0; static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0; static volatile uint8_t tx_buffer_tail = 0;
#endif #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_head = 0;
static volatile uint16_t rx_buffer_tail = 0; static volatile uint16_t rx_buffer_tail = 0;
#else #else
case 32: CORE_PIN32_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; // PTC4 case 32: CORE_PIN32_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; // PTC4
case 62: CORE_PIN62_CONFIG = 0; break; case 62: CORE_PIN62_CONFIG = 0; break;
} }
UART3_S1;
UART3_D; // clear leftover error status
rx_buffer_head = 0; rx_buffer_head = 0;
rx_buffer_tail = 0; rx_buffer_tail = 0;
if (rts_pin) rts_deassert(); if (rts_pin) rts_deassert();

+ 10
- 2
teensy3/serial5.c View File

static volatile uint8_t *rts_pin=NULL; static volatile uint8_t *rts_pin=NULL;
#define rts_assert() *rts_pin = 0 #define rts_assert() *rts_pin = 0
#define rts_deassert() *rts_pin = 1 #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_head = 0;
static volatile uint16_t tx_buffer_tail = 0; static volatile uint16_t tx_buffer_tail = 0;
#else #else
static volatile uint8_t tx_buffer_head = 0; static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0; static volatile uint8_t tx_buffer_tail = 0;
#endif #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_head = 0;
static volatile uint16_t rx_buffer_tail = 0; static volatile uint16_t rx_buffer_tail = 0;
#else #else
UART4_C2 = 0; UART4_C2 = 0;
CORE_PIN34_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); 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); 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_head = 0;
rx_buffer_tail = 0; rx_buffer_tail = 0;
if (rts_pin) rts_deassert(); if (rts_pin) rts_deassert();

+ 10
- 2
teensy3/serial6.c View File

static volatile uint8_t *rts_pin=NULL; static volatile uint8_t *rts_pin=NULL;
#define rts_assert() *rts_pin = 0 #define rts_assert() *rts_pin = 0
#define rts_deassert() *rts_pin = 1 #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_head = 0;
static volatile uint16_t tx_buffer_tail = 0; static volatile uint16_t tx_buffer_tail = 0;
#else #else
static volatile uint8_t tx_buffer_head = 0; static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0; static volatile uint8_t tx_buffer_tail = 0;
#endif #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_head = 0;
static volatile uint16_t rx_buffer_tail = 0; static volatile uint16_t rx_buffer_tail = 0;
#else #else
UART5_C2 = 0; UART5_C2 = 0;
CORE_PIN47_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); 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); 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_head = 0;
rx_buffer_tail = 0; rx_buffer_tail = 0;
if (rts_pin) rts_deassert(); if (rts_pin) rts_deassert();

+ 1
- 1
teensy3/serial6_lpuart.c View File

} }
} }


#endif // HAS_KINETISK_UART4
#endif // HAS_KINETISK_LPUART0

+ 6
- 0
teensy3/serialEvent.cpp View File


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

+ 6
- 0
teensy3/serialEvent1.cpp View File


#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 View File


#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 View File


#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 View File


#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 View File


#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 View File


#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 View File


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

+ 5
- 0
teensy3/serialEventUSB2.cpp View File


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

+ 1
- 3
teensy3/usb_audio.cpp View File

* SOFTWARE. * SOFTWARE.
*/ */


#include <Arduino.h>
#include "usb_dev.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 #ifdef AUDIO_INTERFACE // defined by usb_dev.h -> usb_desc.h
#if F_CPU >= 20000000 #if F_CPU >= 20000000

+ 187
- 3
teensy3/usb_desc.c View File

#ifdef BCD_DEVICE #ifdef BCD_DEVICE
LSB(BCD_DEVICE), MSB(BCD_DEVICE), // bcdDevice LSB(BCD_DEVICE), MSB(BCD_DEVICE), // bcdDevice
#else #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, 0x00, 0x02,
#endif
#endif #endif
1, // iManufacturer 1, // iManufacturer
2, // iProduct 2, // iProduct
0x95, 0x01, // Report Count (1) 0x95, 0x01, // Report Count (1)
0x09, 0x56, // Usage (Scan Time) 0x09, 0x56, // Usage (Scan Time)
0x81, 0x02, // Input (variable,absolute) 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) 0x05, 0x0D, // Usage Page (Digitizers)
0x09, 0x55, // Usage (Contact Count Maximum) 0x09, 0x55, // Usage (Contact Count Maximum)
0x25, MULTITOUCH_FINGERS, // Logical Maximum (10) 0x25, MULTITOUCH_FINGERS, // Logical Maximum (10)
#define CDC_DATA_INTERFACE_DESC_SIZE 0 #define CDC_DATA_INTERFACE_DESC_SIZE 0
#endif #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 #ifdef MIDI_INTERFACE
#if !defined(MIDI_NUM_CABLES) || MIDI_NUM_CABLES < 1 || MIDI_NUM_CABLES > 16 #if !defined(MIDI_NUM_CABLES) || MIDI_NUM_CABLES < 1 || MIDI_NUM_CABLES > 16
#error "MIDI_NUM_CABLES must be defined between 1 to 16" #error "MIDI_NUM_CABLES must be defined between 1 to 16"
0x02, // bFunctionClass 0x02, // bFunctionClass
0x02, // bFunctionSubClass 0x02, // bFunctionSubClass
0x01, // bFunctionProtocol 0x01, // bFunctionProtocol
4, // iFunction
0, // iFunction
#endif #endif


#ifdef CDC_DATA_INTERFACE #ifdef CDC_DATA_INTERFACE
0, // bInterval 0, // bInterval
#endif // CDC_DATA_INTERFACE #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 #ifdef MIDI_INTERFACE
// Standard MS Interface Descriptor, // Standard MS Interface Descriptor,
9, // bLength 9, // bLength
0x06, // bInterfaceClass (0x06 = still image) 0x06, // bInterfaceClass (0x06 = still image)
0x01, // bInterfaceSubClass 0x01, // bInterfaceSubClass
0x01, // bInterfaceProtocol 0x01, // bInterfaceProtocol
4, // iInterface
0, // iInterface
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength 7, // bLength
5, // bDescriptorType 5, // bDescriptorType

+ 151
- 68
teensy3/usb_desc.h View File

#include <stddef.h> #include <stddef.h>


#define ENDPOINT_UNUSED 0x00 #define ENDPOINT_UNUSED 0x00
#define ENDPOINT_TRANSIMIT_ONLY 0x15
#define ENDPOINT_TRANSMIT_ONLY 0x15
#define ENDPOINT_RECEIVE_ONLY 0x19 #define ENDPOINT_RECEIVE_ONLY 0x19
#define ENDPOINT_TRANSMIT_AND_RECEIVE 0x1D #define ENDPOINT_TRANSMIT_AND_RECEIVE 0x1D
#define ENDPOINT_RECEIVE_ISOCHRONOUS 0x18 #define ENDPOINT_RECEIVE_ISOCHRONOUS 0x18
#define CDC_ACM_SIZE 16 #define CDC_ACM_SIZE 16
#define CDC_RX_SIZE 64 #define CDC_RX_SIZE 64
#define CDC_TX_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 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) #elif defined(USB_KEYBOARDONLY)
#define VENDOR_ID 0x16C0 #define VENDOR_ID 0x16C0
#define KEYMEDIA_ENDPOINT 4 #define KEYMEDIA_ENDPOINT 4
#define KEYMEDIA_SIZE 8 #define KEYMEDIA_SIZE 8
#define KEYMEDIA_INTERVAL 4 #define KEYMEDIA_INTERVAL 4
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_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) #elif defined(USB_HID)
#define VENDOR_ID 0x16C0 #define VENDOR_ID 0x16C0
#define JOYSTICK_ENDPOINT 4 #define JOYSTICK_ENDPOINT 4
#define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick #define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick
#define JOYSTICK_INTERVAL 2 #define JOYSTICK_INTERVAL 2
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_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) #elif defined(USB_SERIAL_HID)
#define VENDOR_ID 0x16C0 #define VENDOR_ID 0x16C0
#define JOYSTICK_ENDPOINT 6 #define JOYSTICK_ENDPOINT 6
#define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick #define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick
#define JOYSTICK_INTERVAL 1 #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 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) #elif defined(USB_TOUCHSCREEN)
#define VENDOR_ID 0x16C0 #define VENDOR_ID 0x16C0
#define KEYMEDIA_INTERVAL 4 #define KEYMEDIA_INTERVAL 4
#define MULTITOUCH_INTERFACE 3 // Touchscreen #define MULTITOUCH_INTERFACE 3 // Touchscreen
#define MULTITOUCH_ENDPOINT 5 #define MULTITOUCH_ENDPOINT 5
#define MULTITOUCH_SIZE 8
#define MULTITOUCH_SIZE 16
#define MULTITOUCH_FINGERS 10 #define MULTITOUCH_FINGERS 10
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_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) #elif defined(USB_HID_TOUCHSCREEN)
#define VENDOR_ID 0x16C0 #define VENDOR_ID 0x16C0
#define MOUSE_INTERVAL 2 #define MOUSE_INTERVAL 2
#define MULTITOUCH_INTERFACE 4 // Touchscreen #define MULTITOUCH_INTERFACE 4 // Touchscreen
#define MULTITOUCH_ENDPOINT 5 #define MULTITOUCH_ENDPOINT 5
#define MULTITOUCH_SIZE 8
#define MULTITOUCH_SIZE 16
#define MULTITOUCH_FINGERS 10 #define MULTITOUCH_FINGERS 10
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_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) #elif defined(USB_MIDI)
#define VENDOR_ID 0x16C0 #define VENDOR_ID 0x16C0
#define MIDI_TX_SIZE 64 #define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 4 #define MIDI_RX_ENDPOINT 4
#define MIDI_RX_SIZE 64 #define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_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 ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY


#elif defined(USB_MIDI4) #elif defined(USB_MIDI4)
#define MIDI_TX_SIZE 64 #define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 4 #define MIDI_RX_ENDPOINT 4
#define MIDI_RX_SIZE 64 #define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_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 ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY


#elif defined(USB_MIDI16) #elif defined(USB_MIDI16)
#define MIDI_TX_SIZE 64 #define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 4 #define MIDI_RX_ENDPOINT 4
#define MIDI_RX_SIZE 64 #define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_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 ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY


#elif defined(USB_MIDI_SERIAL) #elif defined(USB_MIDI_SERIAL)
#define MIDI_TX_SIZE 64 #define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 5 #define MIDI_RX_ENDPOINT 5
#define MIDI_RX_SIZE 64 #define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_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 ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY


#elif defined(USB_MIDI4_SERIAL) #elif defined(USB_MIDI4_SERIAL)
#define MIDI_TX_SIZE 64 #define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 5 #define MIDI_RX_ENDPOINT 5
#define MIDI_RX_SIZE 64 #define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_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 ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY


#elif defined(USB_MIDI16_SERIAL) #elif defined(USB_MIDI16_SERIAL)
#define MIDI_TX_SIZE 64 #define MIDI_TX_SIZE 64
#define MIDI_RX_ENDPOINT 5 #define MIDI_RX_ENDPOINT 5
#define MIDI_RX_SIZE 64 #define MIDI_RX_SIZE 64
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_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 ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY


#elif defined(USB_RAWHID) #elif defined(USB_RAWHID)
#define SEREMU_RX_ENDPOINT 2 #define SEREMU_RX_ENDPOINT 2
#define SEREMU_RX_SIZE 32 #define SEREMU_RX_SIZE 32
#define SEREMU_RX_INTERVAL 2 #define SEREMU_RX_INTERVAL 2
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_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 ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY


#elif defined(USB_FLIGHTSIM) #elif defined(USB_FLIGHTSIM)
#define SEREMU_RX_ENDPOINT 2 #define SEREMU_RX_ENDPOINT 2
#define SEREMU_RX_SIZE 32 #define SEREMU_RX_SIZE 32
#define SEREMU_RX_INTERVAL 2 #define SEREMU_RX_INTERVAL 2
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_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 ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY


#elif defined(USB_FLIGHTSIM_JOYSTICK) #elif defined(USB_FLIGHTSIM_JOYSTICK)
#define VENDOR_ID 0x16C0 #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 {'T','e','e','n','s','y','d','u','i','n','o'}
#define MANUFACTURER_NAME_LEN 11 #define MANUFACTURER_NAME_LEN 11
#define PRODUCT_NAME {'T','e','e','n','s','y',' ','F','l','i','g','h','t',' ','S','i','m',' ','C','o','n','t','r','o','l','s'} #define PRODUCT_NAME {'T','e','e','n','s','y',' ','F','l','i','g','h','t',' ','S','i','m',' ','C','o','n','t','r','o','l','s'}
#define JOYSTICK_ENDPOINT 5 #define JOYSTICK_ENDPOINT 5
#define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick #define JOYSTICK_SIZE 12 // 12 = normal, 64 = extreme joystick
#define JOYSTICK_INTERVAL 1 #define JOYSTICK_INTERVAL 1
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_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 ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY




#elif defined(USB_MTPDISK) #elif defined(USB_MTPDISK)
#define SEREMU_RX_ENDPOINT 2 #define SEREMU_RX_ENDPOINT 2
#define SEREMU_RX_SIZE 32 #define SEREMU_RX_SIZE 32
#define SEREMU_RX_INTERVAL 2 #define SEREMU_RX_INTERVAL 2
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE
// TODO: Should ENDPOINT4_CONFIG be ENDPOINT_TRANSMIT_ONLY ???
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY #define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY


#elif defined(USB_AUDIO) #elif defined(USB_AUDIO)
#define AUDIO_RX_ENDPOINT 4 #define AUDIO_RX_ENDPOINT 4
#define AUDIO_RX_SIZE 180 #define AUDIO_RX_SIZE 180
#define AUDIO_SYNC_ENDPOINT 5 #define AUDIO_SYNC_ENDPOINT 5
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY #define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS #define ENDPOINT3_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ISOCHRONOUS #define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ISOCHRONOUS
#define AUDIO_RX_ENDPOINT 7 #define AUDIO_RX_ENDPOINT 7
#define AUDIO_RX_SIZE 180 #define AUDIO_RX_SIZE 180
#define AUDIO_SYNC_ENDPOINT 8 #define AUDIO_SYNC_ENDPOINT 8
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_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 ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS #define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS
#define ENDPOINT7_CONFIG ENDPOINT_RECEIVE_ISOCHRONOUS #define ENDPOINT7_CONFIG ENDPOINT_RECEIVE_ISOCHRONOUS
#define AUDIO_RX_ENDPOINT 7 #define AUDIO_RX_ENDPOINT 7
#define AUDIO_RX_SIZE 180 #define AUDIO_RX_SIZE 180
#define AUDIO_SYNC_ENDPOINT 8 #define AUDIO_SYNC_ENDPOINT 8
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_RECEIVE_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 ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS #define ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS
#define ENDPOINT7_CONFIG ENDPOINT_RECEIVE_ISOCHRONOUS #define ENDPOINT7_CONFIG ENDPOINT_RECEIVE_ISOCHRONOUS
#define MULTITOUCH_ENDPOINT 15 #define MULTITOUCH_ENDPOINT 15
#define MULTITOUCH_SIZE 8 #define MULTITOUCH_SIZE 8
#define MULTITOUCH_FINGERS 10 #define MULTITOUCH_FINGERS 10
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT1_CONFIG ENDPOINT_TRANSMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE #define ENDPOINT2_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE
#define ENDPOINT3_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 ENDPOINT6_CONFIG ENDPOINT_TRANSMIT_AND_RECEIVE
#define ENDPOINT7_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 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 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 ENDPOINT13_CONFIG (ENDPOINT_RECEIVE_ISOCHRONOUS|ENDPOINT_TRANSMIT_ISOCHRONOUS)
#define ENDPOINT14_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS #define ENDPOINT14_CONFIG ENDPOINT_TRANSMIT_ISOCHRONOUS
#define ENDPOINT15_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT15_CONFIG ENDPOINT_TRANSMIT_ONLY


#endif #endif



+ 77
- 15
teensy3/usb_dev.c View File

#include "usb_mem.h" #include "usb_mem.h"
#include <string.h> // for memset #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 // buffer descriptor table


typedef struct { typedef struct {
//serial_print("desc: not found\n"); //serial_print("desc: not found\n");
endpoint0_stall(); endpoint0_stall();
return; return;
#if defined(CDC_STATUS_INTERFACE)
case 0x2221: // CDC_SET_CONTROL_LINE_STATE 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"); //serial_print("set control line state\n");
break; break;
#ifdef CDC_STATUS_INTERFACE
case 0x2321: // CDC_SEND_BREAK case 0x2321: // CDC_SEND_BREAK
break; break;
case 0x2021: // CDC_SET_LINE_CODING case 0x2021: // CDC_SET_LINE_CODING
case 0x01: // OUT transaction received from host case 0x01: // OUT transaction received from host
case 0x02: case 0x02:
//serial_print("PID=OUT\n"); //serial_print("PID=OUT\n");
#ifdef CDC_STATUS_INTERFACE
if (setup.wRequestAndType == 0x2021 /*CDC_SET_LINE_CODING*/) { if (setup.wRequestAndType == 0x2021 /*CDC_SET_LINE_CODING*/) {
int i; 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); endpoint0_transmit(NULL, 0);
} }
#endif
#ifdef KEYBOARD_INTERFACE #ifdef KEYBOARD_INTERFACE
if (setup.word1 == 0x02000921 && setup.word2 == ((1<<16)|KEYBOARD_INTERFACE)) { if (setup.word1 == 0x02000921 && setup.word2 == ((1<<16)|KEYBOARD_INTERFACE)) {
keyboard_leds = buf[0]; keyboard_leds = buf[0];
return usb_queue_byte_count(tx_first[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) uint32_t usb_tx_packet_count(uint32_t endpoint)
{ {
const usb_packet_t *p; const usb_packet_t *p;
{ {
// TODO: initialize R0 with a code.... // TODO: initialize R0 with a code....
__asm__ volatile("bkpt"); __asm__ volatile("bkpt");
__builtin_unreachable();
} }




if (t == 0) usb_serial_flush_callback(); if (t == 0) usb_serial_flush_callback();
} }
#endif #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 #ifdef SEREMU_INTERFACE
t = usb_seremu_transmit_flush_timer; t = usb_seremu_transmit_flush_timer;
if (t) { if (t) {


usb_init_serialnumber(); 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].desc = 0;
table[i].addr = 0; table[i].addr = 0;
} }
#ifdef HAS_KINETIS_MPU #ifdef HAS_KINETIS_MPU
MPU_RGDAAC0 |= 0x03000000; MPU_RGDAAC0 |= 0x03000000;
#endif #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 // 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_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 | USB0_CLK_RECOVER_CTRL = USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN |

+ 12
- 9
teensy3/usb_dev.h View File

return usb_rx_byte_count_data[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 #ifdef SEREMU_INTERFACE
extern volatile uint8_t usb_seremu_transmit_flush_timer; extern volatile uint8_t usb_seremu_transmit_flush_timer;
extern void usb_seremu_flush_callback(void); extern void usb_seremu_flush_callback(void);
} }
#endif #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 #else // F_CPU < 20000000


#ifdef __cplusplus #ifdef __cplusplus

+ 172
- 0
teensy3/usb_flightsim.cpp View File

FlightSimInteger * FlightSimInteger::last = NULL; FlightSimInteger * FlightSimInteger::last = NULL;
FlightSimFloat * FlightSimFloat::first = NULL; FlightSimFloat * FlightSimFloat::first = NULL;
FlightSimFloat * FlightSimFloat::last = 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::enabled = 0;
uint8_t FlightSimClass::request_id_messages = 0; uint8_t FlightSimClass::request_id_messages = 0;
FlightSimClass::xmit(buf, 4, NULL, 0); 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() FlightSimInteger::FlightSimInteger()
{ {
data.b[2] = p[8]; data.b[2] = p[8];
data.b[3] = p[9]; data.b[3] = p[9];
item->update(data.f); 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; break;
case 0x03: // enable/disable case 0x03: // enable/disable
for (FlightSimCommand *p = FlightSimCommand::first; p; p = p->next) { for (FlightSimCommand *p = FlightSimCommand::first; p; p = p->next) {
p->identify(); 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) { for (FlightSimInteger *p = FlightSimInteger::first; p; p = p->next) {
p->identify(); p->identify();
// TODO: send any dirty data // TODO: send any dirty data

+ 99
- 0
teensy3/usb_flightsim.h View File

friend class FlightSimCommand; friend class FlightSimCommand;
friend class FlightSimInteger; friend class FlightSimInteger;
friend class FlightSimFloat; friend class FlightSimFloat;
/// JB
friend class FlightSimEvent;
friend class FlightSimData;
/// JB End
}; };




friend class FlightSimClass; 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 class FlightSimInteger
{ {

+ 15
- 5
teensy3/usb_inst.cpp View File

* SOFTWARE. * SOFTWARE.
*/ */


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


#if F_CPU >= 20000000 #if F_CPU >= 20000000
#endif #endif
#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 #ifdef MIDI_INTERFACE
usb_midi_class usbMIDI; usb_midi_class usbMIDI;
#endif #endif


#else // F_CPU < 20 MHz #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; usb_serial_class Serial;
#elif (USB_DISABLED) #elif (USB_DISABLED)
usb_serial_class Serial; usb_serial_class Serial;
#endif #endif


#endif // F_CPU #endif // F_CPU

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

+ 3
- 2
teensy3/usb_joystick.c View File



// When the PC isn't listening, how long do we wait before discarding data? // When the PC isn't listening, how long do we wait before discarding data?
#define TX_TIMEOUT_MSEC 30 #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) #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1600)
#elif F_CPU == 216000000 #elif F_CPU == 216000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440) #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440)

+ 3
- 2
teensy3/usb_keyboard.c View File



// When the PC isn't listening, how long do we wait before discarding data? // When the PC isn't listening, how long do we wait before discarding data?
#define TX_TIMEOUT_MSEC 50 #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) #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1600)
#elif F_CPU == 216000000 #elif F_CPU == 216000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440) #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440)

+ 2
- 0
teensy3/usb_keyboard.h View File

void set_key4(uint8_t c) { keyboard_keys[3] = c; } void set_key4(uint8_t c) { keyboard_keys[3] = c; }
void set_key5(uint8_t c) { keyboard_keys[4] = c; } void set_key5(uint8_t c) { keyboard_keys[4] = c; }
void set_key6(uint8_t c) { keyboard_keys[5] = c; } void set_key6(uint8_t c) { keyboard_keys[5] = c; }
#ifdef KEYMEDIA_INTERFACE
void set_media(uint16_t c) { void set_media(uint16_t c) {
if (c == 0) { if (c == 0) {
usb_keymedia_release_all(); usb_keymedia_release_all();
press(c); press(c);
} }
} }
#endif
void send_now(void) { usb_keyboard_send(); } void send_now(void) { usb_keyboard_send(); }
void press(uint16_t n) { usb_keyboard_press_keycode(n); } void press(uint16_t n) { usb_keyboard_press_keycode(n); }
void release(uint16_t n) { usb_keyboard_release_keycode(n); } void release(uint16_t n) { usb_keyboard_release_keycode(n); }

+ 12
- 4
teensy3/usb_midi.c View File



// When the PC isn't listening, how long do we wait before discarding data? // When the PC isn't listening, how long do we wait before discarding data?
#define TX_TIMEOUT_MSEC 40 #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) #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1600)
#elif F_CPU == 216000000 #elif F_CPU == 216000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440) #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440)
#endif #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) void usb_midi_write_packed(uint32_t n)
{ {
uint32_t index, wait_count=0; uint32_t index, wait_count=0;
} else { } else {
tx_packet->len = MIDI_TX_SIZE; tx_packet->len = MIDI_TX_SIZE;
usb_tx(MIDI_TX_ENDPOINT, tx_packet); usb_tx(MIDI_TX_ENDPOINT, tx_packet);
tx_packet = usb_malloc();
tx_packet = NULL;
} }
tx_noautoflush = 0; tx_noautoflush = 0;
} }
if (tx_noautoflush == 0 && tx_packet && tx_packet->index > 0) { if (tx_noautoflush == 0 && tx_packet && tx_packet->index > 0) {
tx_packet->len = tx_packet->index * 4; tx_packet->len = tx_packet->index * 4;
usb_tx(MIDI_TX_ENDPOINT, tx_packet); usb_tx(MIDI_TX_ENDPOINT, tx_packet);
tx_packet = usb_malloc();
tx_packet = NULL;
} }
} }



+ 3
- 2
teensy3/usb_mouse.c View File



// When the PC isn't listening, how long do we wait before discarding data? // When the PC isn't listening, how long do we wait before discarding data?
#define TX_TIMEOUT_MSEC 30 #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) #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1600)
#elif F_CPU == 216000000 #elif F_CPU == 216000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440) #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440)

+ 3
- 2
teensy3/usb_seremu.c View File

// too short, we risk losing data during the stalls that are common with ordinary desktop // 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. // software. If it's too long, we stall the user's program when no software is running.
#define TX_TIMEOUT_MSEC 30 #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) #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1600)
#elif F_CPU == 216000000 #elif F_CPU == 216000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440) #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440)

+ 3
- 2
teensy3/usb_serial.c View File

// too short, we risk losing data during the stalls that are common with ordinary desktop // 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. // software. If it's too long, we stall the user's program when no software is running.
#define TX_TIMEOUT_MSEC 70 #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) #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1600)
#elif F_CPU == 216000000 #elif F_CPU == 216000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440) #define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440)

+ 5
- 3
teensy3/usb_serial.h View File



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


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

// C language implementation // C language implementation
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
int usb_serial_write(const void *buffer, uint32_t size); int usb_serial_write(const void *buffer, uint32_t size);
int usb_serial_write_buffer_free(void); int usb_serial_write_buffer_free(void);
void usb_serial_flush_output(void); void usb_serial_flush_output(void);
void usb_serial_flush_callback(void);
extern uint32_t usb_cdc_line_coding[2]; extern uint32_t usb_cdc_line_coding[2];
extern volatile uint32_t usb_cdc_line_rtsdtr_millis; extern volatile uint32_t usb_cdc_line_rtsdtr_millis;
extern volatile uint32_t systick_millis_count; extern volatile uint32_t systick_millis_count;
uint8_t numbits(void) { return usb_cdc_line_coding[1] >> 16; } 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 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; } 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 readBytes(char *buffer, size_t length) {
size_t count=0; size_t count=0;

+ 306
- 0
teensy3/usb_serial2.c View File

/* 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 View File

/* 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 View File

/* 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 View File

/* 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 View File

// 5: Y msb // 5: Y msb
// 6: scan time lsb // 6: scan time lsb
// 7: scan time msb // 7: scan time msb
// 8: contact count


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

if (scan_index == 0) { if (scan_index == 0) {
if (usb_tx_packet_count(MULTITOUCH_ENDPOINT) > 1) { if (usb_tx_packet_count(MULTITOUCH_ENDPOINT) > 1) {
// wait to begin another scan if if more than // wait to begin another scan if if more than
} }
scan_timestamp = millis() * 10; scan_timestamp = millis() * 10;
scan_count = 0; 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) { while (scan_index < MULTITOUCH_FINGERS) {
uint32_t press = pressure[scan_index]; uint32_t press = pressure[scan_index];
uint32_t id = contactid[scan_index]; uint32_t id = contactid[scan_index];
*(tx_packet->buf + 5) = ypos[scan_index] >> 8; *(tx_packet->buf + 5) = ypos[scan_index] >> 8;
*(tx_packet->buf + 6) = scan_timestamp; *(tx_packet->buf + 6) = scan_timestamp;
*(tx_packet->buf + 7) = scan_timestamp >> 8; *(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); usb_tx(MULTITOUCH_ENDPOINT, tx_packet);
scan_index++; scan_index++;
return; return;

+ 50
- 2
teensy3/usb_undef.h View File

#ifdef ENDPOINT_UNUSED #ifdef ENDPOINT_UNUSED
#undef ENDPOINT_UNUSED #undef ENDPOINT_UNUSED
#endif #endif
#ifdef ENDPOINT_TRANSIMIT_ONLY
#undef ENDPOINT_TRANSIMIT_ONLY
#ifdef ENDPOINT_TRANSMIT_ONLY
#undef ENDPOINT_TRANSMIT_ONLY
#endif #endif
#ifdef ENDPOINT_RECEIVE_ONLY #ifdef ENDPOINT_RECEIVE_ONLY
#undef ENDPOINT_RECEIVE_ONLY #undef ENDPOINT_RECEIVE_ONLY
#ifdef CDC_TX_SIZE #ifdef CDC_TX_SIZE
#undef CDC_TX_SIZE #undef CDC_TX_SIZE
#endif #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 #ifdef SEREMU_INTERFACE
#undef SEREMU_INTERFACE #undef SEREMU_INTERFACE
#endif #endif

+ 25
- 6
teensy3/wiring.h View File



#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include "binary.h" #include "binary.h"
#include "core_id.h" #include "core_id.h"
#include "core_pins.h" #include "core_pins.h"
{ {
long x = _x, in_min = _in_min, in_max = _in_max, out_min = _out_min, out_max = _out_max; long x = _x, in_min = _in_min, in_max = _in_max, out_min = _out_min, out_max = _out_max;
// Arduino's traditional algorithm // 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 // 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)) { 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; return (x - in_min) * (out_max - out_min+1) / (in_max - in_min+1) + out_min;
} else { } else {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; 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 // 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> template <class T, class A, class B, class C, class D>
{ {
return (x - (T)in_min) * ((T)out_max - (T)out_min) / ((T)in_max - (T)in_min) + (T)out_min; 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> #include <utility>
// https://forum.pjrc.com/threads/44596-Teensyduino-1-37-Beta-2-(Arduino-1-8-3-support)?p=145150&viewfull=1#post145150 // 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> template<class A, class B>
typedef bool boolean; typedef bool boolean;
#else #else
typedef uint8_t boolean; typedef uint8_t boolean;
#define false 0
#define true (!false)
#endif #endif


#endif #endif

+ 41
- 17
teensy3/yield.cpp View File

* SOFTWARE. * SOFTWARE.
*/ */


#include "core_pins.h"
#include "HardwareSerial.h"
#include "usb_serial.h"
#include "usb_seremu.h"
#include <Arduino.h>
#include "EventResponder.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) __attribute__ ((weak));
void yield(void) void yield(void)
{ {
static uint8_t running=0; static uint8_t running=0;

if (!yield_active_check_flags) return; // nothing to do
if (running) return; // TODO: does this need to be atomic? if (running) return; // TODO: does this need to be atomic?
running = 1; 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 #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 #endif
if (yield_active_check_flags & YIELD_CHECK_HARDWARE_SERIAL) {
HardwareSerial::processSerialEventsList();
}
running = 0; running = 0;
EventResponder::runFromYield();
if (yield_active_check_flags & YIELD_CHECK_EVENT_RESPONDER) EventResponder::runFromYield();
}; };

+ 9
- 0
teensy4/Arduino.h View File

// 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 View File

/* 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 View File


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save