Browse Source

Merge branch 'master' of https://github.com/PaulStoffregen/cores

teensy4-core
Jorg Neves Bliesener 4 years ago
parent
commit
dcd73bc59f
100 changed files with 8021 additions and 1371 deletions
  1. +27
    -0
      .github/ISSUE_TEMPLATE.md
  2. +1
    -1
      README.md
  3. +131
    -11
      keywords.txt
  4. +1
    -0
      teensy/Keyboard.h
  5. +53
    -0
      teensy/MIDIUSB.h
  6. +1
    -0
      teensy/Mouse.h
  7. +10
    -63
      teensy/Print.h
  8. +4
    -4
      teensy/Stream.cpp
  9. +8
    -8
      teensy/Stream.h
  10. +1
    -0
      teensy/Udp.h
  11. +2
    -1
      teensy/core_pins.h
  12. +4
    -3
      teensy/keylayouts.h
  13. +1
    -1
      teensy/malloc.c
  14. +2
    -0
      teensy/pgmspace.h
  15. +6
    -0
      teensy/pins_arduino.h
  16. +3
    -5
      teensy/wiring.h
  17. +7
    -0
      teensy3/Arduino.h
  18. +122
    -25
      teensy3/AudioStream.cpp
  19. +49
    -17
      teensy3/AudioStream.h
  20. +19
    -0
      teensy3/Client.h
  21. +48
    -13
      teensy3/DMAChannel.cpp
  22. +41
    -9
      teensy3/DMAChannel.h
  23. +344
    -0
      teensy3/EventResponder.cpp
  24. +274
    -0
      teensy3/EventResponder.h
  25. +72
    -0
      teensy3/FS.h
  26. +210
    -6
      teensy3/HardwareSerial.h
  27. +31
    -0
      teensy3/HardwareSerial1.cpp
  28. +31
    -0
      teensy3/HardwareSerial2.cpp
  29. +31
    -0
      teensy3/HardwareSerial3.cpp
  30. +41
    -0
      teensy3/HardwareSerial4.cpp
  31. +41
    -0
      teensy3/HardwareSerial5.cpp
  32. +41
    -0
      teensy3/HardwareSerial6.cpp
  33. +20
    -1
      teensy3/IPAddress.cpp
  34. +116
    -175
      teensy3/IntervalTimer.cpp
  35. +128
    -95
      teensy3/IntervalTimer.h
  36. +3
    -0
      teensy3/Keyboard.h
  37. +56
    -0
      teensy3/MIDIUSB.h
  38. +44
    -8
      teensy3/Makefile
  39. +3
    -0
      teensy3/Mouse.h
  40. +41
    -29
      teensy3/Print.cpp
  41. +10
    -3
      teensy3/Print.h
  42. +111
    -2
      teensy3/SPIFIFO.h
  43. +21
    -0
      teensy3/Server.h
  44. +18
    -38
      teensy3/Stream.cpp
  45. +18
    -11
      teensy3/Stream.h
  46. +5
    -7
      teensy3/Tone.cpp
  47. +1
    -0
      teensy3/Udp.h
  48. +3
    -3
      teensy3/WCharacter.h
  49. +2
    -0
      teensy3/WConstants.h
  50. +23
    -7
      teensy3/WMath.cpp
  51. +33
    -4
      teensy3/WProgram.h
  52. +15
    -4
      teensy3/WString.cpp
  53. +11
    -0
      teensy3/WString.h
  54. +142
    -110
      teensy3/analog.c
  55. +3
    -0
      teensy3/avr/eeprom.h
  56. +1
    -0
      teensy3/avr/interrupt.h
  57. +38
    -0
      teensy3/avr/pgmspace.h
  58. +2
    -2
      teensy3/avr/sleep.h
  59. +2
    -0
      teensy3/avr/wdt.h
  60. +12
    -5
      teensy3/avr_emulation.cpp
  61. +771
    -47
      teensy3/avr_emulation.h
  62. +1
    -1
      teensy3/avr_functions.h
  63. +2
    -0
      teensy3/binary.h
  64. +2
    -0
      teensy3/core_id.h
  65. +508
    -14
      teensy3/core_pins.h
  66. +84
    -13
      teensy3/eeprom.c
  67. +1
    -1
      teensy3/elapsedMillis.h
  68. +1
    -1
      teensy3/keylayouts.c
  69. +5
    -4
      teensy3/keylayouts.h
  70. +955
    -38
      teensy3/kinetis.h
  71. +31
    -1
      teensy3/main.cpp
  72. +63
    -71
      teensy3/math_helper.c
  73. +7
    -0
      teensy3/memcpy-armv7m.S
  74. +288
    -37
      teensy3/mk20dx128.c
  75. +2
    -0
      teensy3/mk20dx128.h
  76. +4
    -2
      teensy3/mk20dx128.ld
  77. +5
    -3
      teensy3/mk20dx256.ld
  78. +6
    -4
      teensy3/mk64fx512.ld
  79. +5
    -3
      teensy3/mk66fx1m0.ld
  80. +5
    -3
      teensy3/mkl26z64.ld
  81. +35
    -0
      teensy3/new.cpp
  82. +28
    -1
      teensy3/new.h
  83. +107
    -10
      teensy3/nonstd.c
  84. +2
    -0
      teensy3/pgmspace.h
  85. +121
    -45
      teensy3/pins_arduino.h
  86. +353
    -223
      teensy3/pins_teensy.c
  87. +30
    -0
      teensy3/ser_print.c
  88. +29
    -0
      teensy3/ser_print.h
  89. +99
    -30
      teensy3/serial1.c
  90. +26
    -22
      teensy3/serial1_doughboy.txt
  91. +106
    -40
      teensy3/serial2.c
  92. +63
    -27
      teensy3/serial3.c
  93. +403
    -0
      teensy3/serial4.c
  94. +381
    -0
      teensy3/serial5.c
  95. +381
    -0
      teensy3/serial6.c
  96. +463
    -0
      teensy3/serial6_lpuart.c
  97. +14
    -10
      teensy3/touch.c
  98. +61
    -21
      teensy3/usb_audio.cpp
  99. +34
    -28
      teensy3/usb_audio.h
  100. +0
    -0
      teensy3/usb_desc.c

+ 27
- 0
.github/ISSUE_TEMPLATE.md View File

@@ -0,0 +1,27 @@
Please use this Github issue *only for reporting a specific problem*.

Please **do not use Github issues for project troubleshooting.** Post on the PJRC Forum for Teensy-related troubleshooting.

https://forum.pjrc.com/forum.php

General suggestions for new features should also be discussed on the forum. Github issues for new features are usually only appropriate after decisions are made via forum discussion.

Also check out the most common troubleshooting page:

https://www.pjrc.com/teensy/troubleshoot.html

Before reporting any issue, please make sure you are using the latest Teensyduino version.

https://www.pjrc.com/teensy/td_download.html

If a beta test version is available, please check whether it fixes the issue.

When reporting any issue, please try to provide complete information. The following are almost always needed:

- A complete copy of the code (which can be copied into Arduino and run on a Teensy board) which reproduces the problem is usually needed to investigate any issue. Please try to trim your program to the minimum necessary, ideally not depending on extra hardware if possible. But a complete program that can be copied into Arduino without guesswork is essential. Please do not submit this Github issue with only code fragments or a vague description of code to recreate the issue.

- Which Teensy board(s) are you using.

- If other hardware is needed to reproduce the issue, please provide links or part numbers where this hardware can be purchased. Very specific details showing how the hardware is connected also help. Post photos if needed.

- Which version of Teensyduino and Arduino were used, what Tools menu settings were chosen, and which operating system was used. If other software is needed, please be specific.

+ 1
- 1
README.md View File

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

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


+ 131
- 11
keywords.txt View File

@@ -1,10 +1,17 @@

# language keywords - Arduino doesn't define these, but probably should
volatile LITERAL2
volatile LITERAL1
constexpr LITERAL1
alignas LITERAL1
alignof LITERAL1
nullptr LITERAL1
noexcept LITERAL1
static_assert LITERAL1
thread_local LITERAL1

# teensy specific functions
elapsedMillis LITERAL2
elapsedMicros LITERAL2
elapsedMillis LITERAL1
elapsedMicros LITERAL1
readString KEYWORD2
readStringUntil KEYWORD2
analogReadRes KEYWORD2
@@ -22,12 +29,33 @@ digitalReadFast KEYWORD2
transmitterEnable KEYWORD2
attachRts KEYWORD2
attachCts KEYWORD2
PROGMEM LITERAL2
DMAMEM LITERAL2
FASTRUN LITERAL2
PROGMEM LITERAL1
FLASHMEM LITERAL1
DMAMEM LITERAL1
FASTRUN LITERAL1
Serial4 KEYWORD1
Serial5 KEYWORD1
Serial6 KEYWORD1
Serial7 KEYWORD1
setRX KEYWORD2
setTX KEYWORD2
write9bit KEYWORD2
clear KEYWORD2
EventResponder LITERAL1
EventResponderRef LITERAL1
attachImmediate KEYWORD2
triggerEvent KEYWORD2
clearEvent KEYWORD2
getStatus KEYWORD2
getData KEYWORD2
setContext KEYWORD2
getContext KEYWORD2
waitForEvent KEYWORD2
MillisTimer LITERAL1
beginRepeating KEYWORD2

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

# Arduino constants
A0 LITERAL1
@@ -53,6 +81,10 @@ A19 LITERAL1
A20 LITERAL1
A21 LITERAL1
A22 LITERAL1
A23 LITERAL1
A24 LITERAL1
A25 LITERAL1
A26 LITERAL1
SS LITERAL1
MOSI LITERAL1
MISO LITERAL1
@@ -66,10 +98,57 @@ digitalPinHasPWM KEYWORD2
NOT_AN_INTERRUPT LITERAL1
digitalPinToInterrupt KEYWORD2

# HardwareSerial modes
SERIAL_7E1 LITERAL1
SERIAL_7O1 LITERAL1
SERIAL_8N1 LITERAL1
SERIAL_8E1 LITERAL1
SERIAL_8O1 LITERAL1
SERIAL_7E1_RXINV LITERAL1
SERIAL_7O1_RXINV LITERAL1
SERIAL_8N1_RXINV LITERAL1
SERIAL_8E1_RXINV LITERAL1
SERIAL_8O1_RXINV LITERAL1
SERIAL_7E1_TXINV LITERAL1
SERIAL_7O1_TXINV LITERAL1
SERIAL_8N1_TXINV LITERAL1
SERIAL_8E1_TXINV LITERAL1
SERIAL_8O1_TXINV LITERAL1
SERIAL_7E1_RXINV_TXINV LITERAL1
SERIAL_7O1_RXINV_TXINV LITERAL1
SERIAL_8N1_RXINV_TXINV LITERAL1
SERIAL_8E1_RXINV_TXINV LITERAL1
SERIAL_8O1_RXINV_TXINV LITERAL1
SERIAL_8E2 LITERAL1
SERIAL_8O2 LITERAL1
SERIAL_8E2_RXINV LITERAL1
SERIAL_8O2_RXINV LITERAL1
SERIAL_8E2_TXINV LITERAL1
SERIAL_8O2_TXINV LITERAL1
SERIAL_8E2_RXINV_TXINV LITERAL1
SERIAL_8O2_RXINV_TXINV LITERAL1
SERIAL_8N2 LITERAL1
SERIAL_8N2_RXINV LITERAL1
SERIAL_8N2_TXINV LITERAL1
SERIAL_8N2_RXINV_TXINV LITERAL1
SERIAL_9N1 LITERAL1
SERIAL_9E1 LITERAL1
SERIAL_9O1 LITERAL1
SERIAL_9N1_RXINV LITERAL1
SERIAL_9E1_RXINV LITERAL1
SERIAL_9O1_RXINV LITERAL1
SERIAL_9N1_TXINV LITERAL1
SERIAL_9E1_TXINV LITERAL1
SERIAL_9O1_TXINV LITERAL1
SERIAL_9N1_RXINV_TXINV LITERAL1
SERIAL_9E1_RXINV_TXINV LITERAL1
SERIAL_9O1_RXINV_TXINV LITERAL1

# Teensy 3.x advanced pin states
OUTPUT_OPENDRAIN LITERAL1
INPUT_PULLUP LITERAL1
INPUT_PULLDOWN LITERAL1
INPUT_PULLUP LITERAL1
INPUT_PULLDOWN LITERAL1
INPUT_DISABLE LITERAL1

# String functions
copy KEYWORD2
@@ -195,6 +274,15 @@ KEY_MEDIA_NEXT_TRACK LITERAL1
KEY_MEDIA_PREV_TRACK LITERAL1
KEY_MEDIA_STOP LITERAL1
KEY_MEDIA_EJECT LITERAL1
KEY_MEDIA_PLAY LITERAL1
KEY_MEDIA_PAUSE LITERAL1
KEY_MEDIA_RECORD LITERAL1
KEY_MEDIA_REWIND LITERAL1
KEY_MEDIA_FAST_FORWARD LITERAL1
KEY_MEDIA_PLAY_SKIP LITERAL1
KEY_SYSTEM_POWER_DOWN LITERAL1
KEY_SYSTEM_SLEEP LITERAL1
KEY_SYSTEM_WAKE_UP LITERAL1
KEY_A LITERAL1
KEY_B LITERAL1
KEY_C LITERAL1
@@ -345,14 +433,34 @@ releaseReadOnly KEYWORD2
usbMIDI KEYWORD1
sendNoteOff KEYWORD2
sendNoteOn KEYWORD2
sendAfterTouchPoly KEYWORD2
sendPolyPressure KEYWORD2
sendControlChange KEYWORD2
sendProgramChange KEYWORD2
sendAfterTouch KEYWORD2
sendPitchBend KEYWORD2
sendSysEx KEYWORD2
sendRealTime KEYWORD2
sendTimeCodeQuarterFrame KEYWORD2
sendSongPosition KEYWORD2
sendSongSelect KEYWORD2
sendTuneRequest KEYWORD2
beginRpn KEYWORD2
sendRpnValue KEYWORD2
sendRpnValue KEYWORD2
sendRpnIncrement KEYWORD2
sendRpnDecrement KEYWORD2
endRpn KEYWORD2
beginNrpn KEYWORD2
sendNrpnValue KEYWORD2
sendNrpnValue KEYWORD2
sendNrpnIncrement KEYWORD2
sendNrpnDecrement KEYWORD2
endNrpn KEYWORD2
send KEYWORD2
analog2velocity KEYWORD2
getType KEYWORD2
getCable KEYWORD2
getChannel KEYWORD2
getData1 KEYWORD2
getData2 KEYWORD2
@@ -364,7 +472,6 @@ setHandleControlChange KEYWORD2
setHandleProgramChange KEYWORD2
setHandleAfterTouch KEYWORD2
setHandlePitchChange KEYWORD2
setHandlePitchChange KEYWORD2
NoteOff LITERAL1
NoteOn LITERAL1
AfterTouchPoly LITERAL1
@@ -373,6 +480,19 @@ ProgramChange LITERAL1
AfterTouchChannel LITERAL1
PitchBend LITERAL1
SystemExclusive LITERAL1
TimeCodeQuarterFrame LITERAL1
SongPosition LITERAL1
SongSelect LITERAL1
TuneRequest LITERAL1
Clock LITERAL1
Start LITERAL1
Continue LITERAL1
Stop LITERAL1
ActiveSensing LITERAL1
SystemReset LITERAL1
midiEventPacket_t LITERAL1
MidiUSB KEYWORD1
sendMIDI KEYWORD2

# USB RawHID
RawHID KEYWORD1

+ 1
- 0
teensy/Keyboard.h View File

@@ -0,0 +1 @@
// empty Keyboard.h file, for compability with Arduino's Keyboard examples

+ 53
- 0
teensy/MIDIUSB.h View File

@@ -0,0 +1,53 @@
#ifndef MIDIUSB_h
#define MIDIUSB_h

// For compatibility with Arduino's MIDIUSB library

#ifdef __cplusplus
#if !defined(USB_MIDI)
#error "Please select MIDI in Tools > USB Type to use MIDIUSB.h"
#endif

#include "usb_api.h"

typedef struct {
struct {
uint8_t header;
uint8_t byte1;
uint8_t byte2;
uint8_t byte3;
};
} midiEventPacket_t;


class MIDI_
{
public:
constexpr MIDI_(void) { }
uint32_t available(void) {
return usbMIDI.midiusb_available();
}
midiEventPacket_t read(void) {
midiEventPacket_t event;
usbMIDI.midiusb_read((uint8_t *)&event);
return event;
}
void flush(void) {
usbMIDI.send_now();
}
void sendMIDI(midiEventPacket_t event) {
usbMIDI.send_raw(event.header, event.byte1, event.byte2, event.byte3);
}
size_t write(const uint8_t *buffer, size_t size) {
// TODO - is this really needed?
return 0;
}
operator bool() {
// TODO - is this really needed?
return true;
}
};
extern MIDI_ MidiUSB;

#endif // __cplusplus
#endif // MIDIUSB_h

+ 1
- 0
teensy/Mouse.h View File

@@ -0,0 +1 @@
// empty Mouse.h file, for compability with Arduino's Mouse examples

+ 10
- 63
teensy/Print.h View File

@@ -31,18 +31,24 @@
#define HEX 16
#define OCT 8
#define BIN 2
#define BYTE 0

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

class __FlashStringHelper;

#if ARDUINO >= 100
class Print
{
public:
Print() : write_error(0) {}
virtual size_t write(uint8_t b);
constexpr Print() : write_error(0) {}
virtual size_t write(uint8_t b) = 0;
size_t write(const char *str) { return write((const uint8_t *)str, strlen(str)); }
virtual size_t write(const uint8_t *buffer, size_t size);
virtual int availableForWrite(void) { return 0; }
virtual void flush() { }
size_t write(const char *buffer, size_t size) { return write((const uint8_t *)buffer, size); }
size_t print(const String &s);
size_t print(char c) { return write((uint8_t)c); }
@@ -108,64 +114,5 @@ class Print
size_t printFloat(double n, uint8_t digits);
};

#else
class Print
{
public:
virtual void write(uint8_t);
virtual void write(const char *str);
virtual void write(const uint8_t *buffer, size_t size);
void print(const String &s);
void print(char c) { write((uint8_t)c); }
void print(const char s[]) { write(s); }
void print(const __FlashStringHelper *f);

void print(uint8_t b) { write(b); }
void print(int n) { print((long)n); }
void print(unsigned int n) { printNumber(n, 0, 10); }
void print(long n);
void print(unsigned long n) { printNumber(n, 0, 10); }

void print(unsigned char n, int base) { printNumber(n, 0, base); }
void print(int n, int base) { (base == 10) ? print(n) : printNumber(n, 0, base); }
void print(unsigned int n, int base) { printNumber(n, 0, base); }
void print(long n, int base) { (base == 10) ? print(n) : printNumber(n, 0, base); }
void print(unsigned long n, int base) { printNumber(n, 0, base); }

void print(double n, int digits = 2) { printFloat(n, digits); }
void println(void);
void println(const String &s) { print(s); println(); }
void println(char c) { print(c); println(); }
void println(const char s[]) { print(s); println(); }
void println(const __FlashStringHelper *f) { print(f); println(); }
void println(uint8_t b) { print(b); println(); }
void println(int n) { print(n); println(); }
void println(unsigned int n) { print(n); println(); }
void println(long n) { print(n); println(); }
void println(unsigned long n) { print(n); println(); }

void println(unsigned char n, int base) { print(n, base); println(); }
void println(int n, int base) { print(n, base); println(); }
void println(unsigned int n, int base) { print(n, base); println(); }
void println(long n, int base) { print(n, base); println(); }
void println(unsigned long n, int base) { print(n, base); println(); }

void println(double n, int digits = 2) { print(n, digits); println(); }
private:
void printNumberDec(unsigned long n, uint8_t sign);
void printNumberHex(unsigned long n);
void printNumberBin(unsigned long n);
void printNumberAny(unsigned long n, uint8_t base);
inline size_t printNumber(unsigned long n, uint8_t sign, uint8_t base) __attribute__((always_inline)) {
if (base == 0) { write((uint8_t)n); return; }
if (base == 10 || base < 2) { printNumberDec(n, sign); return; }
if (base == 16) { printNumberHex(n); return; }
if (base == 2) { printNumberBin(n); return; }
printNumberAny(n, base);
}
void printFloat(double n, uint8_t digits);
};
#endif


#endif

+ 4
- 4
teensy/Stream.cpp View File

@@ -73,20 +73,20 @@ void Stream::setTimeout(unsigned long timeout) // sets the maximum number of mi
}

// find returns true if the target string is found
bool Stream::find(char *target)
bool Stream::find(const char *target)
{
return findUntil(target, NULL);
}

// reads data from the stream until the target string of given length is found
// returns true if target string is found, false if timed out
bool Stream::find(char *target, size_t length)
bool Stream::find(const char *target, size_t length)
{
return findUntil(target, length, NULL, 0);
}

// as find but search ends if the terminator string is found
bool Stream::findUntil(char *target, char *terminator)
bool Stream::findUntil(const char *target, char *terminator)
{
return findUntil(target, strlen(target), terminator, strlen(terminator));
}
@@ -94,7 +94,7 @@ bool Stream::findUntil(char *target, char *terminator)
// reads data from the stream until the target string of the given length is found
// search terminated if the terminator string is found
// returns true if target string is found, false if terminated or timed out
bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen)
bool Stream::findUntil(const char *target, size_t targetLen, char *terminator, size_t termLen)
{
size_t index = 0; // maximum target string length is 64k bytes!
size_t termIndex = 0;

+ 8
- 8
teensy/Stream.h View File

@@ -33,14 +33,14 @@ class Stream : public Print
virtual void flush() = 0;

void setTimeout(unsigned long timeout);
bool find(char *target);
bool find(uint8_t *target) { return find ((char *)target); }
bool find(char *target, size_t length);
bool find(uint8_t *target, size_t length) { return find ((char *)target, length); }
bool findUntil(char *target, char *terminator);
bool findUntil(uint8_t *target, char *terminator) { return findUntil((char *)target, terminator); }
bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen);
bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); }
bool find(const char *target);
bool find(const uint8_t *target) { return find ((const char *)target); }
bool find(const char *target, size_t length);
bool find(const uint8_t *target, size_t length) { return find ((const char *)target, length); }
bool findUntil(const char *target, char *terminator);
bool findUntil(const uint8_t *target, char *terminator) { return findUntil((const char *)target, terminator); }
bool findUntil(const char *target, size_t targetLen, char *terminate, size_t termLen);
bool findUntil(const uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((const char *)target, targetLen, terminate, termLen); }
long parseInt();
long parseInt(char skipChar);
float parseFloat();

+ 1
- 0
teensy/Udp.h View File

@@ -44,6 +44,7 @@ class UDP : public Stream {

public:
virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
virtual uint8_t beginMulticast(IPAddress, uint16_t) { return 0; }
virtual void stop() =0; // Finish with the UDP socket

// Sending UDP packets

+ 2
- 1
teensy/core_pins.h View File

@@ -2136,7 +2136,8 @@ static inline void delayMicroseconds(uint16_t usec)
uint8_t tmp2 = tmp;
asm volatile(
"L_%=_loop:" // 1 to load
"subi %0, 1" "\n\t" // 2
"subi %0, 1" "\n\t" // 1
"nop" "\n\t" // 1
"brne L_%=_loop" "\n\t" // 2 (1 on last)
: "=d" (tmp2)
: "0" (tmp2)

+ 4
- 3
teensy/keylayouts.h View File

@@ -93,7 +93,7 @@ extern "C"{
#define KEY_MEDIA_PREV_TRACK ( 0xB6 | 0xE400 )
#define KEY_MEDIA_STOP ( 0xB7 | 0xE400 )
#define KEY_MEDIA_EJECT ( 0xB8 | 0xE400 )
#define KEY_MEDIA_RANDOM_PLAY ( 0xB0 | 0xE400 )
#define KEY_MEDIA_RANDOM_PLAY ( 0xB9 | 0xE400 )
#define KEY_MEDIA_PLAY_PAUSE ( 0xCD | 0xE400 )
#define KEY_MEDIA_PLAY_SKIP ( 0xCE | 0xE400 )
#define KEY_MEDIA_MUTE ( 0xE2 | 0xE400 )
@@ -196,6 +196,7 @@ extern "C"{
#define KEYPAD_9 ( 97 | 0xF000 )
#define KEYPAD_0 ( 98 | 0xF000 )
#define KEYPAD_PERIOD ( 99 | 0xF000 )
#define KEY_NON_US_BS ( 100 | 0xF000 )
#define KEY_MENU ( 101 | 0xF000 )
#define KEY_F13 ( 104 | 0xF000 )
#define KEY_F14 ( 105 | 0xF000 )
@@ -1450,7 +1451,7 @@ extern "C"{
#define ASCII_20 KEY_SPACE // 32
#define ASCII_21 KEY_1 + SHIFT_MASK // 33 !
#define ASCII_22 KEY_2 + SHIFT_MASK // 34 "
#define ASCII_23 KEY_BACKSPACE // 35 #
#define ASCII_23 KEY_BACKSLASH // 35 #
#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $
#define ASCII_25 KEY_5 + SHIFT_MASK // 37 %
#define ASCII_26 KEY_7 + SHIFT_MASK // 38 &
@@ -4532,7 +4533,7 @@ extern "C"{
#define ASCII_20 KEY_SPACE // 32
#define ASCII_21 KEY_1 + SHIFT_MASK // 33 !
#define ASCII_22 KEY_2 + SHIFT_MASK // 34 "
#define ASCII_23 KEY_BACKSPACE // 35 #
#define ASCII_23 KEY_BACKSLASH // 35 #
#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $
#define ASCII_25 KEY_5 + SHIFT_MASK // 37 %
#define ASCII_26 KEY_7 + SHIFT_MASK // 38 &

+ 1
- 1
teensy/malloc.c View File

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


+ 2
- 0
teensy/pgmspace.h View File

@@ -0,0 +1,2 @@
// For compatibility with some ESP8266 programs
#include <avr/pgmspace.h>

+ 6
- 0
teensy/pins_arduino.h View File

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

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

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

+ 3
- 5
teensy/wiring.h View File

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

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

#define true 1
#define false 0

#define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398
#define TWO_PI 6.283185307179586476925286766559
@@ -87,13 +85,13 @@ extern "C"{
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet((value), (bit)) : bitClear((value), (bit)))

typedef unsigned int word;

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

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

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

+ 7
- 0
teensy3/Arduino.h View File

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

#ifndef Arduino_h
#define Arduino_h

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

#endif

+ 122
- 25
teensy3/AudioStream.cpp View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -10,10 +10,10 @@
* 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
* 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
* 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.
@@ -29,17 +29,32 @@
*/


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

#if defined(__MKL26Z64__)
#define MAX_AUDIO_MEMORY 6144
#elif defined(__MK20DX128__)
#define MAX_AUDIO_MEMORY 12288
#elif defined(__MK20DX256__)
#define MAX_AUDIO_MEMORY 49152
#elif defined(__MK64FX512__)
#define MAX_AUDIO_MEMORY 163840
#elif defined(__MK66FX1M0__)
#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[6];
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;
uint8_t AudioStream::memory_used = 0;
uint8_t AudioStream::memory_used_max = 0;
uint16_t AudioStream::memory_used = 0;
uint16_t AudioStream::memory_used_max = 0;




@@ -48,13 +63,15 @@ uint8_t AudioStream::memory_used_max = 0;
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 > 192) num = 192;
if (num > maxnum) num = maxnum;
__disable_irq();
memory_pool = data;
for (i=0; i < 6; i++) {
memory_pool_first_mask = 0;
for (i=0; i < NUM_MASKS; i++) {
memory_pool_available_mask[i] = 0;
}
for (i=0; i < num; i++) {
@@ -72,25 +89,31 @@ void AudioStream::initialize_memory(audio_block_t *data, unsigned int num)
audio_block_t * AudioStream::allocate(void)
{
uint32_t n, index, avail;
uint32_t *p;
uint32_t *p, *end;
audio_block_t *block;
uint8_t used;
uint32_t used;

p = memory_pool_available_mask;
end = p + NUM_MASKS;
__disable_irq();
do {
avail = *p; if (avail) break;
p++; avail = *p; if (avail) break;
p++; avail = *p; if (avail) break;
p++; avail = *p; if (avail) break;
p++; avail = *p; if (avail) break;
p++; avail = *p; if (avail) break;
__enable_irq();
//Serial.println("alloc:null");
return NULL;
} while (0);
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);
*p = avail & ~(0x80000000 >> n);
avail &= ~(0x80000000 >> n);
*p = avail;
if (!avail) index++;
memory_pool_first_mask = index;
used = memory_used + 1;
memory_used = used;
__enable_irq();
@@ -108,10 +131,10 @@ audio_block_t * AudioStream::allocate(void)
// 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--;
@@ -119,6 +142,7 @@ void AudioStream::release(audio_block_t *block)
//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();
@@ -179,20 +203,93 @@ 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) p = p->next_dest;
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()

+ 49
- 17
teensy3/AudioStream.h View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -31,29 +31,49 @@
#ifndef AudioStream_h
#define AudioStream_h

#ifndef __ASSEMBLER__
#include <stdio.h> // for NULL
#include <string.h> // for memcpy
#include "kinetis.h"
#endif

// AUDIO_BLOCK_SAMPLES determines how many samples the audio library processes
// per update. It may be reduced to achieve lower latency response to events,
// at the expense of higher interrupt and DMA setup overhead.
//
// Less than 32 may not work with some input & output objects. Multiples of 16
// should be used, since some synthesis objects generate 16 samples per loop.
//
// Some parts of the audio library may have hard-coded dependency on 128 samples.
// Please report these on the forum with reproducible test cases.

#if defined(KINETISK)
#ifndef AUDIO_BLOCK_SAMPLES
#if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
#define AUDIO_BLOCK_SAMPLES 128
#define AUDIO_SAMPLE_RATE 44117.64706
#define AUDIO_SAMPLE_RATE_EXACT 44117.64706 // 48 MHz / 1088, or 96 MHz * 2 / 17 / 256
#elif defined(KINETISL)
#elif defined(__MKL26Z64__)
#define AUDIO_BLOCK_SAMPLES 64
#define AUDIO_SAMPLE_RATE 22058.82353
#endif
#endif

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

#define AUDIO_SAMPLE_RATE AUDIO_SAMPLE_RATE_EXACT

#ifndef __ASSEMBLER__
class AudioStream;
class AudioConnection;

typedef struct audio_block_struct {
unsigned char ref_count;
unsigned char memory_pool_index;
unsigned char reserved1;
unsigned char reserved2;
int16_t data[AUDIO_BLOCK_SAMPLES];
uint8_t ref_count;
uint8_t reserved1;
uint16_t memory_pool_index;
int16_t data[AUDIO_BLOCK_SAMPLES];
} audio_block_t;


@@ -63,21 +83,28 @@ public:
AudioConnection(AudioStream &source, AudioStream &destination) :
src(source), dst(destination), src_index(0), dest_index(0),
next_dest(NULL)
{ connect(); }
{ isConnected = false;
connect(); }
AudioConnection(AudioStream &source, unsigned char sourceOutput,
AudioStream &destination, unsigned char destinationInput) :
src(source), dst(destination),
src_index(sourceOutput), dest_index(destinationInput),
next_dest(NULL)
{ connect(); }
{ isConnected = false;
connect(); }
friend class AudioStream;
protected:
~AudioConnection() {
disconnect();
}
void disconnect(void);
void connect(void);
protected:
AudioStream &src;
AudioStream &dst;
unsigned char src_index;
unsigned char dest_index;
AudioConnection *next_dest;
bool isConnected;
};


@@ -117,17 +144,19 @@ public:
next_update = NULL;
cpu_cycles = 0;
cpu_cycles_max = 0;
numConnections = 0;
}
static void initialize_memory(audio_block_t *data, unsigned int num);
int processorUsage(void) { return CYCLE_COUNTER_APPROX_PERCENT(cpu_cycles); }
int processorUsageMax(void) { return CYCLE_COUNTER_APPROX_PERCENT(cpu_cycles_max); }
void processorUsageMaxReset(void) { cpu_cycles_max = cpu_cycles; }
bool isActive(void) { return active; }
uint16_t cpu_cycles;
uint16_t cpu_cycles_max;
static uint16_t cpu_cycles_total;
static uint16_t cpu_cycles_total_max;
static uint8_t memory_used;
static uint8_t memory_used_max;
static uint16_t memory_used;
static uint16_t memory_used_max;
protected:
bool active;
unsigned char num_inputs;
@@ -141,6 +170,7 @@ protected:
static void update_all(void) { NVIC_SET_PENDING(IRQ_SOFTWARE); }
friend void software_isr(void);
friend class AudioConnection;
uint8_t numConnections;
private:
AudioConnection *destination_list;
audio_block_t **inputQueue;
@@ -149,7 +179,9 @@ private:
static AudioStream *first_update; // for update_all
AudioStream *next_update; // for update_all
static audio_block_t *memory_pool;
static uint32_t memory_pool_available_mask[6];
static uint32_t memory_pool_available_mask[];
static uint16_t memory_pool_first_mask;
};

#endif
#endif

+ 19
- 0
teensy3/Client.h View File

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

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

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

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

#if ARDUINO >= 100

#ifndef client_h

+ 48
- 13
teensy3/DMAChannel.cpp View File

@@ -1,8 +1,39 @@
/* 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 "DMAChannel.h"

#if DMA_NUM_CHANNELS > 16
#undef DMA_NUM_CHANNELS
#define DMA_NUM_CHANNELS 16
#if DMA_NUM_CHANNELS <= 16
#define DMA_MAX_CHANNELS DMA_NUM_CHANNELS
#else
#define DMA_MAX_CHANNELS 16
#endif


@@ -22,7 +53,7 @@ void DMAChannel::begin(bool force_initialization)
uint32_t ch = 0;

__disable_irq();
if (!force_initialization && TCD && channel < DMA_NUM_CHANNELS
if (!force_initialization && TCD && channel < DMA_MAX_CHANNELS
&& (dma_channel_allocated_mask & (1 << channel))
&& (uint32_t)TCD == (uint32_t)(0x40009000 + channel * 32)) {
// DMA channel already allocated
@@ -35,10 +66,10 @@ void DMAChannel::begin(bool force_initialization)
__enable_irq();
break;
}
if (++ch >= DMA_NUM_CHANNELS) {
if (++ch >= DMA_MAX_CHANNELS) {
__enable_irq();
TCD = (TCD_t *)0;
channel = DMA_NUM_CHANNELS;
channel = DMA_MAX_CHANNELS;
return; // no more channels available
// attempts to use this object will hardfault
}
@@ -46,7 +77,11 @@ void DMAChannel::begin(bool force_initialization)
channel = ch;
SIM_SCGC7 |= SIM_SCGC7_DMA;
SIM_SCGC6 |= SIM_SCGC6_DMAMUX;
DMA_CR = DMA_CR_EMLM | DMA_CR_EDBG ; // minor loop mapping is available
#if DMA_NUM_CHANNELS <= 16
DMA_CR = DMA_CR_EMLM | DMA_CR_EDBG; // minor loop mapping is available
#else
DMA_CR = DMA_CR_GRP1PRI| DMA_CR_EMLM | DMA_CR_EDBG;
#endif
DMA_CERQ = ch;
DMA_CERR = ch;
DMA_CEEI = ch;
@@ -65,12 +100,12 @@ void DMAChannel::begin(bool force_initialization)

void DMAChannel::release(void)
{
if (channel >= DMA_NUM_CHANNELS) return;
if (channel >= DMA_MAX_CHANNELS) return;
DMA_CERQ = channel;
__disable_irq();
dma_channel_allocated_mask &= ~(1 << channel);
__enable_irq();
channel = DMA_NUM_CHANNELS;
channel = DMA_MAX_CHANNELS;
TCD = (TCD_t *)0;
}

@@ -106,7 +141,7 @@ void DMAChannel::begin(bool force_initialization)
uint32_t ch = 0;

__disable_irq();
if (!force_initialization && CFG && channel < DMA_NUM_CHANNELS
if (!force_initialization && CFG && channel < DMA_MAX_CHANNELS
&& (dma_channel_allocated_mask & (1 << channel))
&& (uint32_t)CFG == (uint32_t)(0x40008100 + channel * 16)) {
// DMA channel already allocated
@@ -119,10 +154,10 @@ void DMAChannel::begin(bool force_initialization)
__enable_irq();
break;
}
if (++ch >= DMA_NUM_CHANNELS) {
if (++ch >= DMA_MAX_CHANNELS) {
__enable_irq();
CFG = (CFG_t *)0;
channel = DMA_NUM_CHANNELS;
channel = DMA_MAX_CHANNELS;
return; // no more channels available
// attempts to use this object will hardfault
}
@@ -139,7 +174,7 @@ void DMAChannel::begin(bool force_initialization)

void DMAChannel::release(void)
{
if (channel >= DMA_NUM_CHANNELS) return;
if (channel >= DMA_MAX_CHANNELS) return;
CFG->DSR_BCR = DMA_DSR_BCR_DONE;
__disable_irq();
dma_channel_allocated_mask &= ~(1 << channel);

+ 41
- 9
teensy3/DMAChannel.h View File

@@ -1,3 +1,33 @@
/* 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 DMAChannel_h_
#define DMAChannel_h_

@@ -41,7 +71,7 @@ extern uint16_t dma_channel_allocated_mask;

class DMABaseClass {
public:
typedef struct __attribute__((packed)) {
typedef struct __attribute__((packed, aligned(4))) {
volatile const void * volatile SADDR;
int16_t SOFF;
union { uint16_t ATTR;
@@ -311,11 +341,12 @@ public:

// Set the number of transfers (number of triggers until complete)
void transferCount(unsigned int len) {
if (len > 32767) return;
if (len >= 512) {
if (!(TCD->BITER & DMA_TCD_BITER_ELINK)) {
if (len > 32767) return;
TCD->BITER = len;
TCD->CITER = len;
} else {
if (len > 511) return;
TCD->BITER = (TCD->BITER & 0xFE00) | len;
TCD->CITER = (TCD->CITER & 0xFE00) | len;
}
@@ -349,6 +380,7 @@ protected:
DMABaseClass() {}

static inline void copy_tcd(TCD_t *dst, const TCD_t *src) {
dst->CSR = 0;
const uint32_t *p = (const uint32_t *)src;
uint32_t *q = (uint32_t *)dst;
uint32_t t1, t2, t3, t4;
@@ -589,7 +621,7 @@ void DMAPriorityOrder(DMAChannel &ch1, DMAChannel &ch2, DMAChannel &ch3, DMAChan

class DMABaseClass {
public:
typedef struct __attribute__((packed)) {
typedef struct __attribute__((packed, aligned(4))) {
volatile const void * volatile SAR;
volatile void * volatile DAR;
volatile uint32_t DSR_BCR;
@@ -753,7 +785,7 @@ public:
uint32_t mod = len2mod(len);
if (mod == 0) return;
CFG->DAR = p;
CFG->DCR = (CFG->DCR & 0xF0F0F0FF) | DMA_DCR_DSIZE(1) | DMA_DCR_DINC
CFG->DCR = (CFG->DCR & 0xF0F0F0FF) | DMA_DCR_DSIZE(2) | DMA_DCR_DINC
| DMA_DCR_DMOD(mod);
CFG->DSR_BCR = len;
}
@@ -767,7 +799,7 @@ public:
uint32_t mod = len2mod(len);
if (mod == 0) return;
CFG->DAR = p;
CFG->DCR = (CFG->DCR & 0xF0F0F0FF) | DMA_DCR_DSIZE(1) | DMA_DCR_DINC
CFG->DCR = (CFG->DCR & 0xF0F0F0FF) | DMA_DCR_DSIZE(0) | DMA_DCR_DINC
| DMA_DCR_DMOD(mod);
CFG->DSR_BCR = len;
}
@@ -780,11 +812,11 @@ public:
void transferSize(unsigned int len) {
uint32_t dcr = CFG->DCR & 0xF0C8FFFF;
if (len == 4) {
CFG->DCR = dcr | DMA_DCR_DSIZE(0) | DMA_DCR_DSIZE(0);
CFG->DCR = dcr | DMA_DCR_SSIZE(0) | DMA_DCR_DSIZE(0);
} else if (len == 2) {
CFG->DCR = dcr | DMA_DCR_DSIZE(2) | DMA_DCR_DSIZE(2);
CFG->DCR = dcr | DMA_DCR_SSIZE(2) | DMA_DCR_DSIZE(2);
} else {
CFG->DCR = dcr | DMA_DCR_DSIZE(1) | DMA_DCR_DSIZE(1);
CFG->DCR = dcr | DMA_DCR_SSIZE(1) | DMA_DCR_DSIZE(1);
}
}


+ 344
- 0
teensy3/EventResponder.cpp View File

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

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

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

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

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

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

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

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

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

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


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


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

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

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

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

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

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

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

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

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



+ 274
- 0
teensy3/EventResponder.h View File

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

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

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

#include <Arduino.h>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#endif

+ 72
- 0
teensy3/FS.h View File

@@ -0,0 +1,72 @@
/* 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....
*/


#ifndef FS_H
#define FS_H
#ifdef __cplusplus

#include "Stream.h"
#include "WString.h"

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

bool seek(uint32_t pos) {
return seek(pos, SeekSet);
}
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);
}

// 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);
};

class Dir {
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());
}
};

#endif // __cplusplus
#endif // FS_H

+ 210
- 6
teensy3/HardwareSerial.h View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -33,32 +33,36 @@

#include "kinetis.h"

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


#define SERIAL_7E1 0x02
#define SERIAL_7O1 0x03
#define SERIAL_8N1 0x00
#define SERIAL_8N2 0x04
#define SERIAL_8E1 0x06
#define SERIAL_8O1 0x07
#define SERIAL_7E1_RXINV 0x12
#define SERIAL_7O1_RXINV 0x13
#define SERIAL_8N1_RXINV 0x10
#define SERIAL_8N2_RXINV 0x14
#define SERIAL_8E1_RXINV 0x16
#define SERIAL_8O1_RXINV 0x17
#define SERIAL_7E1_TXINV 0x22
#define SERIAL_7O1_TXINV 0x23
#define SERIAL_8N1_TXINV 0x20
#define SERIAL_8N2_TXINV 0x24
#define SERIAL_8E1_TXINV 0x26
#define SERIAL_8O1_TXINV 0x27
#define SERIAL_7E1_RXINV_TXINV 0x32
#define SERIAL_7O1_RXINV_TXINV 0x33
#define SERIAL_8N1_RXINV_TXINV 0x30
#define SERIAL_8N2_RXINV_TXINV 0x34
#define SERIAL_8E1_RXINV_TXINV 0x36
#define SERIAL_8O1_RXINV_TXINV 0x37
#ifdef SERIAL_9BIT_SUPPORT
@@ -75,6 +79,28 @@
#define SERIAL_9E1_RXINV_TXINV 0xBE
#define SERIAL_9O1_RXINV_TXINV 0xBF
#endif
// Teensy LC and 3.5 and 3.6 Uarts have 1/2 bit stop setting
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(KINETISL)
#define SERIAL_2STOP_BITS 0x100
#define SERIAL_8E2 (SERIAL_8E1 | SERIAL_2STOP_BITS)
#define SERIAL_8O2 (SERIAL_8O1 | SERIAL_2STOP_BITS)
#define SERIAL_8E2_RXINV (SERIAL_8E1_RXINV | SERIAL_2STOP_BITS)
#define SERIAL_8O2_RXINV (SERIAL_8O1_RXINV | SERIAL_2STOP_BITS)
#define SERIAL_8E2_TXINV (SERIAL_8E1_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8O2_TXINV (SERIAL_8O1_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8E2_RXINV_TXINV (SERIAL_8E1_RXINV_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8O2_RXINV_TXINV (SERIAL_8O1_RXINV_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8N2 (SERIAL_8N1 | SERIAL_2STOP_BITS)
#define SERIAL_8N2_RXINV (SERIAL_8N1_RXINV | SERIAL_2STOP_BITS)
#define SERIAL_8N2_TXINV (SERIAL_8N1_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8N2_RXINV_TXINV (SERIAL_8N1_RXINV_TXINV | SERIAL_2STOP_BITS)
#else
// for Teensy 3.0-3.2 we can fake 2 stop bits by using 9 bit mode
#define SERIAL_8N2 0x04
#define SERIAL_8N2_RXINV 0x14
#define SERIAL_8N2_TXINV 0x24
#define SERIAL_8N2_RXINV_TXINV 0x34
#endif
// bit0: parity, 0=even, 1=odd
// bit1: parity, 0=disable, 1=enable
// bit2: mode, 1=9bit, 0=8bit
@@ -164,6 +190,57 @@ int serial3_getchar(void);
int serial3_peek(void);
void serial3_clear(void);

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

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

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

#ifdef __cplusplus
}
#endif
@@ -176,6 +253,7 @@ void serial3_clear(void);
class HardwareSerial : public Stream
{
public:
constexpr HardwareSerial() {}
virtual void begin(uint32_t baud) { serial_begin(BAUD2DIV(baud)); }
virtual void begin(uint32_t baud, uint32_t format) {
serial_begin(BAUD2DIV(baud));
@@ -192,6 +270,7 @@ public:
virtual void flush(void) { serial_flush(); }
virtual void clear(void) { serial_clear(); }
virtual int availableForWrite(void) { return serial_write_buffer_free(); }
using Print::write;
virtual size_t write(uint8_t c) { serial_putchar(c); return 1; }
virtual size_t write(unsigned long n) { return write((uint8_t)n); }
virtual size_t write(long n) { return write((uint8_t)n); }
@@ -211,6 +290,7 @@ extern void serialEvent1(void);
class HardwareSerial2 : public HardwareSerial
{
public:
constexpr HardwareSerial2() {}
virtual void begin(uint32_t baud) { serial2_begin(BAUD2DIV2(baud)); }
virtual void begin(uint32_t baud, uint32_t format) {
serial2_begin(BAUD2DIV2(baud));
@@ -227,6 +307,7 @@ public:
virtual void flush(void) { serial2_flush(); }
virtual void clear(void) { serial2_clear(); }
virtual int availableForWrite(void) { return serial2_write_buffer_free(); }
using Print::write;
virtual size_t write(uint8_t c) { serial2_putchar(c); return 1; }
virtual size_t write(unsigned long n) { return write((uint8_t)n); }
virtual size_t write(long n) { return write((uint8_t)n); }
@@ -246,6 +327,7 @@ extern void serialEvent2(void);
class HardwareSerial3 : public HardwareSerial
{
public:
constexpr HardwareSerial3() {}
virtual void begin(uint32_t baud) { serial3_begin(BAUD2DIV3(baud)); }
virtual void begin(uint32_t baud, uint32_t format) {
serial3_begin(BAUD2DIV3(baud));
@@ -262,6 +344,7 @@ public:
virtual void flush(void) { serial3_flush(); }
virtual void clear(void) { serial3_clear(); }
virtual int availableForWrite(void) { return serial3_write_buffer_free(); }
using Print::write;
virtual size_t write(uint8_t c) { serial3_putchar(c); return 1; }
virtual size_t write(unsigned long n) { return write((uint8_t)n); }
virtual size_t write(long n) { return write((uint8_t)n); }
@@ -278,5 +361,126 @@ public:
extern HardwareSerial3 Serial3;
extern void serialEvent3(void);

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

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

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




#endif
#endif

+ 31
- 0
teensy3/HardwareSerial1.cpp View File

@@ -1,3 +1,34 @@
/* 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 "HardwareSerial.h"

HardwareSerial Serial1;

+ 31
- 0
teensy3/HardwareSerial2.cpp View File

@@ -1,3 +1,34 @@
/* 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 "HardwareSerial.h"

HardwareSerial2 Serial2;

+ 31
- 0
teensy3/HardwareSerial3.cpp View File

@@ -1,3 +1,34 @@
/* 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 "HardwareSerial.h"

HardwareSerial3 Serial3;

+ 41
- 0
teensy3/HardwareSerial4.cpp View File

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

#ifdef HAS_KINETISK_UART3

HardwareSerial4 Serial4;

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

#endif

+ 41
- 0
teensy3/HardwareSerial5.cpp View File

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

#ifdef HAS_KINETISK_UART4

HardwareSerial5 Serial5;

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

#endif

+ 41
- 0
teensy3/HardwareSerial6.cpp View File

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

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

HardwareSerial6 Serial6;

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

#endif

+ 20
- 1
teensy3/IPAddress.cpp View File

@@ -1,4 +1,23 @@
#include "Arduino.h"
/*
IPAddress.cpp - Base class that provides IPAddress
Copyright (c) 2011 Adrian McEwen. All right reserved.

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

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

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

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

size_t IPAddress::printTo(Print& p) const

+ 116
- 175
teensy3/IntervalTimer.cpp View File

@@ -1,204 +1,145 @@
/* Copyright (c) 2013 Daniel Gilbert, loglow@gmail.com

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in the
Software without restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */

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

#include "IntervalTimer.h"

static void dummy_funct(void);

// ------------------------------------------------------------
// static class variables need to be reiterated here before use
// ------------------------------------------------------------
bool IntervalTimer::PIT_enabled;
bool IntervalTimer::PIT_used[];
IntervalTimer::ISR IntervalTimer::PIT_ISR[];



// ------------------------------------------------------------
// these are the ISRs (Interrupt Service Routines) that get
// called by each PIT timer when it fires. they're defined here
// so that they can auto-clear themselves and so the user can
// specify a custom ISR and reassign it as needed
// ------------------------------------------------------------
#if defined(KINETISK)
void pit0_isr() { PIT_TFLG0 = 1; IntervalTimer::PIT_ISR[0](); }
void pit1_isr() { PIT_TFLG1 = 1; IntervalTimer::PIT_ISR[1](); }
void pit2_isr() { PIT_TFLG2 = 1; IntervalTimer::PIT_ISR[2](); }
void pit3_isr() { PIT_TFLG3 = 1; IntervalTimer::PIT_ISR[3](); }
#define NUM_CHANNELS 4
static void (*funct_table[4])(void) = {dummy_funct, dummy_funct, dummy_funct, dummy_funct};

#elif defined(KINETISL)
void pit_isr() {
if (PIT_TFLG0) { PIT_TFLG0 = 1; IntervalTimer::PIT_ISR[0](); }
if (!IntervalTimer::PIT_enabled) return;
if (PIT_TFLG1) { PIT_TFLG1 = 1; IntervalTimer::PIT_ISR[1](); }
}
#define NUM_CHANNELS 2
static void (*funct_table[2])(void) = {dummy_funct, dummy_funct};
uint8_t IntervalTimer::nvic_priorites[2] = {255, 255};
#endif



// ------------------------------------------------------------
// this function inits and starts the timer, using the specified
// function as a callback and the period provided. must be passed
// the name of a function taking no arguments and returning void.
// make sure this function can complete within the time allowed.
// attempts to allocate a timer using available resources,
// returning true on success or false in case of failure.
// period is specified as number of bus cycles
// ------------------------------------------------------------
bool IntervalTimer::beginCycles(ISR newISR, uint32_t newValue) {

// if this interval timer is already running, stop it
if (status == TIMER_PIT) {
stop_PIT();
status = TIMER_OFF;
}
// store callback pointer
myISR = newISR;
// attempt to allocate this timer
if (allocate_PIT(newValue)) status = TIMER_PIT;
else status = TIMER_OFF;
// check for success and return
if (status != TIMER_OFF) return true;
return false;
bool IntervalTimer::beginCycles(void (*funct)(), uint32_t cycles)
{
if (channel) {
channel->TCTRL = 0;
channel->TFLG = 1;
} else {
SIM_SCGC6 |= SIM_SCGC6_PIT;
__asm__ volatile("nop"); // solves timing problem on Teensy 3.5
PIT_MCR = 1;
channel = KINETISK_PIT_CHANNELS;
while (1) {
if (channel->TCTRL == 0) break;
if (++channel >= KINETISK_PIT_CHANNELS + NUM_CHANNELS) {
channel = NULL;
return false;
}
}
}
int index = channel - KINETISK_PIT_CHANNELS;
funct_table[index] = funct;
channel->LDVAL = cycles;
channel->TCTRL = 3;
#if defined(KINETISK)
NVIC_SET_PRIORITY(IRQ_PIT_CH0 + index, nvic_priority);
NVIC_ENABLE_IRQ(IRQ_PIT_CH0 + index);
#elif defined(KINETISL)
nvic_priorites[index] = nvic_priority;
if (nvic_priorites[0] <= nvic_priorites[1]) {
NVIC_SET_PRIORITY(IRQ_PIT, nvic_priorites[0]);
} else {
NVIC_SET_PRIORITY(IRQ_PIT, nvic_priorites[1]);
}
NVIC_ENABLE_IRQ(IRQ_PIT);
#endif
return true;
}


// ------------------------------------------------------------
// stop the timer if it's currently running, using its status
// to determine what hardware resources the timer may be using
// ------------------------------------------------------------
void IntervalTimer::end() {
if (status == TIMER_PIT) stop_PIT();
status = TIMER_OFF;
if (channel) {
int index = channel - KINETISK_PIT_CHANNELS;
#if defined(KINETISK)
NVIC_DISABLE_IRQ(IRQ_PIT_CH0 + index);
#elif defined(KINETISL)
// TODO: disable IRQ_PIT, but only if both instances ended
#endif
funct_table[index] = dummy_funct;
channel->TCTRL = 0;
#if defined(KINETISL)
nvic_priorites[index] = 255;
if (nvic_priorites[0] <= nvic_priorites[1]) {
NVIC_SET_PRIORITY(IRQ_PIT, nvic_priorites[0]);
} else {
NVIC_SET_PRIORITY(IRQ_PIT, nvic_priorites[1]);
}
#endif
channel = 0;
}
}



// ------------------------------------------------------------
// enables the PIT clock bit, the master PIT reg, and sets flag
// ------------------------------------------------------------
void IntervalTimer::enable_PIT() {
SIM_SCGC6 |= SIM_SCGC6_PIT;
PIT_MCR = 0;
PIT_enabled = true;
#if defined(KINETISK)
void pit0_isr()
{
PIT_TFLG0 = 1;
funct_table[0]();
}



// ------------------------------------------------------------
// disables the master PIT reg, the PIT clock bit, and unsets flag
// ------------------------------------------------------------
void IntervalTimer::disable_PIT() {
PIT_MCR = 1;
SIM_SCGC6 &= ~SIM_SCGC6_PIT;
PIT_enabled = false;
void pit1_isr() {
PIT_TFLG1 = 1;
funct_table[1]();
}



// ------------------------------------------------------------
// enables the PIT clock if not already enabled, then checks to
// see if any PITs are available for use. if one is available,
// it's initialized and started with the specified value, and
// the function returns true, otherwise it returns false
// ------------------------------------------------------------
bool IntervalTimer::allocate_PIT(uint32_t newValue) {
// enable clock to the PIT module if necessary
if (!PIT_enabled) enable_PIT();
// check for an available PIT, and if so, start it
for (uint8_t id = 0; id < NUM_PIT; id++) {
if (!PIT_used[id]) {
PIT_id = id;
start_PIT(newValue);
PIT_used[id] = true;
return true;
}
}
// no PIT available
return false;
void pit2_isr() {
PIT_TFLG2 = 1;
funct_table[2]();
}



// ------------------------------------------------------------
// configuters a PIT's registers, function pointer, and enables
// interrupts, effectively starting the timer upon completion
// ------------------------------------------------------------
void IntervalTimer::start_PIT(uint32_t newValue) {
// point to the correct registers
PIT_LDVAL = &PIT_LDVAL0 + PIT_id * 4;
PIT_TCTRL = &PIT_TCTRL0 + PIT_id * 4;
// point to the correct PIT ISR
PIT_ISR[PIT_id] = myISR;
// write value to register and enable interrupt
*PIT_TCTRL = 0;
*PIT_LDVAL = newValue;
*PIT_TCTRL = 3;
#if defined(KINETISK)
IRQ_PIT_CH = IRQ_PIT_CH0 + PIT_id;
NVIC_SET_PRIORITY(IRQ_PIT_CH, nvic_priority);
NVIC_ENABLE_IRQ(IRQ_PIT_CH);
#elif defined(KINETISL)
NVIC_SET_PRIORITY(IRQ_PIT, nvic_priority); // TODO: use the higher of both channels, shared irq
NVIC_ENABLE_IRQ(IRQ_PIT);
#endif

void pit3_isr() {
PIT_TFLG3 = 1;
funct_table[3]();
}



// ------------------------------------------------------------
// stops an active PIT by disabling its interrupt, writing to
// its control register, and freeing up its state for future use.
// also, if no PITs remain in use, disables the core PIT clock
// ------------------------------------------------------------
void IntervalTimer::stop_PIT() {
// disable interrupt and PIT
*PIT_TCTRL = 0;
#if defined(KINETISK)
NVIC_DISABLE_IRQ(IRQ_PIT_CH);
#elif defined(KINETISL)
NVIC_DISABLE_IRQ(IRQ_PIT);
#endif
// free PIT for future use
PIT_used[PIT_id] = false;
// check if we're still using any PIT
for (uint8_t id = 0; id < NUM_PIT; id++) {
if (PIT_used[id]) return;
}
// none used, disable PIT clock
disable_PIT();
void pit_isr() {
if (PIT_TFLG0) {
PIT_TFLG0 = 1;
funct_table[0]();
}
if (PIT_TFLG1) {
PIT_TFLG1 = 1;
funct_table[1]();
}
}
#endif

static void dummy_funct(void)
{
}


+ 128
- 95
teensy3/IntervalTimer.h View File

@@ -1,22 +1,32 @@
/* Copyright (c) 2013 Daniel Gilbert, loglow@gmail.com

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in the
Software without restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */

/* 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 __INTERVALTIMER_H__
#define __INTERVALTIMER_H__
@@ -28,82 +38,105 @@ extern "C" {
#endif

class IntervalTimer {
private:
typedef void (*ISR)();
typedef volatile uint32_t* reg;
enum {TIMER_OFF, TIMER_PIT};
#if defined(KINETISK)
static const uint8_t NUM_PIT = 4;
#elif defined(KINETISL)
static const uint8_t NUM_PIT = 2;
#endif
static const uint32_t MAX_PERIOD = UINT32_MAX / (F_BUS / 1000000.0);
static void enable_PIT();
static void disable_PIT();
static bool PIT_enabled;
static bool PIT_used[NUM_PIT];
static ISR PIT_ISR[NUM_PIT];
bool allocate_PIT(uint32_t newValue);
void start_PIT(uint32_t newValue);
void stop_PIT();
bool status;
uint8_t PIT_id;
reg PIT_LDVAL;
reg PIT_TCTRL;
uint8_t IRQ_PIT_CH;
uint8_t nvic_priority;
ISR myISR;
bool beginCycles(ISR newISR, uint32_t cycles);
public:
IntervalTimer() { status = TIMER_OFF; nvic_priority = 128; }
~IntervalTimer() { end(); }
bool begin(ISR newISR, unsigned int newPeriod) {
if (newPeriod == 0 || newPeriod > MAX_PERIOD) return false;
uint32_t newValue = (F_BUS / 1000000) * newPeriod - 1;
return beginCycles(newISR, newValue);
}
bool begin(ISR newISR, int newPeriod) {
if (newPeriod < 0) return false;
return begin(newISR, (unsigned int)newPeriod);
}
bool begin(ISR newISR, unsigned long newPeriod) {
return begin(newISR, (unsigned int)newPeriod);
}
bool begin(ISR newISR, long newPeriod) {
return begin(newISR, (int)newPeriod);
}
bool begin(ISR newISR, float newPeriod) {
if (newPeriod <= 0 || newPeriod > MAX_PERIOD) return false;
uint32_t newValue = (float)(F_BUS / 1000000) * newPeriod - 0.5;
if (newValue < 40) return false;
return beginCycles(newISR, newValue);
}
bool begin(ISR newISR, double newPeriod) {
return begin(newISR, (float)newPeriod);
}
void end();
void priority(uint8_t n) {
nvic_priority = n;
if (PIT_enabled) NVIC_SET_PRIORITY(IRQ_PIT_CH, n);
}
operator IRQ_NUMBER_t() {
if (PIT_enabled) {
#if defined(KINETISK)
return (IRQ_NUMBER_t)(IRQ_PIT_CH + PIT_id);
#elif defined(KINETISL)
return IRQ_PIT;
#endif
}
return (IRQ_NUMBER_t)NVIC_NUM_INTERRUPTS;
}
#if defined(KINETISK)
friend void pit0_isr();
friend void pit1_isr();
friend void pit2_isr();
friend void pit3_isr();
#elif defined(KINETISL)
friend void pit_isr();
#endif
private:
static const uint32_t MAX_PERIOD = UINT32_MAX / (F_BUS / 1000000.0);
public:
IntervalTimer() {
channel = NULL;
nvic_priority = 128;
}
~IntervalTimer() {
end();
}
bool begin(void (*funct)(), unsigned int microseconds) {
if (microseconds == 0 || microseconds > MAX_PERIOD) return false;
uint32_t cycles = (F_BUS / 1000000) * microseconds - 1;
if (cycles < 36) return false;
return beginCycles(funct, cycles);
}
bool begin(void (*funct)(), int microseconds) {
if (microseconds < 0) return false;
return begin(funct, (unsigned int)microseconds);
}
bool begin(void (*funct)(), unsigned long microseconds) {
return begin(funct, (unsigned int)microseconds);
}
bool begin(void (*funct)(), long microseconds) {
return begin(funct, (int)microseconds);
}
bool begin(void (*funct)(), float microseconds) {
if (microseconds <= 0 || microseconds > MAX_PERIOD) return false;
uint32_t cycles = (float)(F_BUS / 1000000) * microseconds - 0.5;
if (cycles < 36) return false;
return beginCycles(funct, cycles);
}
bool begin(void (*funct)(), double microseconds) {
return begin(funct, (float)microseconds);
}
void update(unsigned int microseconds) {
if (microseconds == 0 || microseconds > MAX_PERIOD) return;
uint32_t cycles = (F_BUS / 1000000) * microseconds - 1;
if (cycles < 36) return;
if (channel) channel->LDVAL = cycles;
}
void update(int microseconds) {
if (microseconds < 0) return;
return update((unsigned int)microseconds);
}
void update(unsigned long microseconds) {
return update((unsigned int)microseconds);
}
void update(long microseconds) {
return update((int)microseconds);
}
void update(float microseconds) {
if (microseconds <= 0 || microseconds > MAX_PERIOD) return;
uint32_t cycles = (float)(F_BUS / 1000000) * microseconds - 0.5;
if (cycles < 36) return;
if (channel) channel->LDVAL = cycles;
}
void update(double microseconds) {
return update((float)microseconds);
}
void end();
void priority(uint8_t n) {
nvic_priority = n;
#if defined(KINETISK)
if (channel) {
int index = channel - KINETISK_PIT_CHANNELS;
NVIC_SET_PRIORITY(IRQ_PIT_CH0 + index, nvic_priority);
}
#elif defined(KINETISL)
if (channel) {
int index = channel - KINETISK_PIT_CHANNELS;
nvic_priorites[index] = nvic_priority;
if (nvic_priorites[0] <= nvic_priorites[1]) {
NVIC_SET_PRIORITY(IRQ_PIT, nvic_priorites[0]);
} else {
NVIC_SET_PRIORITY(IRQ_PIT, nvic_priorites[1]);
}
}
#endif
}
operator IRQ_NUMBER_t() {
if (channel) {
#if defined(KINETISK)
int index = channel - KINETISK_PIT_CHANNELS;
return (IRQ_NUMBER_t)(IRQ_PIT_CH0 + index);
#elif defined(KINETISL)
return IRQ_PIT;
#endif
}
return (IRQ_NUMBER_t)NVIC_NUM_INTERRUPTS;
}
private:
KINETISK_PIT_CHANNEL_t *channel;
uint8_t nvic_priority;
#if defined(KINETISL)
static uint8_t nvic_priorites[2];
#endif
bool beginCycles(void (*funct)(), uint32_t cycles);

};



+ 3
- 0
teensy3/Keyboard.h View File

@@ -0,0 +1,3 @@
// empty Keyboard.h file, for compability with Arduino's Keyboard examples

// This header file is in the public domain.

+ 56
- 0
teensy3/MIDIUSB.h View File

@@ -0,0 +1,56 @@
#ifndef MIDIUSB_h
#define MIDIUSB_h

// For compatibility with Arduino's MIDIUSB library

#include "usb_midi.h"

#ifdef __cplusplus
#if !defined(USB_MIDI) && !defined(USB_MIDI4) && !defined(USB_MIDI16) && !defined(USB_MIDI_SERIAL) && !defined(USB_MIDI4_SERIAL) && !defined(USB_MIDI16_SERIAL) && !defined(USB_MIDI_AUDIO_SERIAL) && !defined(USB_MIDI16_AUDIO_SERIAL) && !defined(USB_EVERYTHING)
#error "Please select MIDI in Tools > USB Type to use MIDIUSB.h"
#endif

typedef struct {
union {
struct {
uint8_t header;
uint8_t byte1;
uint8_t byte2;
uint8_t byte3;
};
uint32_t word;
};
} midiEventPacket_t;


class MIDI_
{
public:
constexpr MIDI_(void) { }
uint32_t available(void) {
return usb_midi_available();
}
midiEventPacket_t read(void) {
midiEventPacket_t event;
event.word = usb_midi_read_message();
return event;
}
void flush(void) {
usb_midi_flush_output();
}
void sendMIDI(midiEventPacket_t event) {
usb_midi_write_packed(event.word);
}
size_t write(const uint8_t *buffer, size_t size) {
// TODO - is this really needed?
return 0;
}
operator bool() {
// TODO - is this really needed?
return true;
}
};
extern MIDI_ MidiUSB;

#endif // __cplusplus
#endif // MIDIUSB_h

+ 44
- 8
teensy3/Makefile View File

@@ -1,5 +1,37 @@
# 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.

# set your MCU type here, or make command line `make MCU=MK20DX256`
MCU=MK20DX256
#MCU=MKL26Z64
#MCU=MK64FX512
#MCU=MK66FX1M0

# make it lower case
LOWER_MCU := $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$(MCU)))))))))))))))))))))))))))
@@ -15,14 +47,18 @@ TARGET = main
ifndef NO_ARDUINO
# Path to your arduino installation
ARDUINOPATH ?= ../../../../..
#ARDUINOPATH ?= ../../../..
endif

# configurable options
OPTIONS = -DF_CPU=48000000 -DUSB_SERIAL -DLAYOUT_US_ENGLISH -DUSING_MAKEFILE

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

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


# Other Makefiles and project templates for Teensy 3.x:
@@ -40,8 +76,8 @@ OPTIONS += -D__$(MCU)__ -DARDUINO=10600 -DTEENSYDUINO=121

ifdef ARDUINOPATH

# path location for Teensy Loader, teensy_post_compile and teensy_reboot
TOOLSPATH = $(abspath $(ARDUINOPATH)/hardware/tools) # on Linux
# path location for Teensy Loader, teensy_post_compile and teensy_reboot (on Linux)
TOOLSPATH = $(abspath $(ARDUINOPATH)/hardware/tools)

# path location for Arduino libraries (currently not used)
LIBRARYPATH = $(abspath $(ARDUINOPATH)/libraries)
@@ -61,16 +97,16 @@ endif
#************************************************************************

# CPPFLAGS = compiler options for C and C++
CPPFLAGS = -Wall -g -Os -mcpu=cortex-m4 -mthumb -MMD $(OPTIONS) -I.
CPPFLAGS = -Wall -g -Os -mcpu=$(CPUARCH) -mthumb -MMD $(OPTIONS) -I.

# compiler options for C++ only
CXXFLAGS = -std=gnu++0x -felide-constructors -fno-exceptions -fno-rtti
CXXFLAGS = -std=gnu++14 -felide-constructors -fno-exceptions -fno-rtti

# compiler options for C only
CFLAGS =

# linker options
LDFLAGS = -Os -Wl,--gc-sections,--defsym=__rtc_localtime=0 --specs=nano.specs -mcpu=cortex-m4 -mthumb -T$(MCU_LD)
LDFLAGS = -Os -Wl,--gc-sections,--defsym=__rtc_localtime=0 --specs=nano.specs -mcpu=$(CPUARCH) -mthumb -T$(MCU_LD)

# additional libraries to link
LIBS = -lm

+ 3
- 0
teensy3/Mouse.h View File

@@ -0,0 +1,3 @@
// empty Mouse.h file, for compability with Arduino's Mouse examples

// This header file is in the public domain.

+ 41
- 29
teensy3/Print.cpp View File

@@ -1,38 +1,45 @@
/*
Print.cpp - Base class that provides print() and println()
Copyright (c) 2008 David A. Mellis. All right reserved.
many modifications, by Paul Stoffregen <paul@pjrc.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 23 November 2006 by David A. Mellis
/* 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 <stdio.h>
//#include <string.h>
#include <inttypes.h>
//#include <math.h>
//#include <avr/pgmspace.h>
//#include "wiring.h"

#include "Print.h"
// Long ago this file contained code from Arduino.cc, which was
// Copyright (c) 2008 David A. Mellis. No substantial portion of
// Arduino's original code remains. In fact, several improvements
// developed for Teensyduino have made their way back into
// Arduino's code base. :-)

#include <Arduino.h>


size_t Print::write(const uint8_t *buffer, size_t size)
{
if (buffer == nullptr) return 0;
size_t count = 0;
while (size--) count += write(*buffer++);
return count;
@@ -80,7 +87,7 @@ __attribute__((weak))
int _write(int file, char *ptr, int len)
{
((class Print *)file)->write((uint8_t *)ptr, len);
return 0;
return len;
}
}

@@ -285,6 +292,11 @@ size_t Print::printFloat(double number, uint8_t digits)
uint8_t sign=0;
size_t count=0;

if (isnan(number)) return print("nan");
if (isinf(number)) return print("inf");
if (number > 4294967040.0f) return print("ovf"); // constant determined empirically
if (number <-4294967040.0f) return print("ovf"); // constant determined empirically
// Handle negative numbers
if (number < 0.0) {
sign = 1;

+ 10
- 3
teensy3/Print.h View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -42,17 +42,24 @@
#define HEX 16
#define OCT 8
#define BIN 2
#define BYTE 0

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

class __FlashStringHelper;

class Print
{
public:
Print() : write_error(0) {}
constexpr Print() : write_error(0) {}
virtual size_t write(uint8_t b) = 0;
size_t write(const char *str) { return write((const uint8_t *)str, strlen(str)); }
virtual size_t write(const uint8_t *buffer, size_t size);
virtual int availableForWrite(void) { return 0; }
virtual void flush() { }
size_t write(const char *buffer, size_t size) { return write((const uint8_t *)buffer, size); }
size_t print(const String &s);
size_t print(char c) { return write((uint8_t)c); }

+ 111
- 2
teensy3/SPIFIFO.h View File

@@ -1,3 +1,33 @@
/* 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 _SPIFIFO_h_
#define _SPIFIFO_h_

@@ -5,7 +35,81 @@

#ifdef KINETISK

#if F_BUS == 60000000
// The preferred way to set SPI speed is with SPI.beginTransaction()

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

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

#elif F_BUS == 108000000
#define HAS_SPIFIFO
#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(108 / 5) * ((1+1)/2) = 21.6 MHz
#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2)) //(108 / 2) * ((1+0)/4) = 13.5 MHz
#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(4) | SPI_CTAR_DBR) //(108 / 3) * ((1+1)/6)
#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(4) | SPI_CTAR_DBR) //(108 / 5) * ((1+1)/6) = 7.2 MHz
#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(4)) //(108 / 3) * ((1+0)/6)
#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(5) | SPI_CTAR_BR(2)) //(108 / 7) * ((1+0)/4) = 3.86 MHz

#elif F_BUS == 96000000
#define HAS_SPIFIFO
#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(96 / 2) * ((1+0)/2)
#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(4) | SPI_CTAR_DBR) //(96 / 2) * ((1+1)/6)
#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(6) | SPI_CTAR_DBR) //(96 / 2) * ((1+1)/8)
#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(2)) //(96 / 3) * ((1+0)/4)
#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(6)) //(96 / 2) * ((1+0)/8)
#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(6)) //(96 / 3) * ((1+0)/8)

#elif F_BUS == 90000000
#define HAS_SPIFIFO
#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(90 / 2) * ((1+0)/2) = 22.5 MHz
#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(4) | SPI_CTAR_DBR) //(90 / 2) * ((1+1)/6) = 15 MHz
#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(6) | SPI_CTAR_DBR) //(90 / 2) * ((1+1)/8) = 11.25 MHz
#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(4)) //(90 / 2) * ((1+0)/6) = 7.5 MHz
#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(4) | SPI_CTAR_DBR) //(90 / 5) * ((1+1)/6)
#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(6)) //(90 / 3) * ((1+0)/8) = 3.75 MHz

#elif F_BUS == 80000000
#define HAS_SPIFIFO
#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(80 / 2) * ((1+0)/2) = 20 MHz
#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(80 / 5) * ((1+1)/2)
#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(5) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(80 / 7) * ((1+1)/2) = 11.42 MHz
#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(0)) //(80 / 5) * ((1+0)/2)
#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(5) | SPI_CTAR_BR(0)) //(80 / 7) * ((1+0)/2) = 5.7 MHz
#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(2)) //(80 / 5) * ((1+0)/4)

#elif F_BUS == 72000000
#define HAS_SPIFIFO
#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(72 / 3) * ((1+1)/2)
#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(4) | SPI_CTAR_DBR) //(72 / 2) * ((1+1)/6) = 12 MHz
#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(4) | SPI_CTAR_DBR) //(72 / 2) * ((1+1)/6)
#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(4) | SPI_CTAR_DBR) //(72 / 3) * ((1+1)/6)
#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(4)) //(72 / 2) * ((1+0)/6)
#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(4)) //(72 / 3) * ((1+0)/6)

#elif F_BUS == 64000000
#define HAS_SPIFIFO
#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(64 / 3) * ((1+1)/2) = 21.3 MHz
#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(64 / 2) * ((1+0)/2)
#define SPI_CLOCK_12MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0)) //(64 / 3) * ((1+0)/2) = 10.67 MHz
#define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2)) //(64 / 2) * ((1+0)/4)
#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(4)) //(64 / 2) * ((1+0)/6) = 5.3 MHz
#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(6)) //(64 / 2) * ((1+0)/8)

#elif F_BUS == 60000000
#define HAS_SPIFIFO
#define SPI_CLOCK_24MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(60 / 3) * ((1+1)/2) = 20 MHz
#define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(60 / 2) * ((1+0)/2) = 15 MHz
@@ -133,7 +237,7 @@ for $i (2, 3, 5, 7) {
class SPIFIFOclass
{
public:
inline void begin(uint8_t pin, uint32_t speed, uint32_t mode=SPI_MODE0) __attribute__((always_inline)) {
inline void begin(uint8_t pin, uint32_t speed, uint32_t mode=SPI_MODE0) __attribute__((always_inline, deprecated)) {
uint32_t p, ctar = speed;
SIM_SCGC6 |= SIM_SCGC6_SPI0;

@@ -174,6 +278,11 @@ public:
} else if (pin == 15) { // PTC0
CORE_PIN15_CONFIG = PORT_PCR_MUX(2);
p = 0x10;
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
} else if (pin == 26) {
CORE_PIN26_CONFIG = PORT_PCR_MUX(2);
p = 0x01;
#endif
} else {
reg = portOutputRegister(pin);
pinMode(pin, OUTPUT);

+ 21
- 0
teensy3/Server.h View File

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

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

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

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

#if ARDUINO >= 100

#ifndef server_h
#define server_h

#include "Print.h"

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

+ 18
- 38
teensy3/Stream.cpp View File

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

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

#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field
@@ -75,35 +74,38 @@ void Stream::setTimeout(unsigned long timeout) // sets the maximum number of mi
}

// find returns true if the target string is found
bool Stream::find(char *target)
bool Stream::find(const char *target)
{
return findUntil(target, NULL);
}

// reads data from the stream until the target string of given length is found
// returns true if target string is found, false if timed out
bool Stream::find(char *target, size_t length)
bool Stream::find(const char *target, size_t length)
{
return findUntil(target, length, NULL, 0);
}

// as find but search ends if the terminator string is found
bool Stream::findUntil(char *target, 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
// search terminated if the terminator string is found
// returns true if target string is found, false if terminated or timed out
bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen)
bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen)
{
size_t index = 0; // maximum target string length is 64k bytes!
size_t termIndex = 0;
int c;
if( target == nullptr) return true;
if( *target == 0) return true; // return true if target is a null string
if (terminator == nullptr) termLen = 0;

if( *target == 0)
return true; // return true if target is a null string
while( (c = timedRead()) > 0){
if( c == target[index]){
//////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
@@ -176,7 +178,7 @@ float Stream::parseFloat(char skipChar){
boolean isNegative = false;
boolean isFraction = false;
long value = 0;
char c;
int c;
float fraction = 1.0;

c = peekNextDigit();
@@ -216,6 +218,7 @@ float Stream::parseFloat(char skipChar){
//
size_t Stream::readBytes(char *buffer, size_t length)
{
if (buffer == nullptr) return 0;
size_t count = 0;
while (count < length) {
int c = timedRead();
@@ -236,6 +239,7 @@ size_t Stream::readBytes(char *buffer, size_t length)

size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
{
if (buffer == nullptr) return 0;
if (length < 1) return 0;
length--;
size_t index = 0;
@@ -256,7 +260,7 @@ size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
String Stream::readString(size_t max)
{
String str;
size_t length = str.length();
size_t length = 0;
while (length < max) {
int c = timedRead();
if (c < 0) {
@@ -265,6 +269,7 @@ String Stream::readString(size_t max)
}
if (c == 0) break;
str += (char)c;
length++;
}
return str;
}
@@ -272,7 +277,7 @@ String Stream::readString(size_t max)
String Stream::readStringUntil(char terminator, size_t max)
{
String str;
size_t length = str.length();
size_t length = 0;
while (length < max) {
int c = timedRead();
if (c < 0) {
@@ -281,32 +286,7 @@ String Stream::readStringUntil(char terminator, size_t max)
}
if (c == 0 || c == terminator) break;
str += (char)c;
length++;
}
return str;
}



























+ 18
- 11
teensy3/Stream.h View File

@@ -26,27 +26,34 @@
class Stream : public Print
{
public:
Stream() : _timeout(1000), read_error(0) {}
constexpr Stream() : _timeout(1000), read_error(0) {}
virtual int available() = 0;
virtual int read() = 0;
virtual int peek() = 0;
virtual void flush() = 0;

void setTimeout(unsigned long timeout);
bool find(char *target);
bool find(uint8_t *target) { return find ((char *)target); }
bool find(char *target, size_t length);
bool find(uint8_t *target, size_t length) { return find ((char *)target, length); }
bool findUntil(char *target, char *terminator);
bool findUntil(uint8_t *target, char *terminator) { return findUntil((char *)target, terminator); }
bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen);
bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); }
bool find(const char *target);
bool find(const uint8_t *target) { return find ((const char *)target); }
bool find(const String &target) { return find(target.c_str()); }
bool find(const char *target, size_t length);
bool find(const uint8_t *target, size_t length) { return find ((const char *)target, length); }
bool find(const String &target, size_t length) { return find(target.c_str(), length); }
bool findUntil(const char *target, const char *terminator);
bool findUntil(const uint8_t *target, const char *terminator) { return findUntil((const char *)target, terminator); }
bool findUntil(const String &target, const char *terminator) { return findUntil(target.c_str(), terminator); }
bool findUntil(const char *target, const String &terminator) { return findUntil(target, terminator.c_str()); }
bool findUntil(const String &target, const String &terminator) { return findUntil(target.c_str(), terminator.c_str()); }
bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen);
bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) {return findUntil((const char *)target, targetLen, terminate, termLen); }
bool findUntil(const String &target, size_t targetLen, const char *terminate, size_t termLen);
bool findUntil(const char *target, size_t targetLen, const String &terminate, size_t termLen);
bool findUntil(const String &target, size_t targetLen, const String &terminate, size_t termLen);
long parseInt();
long parseInt(char skipChar);
float parseFloat();
float parseFloat(char skipChar);
size_t readBytes(char *buffer, size_t length);
size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
size_t readBytes(uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
size_t readBytesUntil(char terminator, char *buffer, size_t length);
size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); }
String readString(size_t max = 120);

+ 5
- 7
teensy3/Tone.cpp View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -10,10 +10,10 @@
* 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
* 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
* 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.
@@ -28,10 +28,7 @@
* SOFTWARE.
*/

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

// IntervalTimer based tone. This allows tone() to share the timers with other
// libraries, rather than permanently hogging one PIT timer even for projects
@@ -73,6 +70,7 @@ void tone(uint8_t pin, uint16_t frequency, uint32_t duration)
} else {
count = 0xFFFFFFFD;
}
if (frequency < 1) frequency = 1; // minimum is 1 Hz
usec = (float)500000.0 / (float)frequency;
config = portConfigRegister(pin);


+ 1
- 0
teensy3/Udp.h View File

@@ -44,6 +44,7 @@ class UDP : public Stream {

public:
virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
virtual uint8_t beginMulticast(IPAddress, uint16_t) { return 0; }
virtual void stop() =0; // Finish with the UDP socket

// Sending UDP packets

+ 3
- 3
teensy3/WCharacter.h View File

@@ -1,17 +1,17 @@
/*
WCharacter.h - Character utility functions for Wiring & Arduino
Copyright (c) 2010 Hernando Barragan. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

+ 2
- 0
teensy3/WConstants.h View File

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

#include "wiring.h"

+ 23
- 7
teensy3/WMath.cpp View File

@@ -1,3 +1,24 @@
/*
Part of the Wiring project - http://wiring.org.co
Copyright (c) 2004-06 Hernando Barragan
Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/

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

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

You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
*/

#include <stdint.h>

static uint32_t seed;
@@ -7,12 +28,12 @@ void randomSeed(uint32_t newseed)
if (newseed > 0) seed = newseed;
}

void srandom(uint32_t newseed)
void srandom(unsigned int newseed)
{
seed = newseed;
}

uint32_t random(void)
int32_t random(void)
{
int32_t hi, lo, x;

@@ -40,11 +61,6 @@ int32_t random(int32_t howsmall, int32_t howbig)
return random(diff) + howsmall;
}

long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

unsigned int makeWord(unsigned int w) { return w; }
unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; }


+ 33
- 4
teensy3/WProgram.h View File

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

#ifndef WProgram_h
#define WProgram_h

@@ -34,7 +64,7 @@
#include "usb_touch.h"
#include "usb_undef.h" // do not allow usb_desc.h stuff to leak to user programs

//#include "WCharacter.h"
#include "WCharacter.h"
#include "WString.h"
#include "elapsedMillis.h"
#include "IntervalTimer.h"
@@ -50,12 +80,11 @@ void tone(uint8_t pin, uint16_t frequency, uint32_t duration = 0);
void noTone(uint8_t pin);

// WMath prototypes
uint32_t random(void);
int32_t random(void);
uint32_t random(uint32_t howbig);
int32_t random(int32_t howsmall, int32_t howbig);
void randomSeed(uint32_t newseed);
void srandom(uint32_t newseed);
long map(long, long, long, long, long);
void srandom(unsigned int newseed);

#include "pins_arduino.h"


+ 15
- 4
teensy3/WString.cpp View File

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

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


/*********************************************/
@@ -248,8 +248,19 @@ String & String::append(const String &s)
String & String::append(const char *cstr, unsigned int length)
{
unsigned int newlen = len + length;
bool self = false;
unsigned int buffer_offset;
if ( (cstr >= buffer) && (cstr < (buffer+len) ) ) {
self = true;
buffer_offset = (unsigned int)(cstr-buffer);
}
if (length == 0 || !reserve(newlen)) return *this;
strcpy(buffer + len, cstr);
if ( self ) {
memcpy(buffer + len, buffer+buffer_offset, length);
buffer[newlen] = 0;
}
else
strcpy(buffer + len, cstr);
len = newlen;
return *this;
}
@@ -549,7 +560,7 @@ int String::lastIndexOf( char theChar ) const

int String::lastIndexOf(char ch, unsigned int fromIndex) const
{
if (fromIndex >= len || fromIndex < 0) return -1;
if (fromIndex >= len) return -1;
char tempchar = buffer[fromIndex + 1];
buffer[fromIndex + 1] = '\0';
char* temp = strrchr( buffer, ch );
@@ -565,7 +576,7 @@ int String::lastIndexOf(const String &s2) const

int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
{
if (s2.len == 0 || len == 0 || s2.len > len || fromIndex < 0) return -1;
if (s2.len == 0 || len == 0 || s2.len > len) return -1;
if (fromIndex >= len) fromIndex = len - 1;
int found = -1;
for (char *p = buffer; p <= buffer + fromIndex; p++) {

+ 11
- 0
teensy3/WString.h View File

@@ -28,6 +28,10 @@
#include <ctype.h>
#include "avr_functions.h"

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

// When compiling programs with this class, the following gcc parameters
// dramatically increase performance and memory (RAM) efficiency, typically
// with little or no increase in code size.
@@ -196,6 +200,13 @@ protected:
void init(void);
unsigned char changeBuffer(unsigned int maxStrLen);
String & append(const char *cstr, unsigned int length);
private:
// allow for "if (s)" without the complications of an operator bool().
// for more information http://www.artima.com/cppsource/safebool.html
typedef void (String::*StringIfHelperType)() const;
void StringIfHelper() const {}
public:
operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; }
};

class StringSumHelper : public String

+ 142
- 110
teensy3/analog.c View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -10,10 +10,10 @@
* 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
* 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
* 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.
@@ -31,10 +31,6 @@
#include "core_pins.h"
//#include "HardwareSerial.h"

#if defined(__MK64FX512__) || defined(__MK66FX1M0__) // ugly hack for now...
#define __MK20DX256__
#endif

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

#if F_BUS == 60000000
#if F_BUS == 128000000
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(3) + ADC_CFG1_ADICLK(1) // 8 MHz
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 16 MHz
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 16 MHz
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 16 MHz
#elif F_BUS == 120000000
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(3) + ADC_CFG1_ADICLK(1) // 7.5 MHz
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 15 MHz
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 15 MHz
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 15 MHz
#elif F_BUS == 108000000
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(3) + ADC_CFG1_ADICLK(1) // 7 MHz
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 14 MHz
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 14 MHz
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 14 MHz
#elif F_BUS == 96000000
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 12 MHz
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 12 MHz
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 12 MHz
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 24 MHz
#elif F_BUS == 90000000
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 11.25 MHz
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 11.25 MHz
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 11.25 MHz
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 22.5 MHz
#elif F_BUS == 80000000
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 10 MHz
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 10 MHz
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 10 MHz
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 20 MHz
#elif F_BUS == 72000000
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 9 MHz
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 18 MHz
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 18 MHz
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 18 MHz
#elif F_BUS == 64000000
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 8 MHz
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 16 MHz
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 16 MHz
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 16 MHz
#elif F_BUS == 60000000
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 7.5 MHz
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 15 MHz
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 15 MHz
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 15 MHz
#elif F_BUS == 56000000
#elif F_BUS == 56000000 || F_BUS == 54000000
#define ADC_CFG1_16BIT ADC_CFG1_ADIV(2) + ADC_CFG1_ADICLK(1) // 7 MHz
#define ADC_CFG1_12BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 14 MHz
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 14 MHz
@@ -96,14 +131,14 @@ static uint8_t analog_reference_internal = 0;
#define ADC_CFG1_10BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 2 MHz
#define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 2 MHz
#else
#error "F_BUS must be 60, 56, 48, 40, 36, 24, 4 or 2 MHz"
#error "F_BUS must be 128, 120, 108, 96, 90, 80, 72, 64, 60, 56, 54, 48, 40, 36, 24, 4 or 2 MHz"
#endif

void analog_init(void)
{
uint32_t num;

#if defined(__MK20DX128__) || defined(__MK20DX256__)
#if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
VREF_TRM = 0x60;
VREF_SC = 0xE1; // enable 1.2 volt ref
#endif
@@ -111,28 +146,28 @@ void analog_init(void)
if (analog_config_bits == 8) {
ADC0_CFG1 = ADC_CFG1_8BIT + ADC_CFG1_MODE(0);
ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
#if defined(__MK20DX256__)
#ifdef HAS_KINETIS_ADC1
ADC1_CFG1 = ADC_CFG1_8BIT + ADC_CFG1_MODE(0);
ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
#endif
} else if (analog_config_bits == 10) {
ADC0_CFG1 = ADC_CFG1_10BIT + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP;
ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
#if defined(__MK20DX256__)
#ifdef HAS_KINETIS_ADC1
ADC1_CFG1 = ADC_CFG1_10BIT + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP;
ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
#endif
} else if (analog_config_bits == 12) {
ADC0_CFG1 = ADC_CFG1_12BIT + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP;
ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
#if defined(__MK20DX256__)
#ifdef HAS_KINETIS_ADC1
ADC1_CFG1 = ADC_CFG1_12BIT + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP;
ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
#endif
} else {
ADC0_CFG1 = ADC_CFG1_16BIT + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP;
ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
#if defined(__MK20DX256__)
#ifdef HAS_KINETIS_ADC1
ADC1_CFG1 = ADC_CFG1_16BIT + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP;
ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
#endif
@@ -144,7 +179,7 @@ void analog_init(void)
} else {
ADC0_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref
}
#elif defined(__MK20DX256__)
#elif defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
if (analog_reference_internal) {
ADC0_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref
ADC1_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref
@@ -163,27 +198,27 @@ void analog_init(void)
num = analog_num_average;
if (num <= 1) {
ADC0_SC3 = ADC_SC3_CAL; // begin cal
#if defined(__MK20DX256__)
#ifdef HAS_KINETIS_ADC1
ADC1_SC3 = ADC_SC3_CAL; // begin cal
#endif
} else if (num <= 4) {
ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0);
#if defined(__MK20DX256__)
#ifdef HAS_KINETIS_ADC1
ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0);
#endif
} else if (num <= 8) {
ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1);
#if defined(__MK20DX256__)
#ifdef HAS_KINETIS_ADC1
ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1);
#endif
} else if (num <= 16) {
ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2);
#if defined(__MK20DX256__)
#ifdef HAS_KINETIS_ADC1
ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2);
#endif
} else {
ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3);
#if defined(__MK20DX256__)
#ifdef HAS_KINETIS_ADC1
ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3);
#endif
}
@@ -195,12 +230,12 @@ static void wait_for_cal(void)
uint16_t sum;

//serial_print("wait_for_cal\n");
#if defined(__MK20DX128__)
while (ADC0_SC3 & ADC_SC3_CAL) {
#if defined(HAS_KINETIS_ADC0) && defined(HAS_KINETIS_ADC1)
while ((ADC0_SC3 & ADC_SC3_CAL) || (ADC1_SC3 & ADC_SC3_CAL)) {
// wait
}
#elif defined(__MK20DX256__)
while ((ADC0_SC3 & ADC_SC3_CAL) || (ADC1_SC3 & ADC_SC3_CAL)) {
#elif defined(HAS_KINETIS_ADC0)
while (ADC0_SC3 & ADC_SC3_CAL) {
// wait
}
#endif
@@ -219,7 +254,7 @@ static void wait_for_cal(void)
//serial_print("ADC0_MG = ");
//serial_phex16(sum);
//serial_print("\n");
#if defined(__MK20DX256__)
#ifdef HAS_KINETIS_ADC1
sum = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0;
sum = (sum / 2) | 0x8000;
ADC1_PG = sum;
@@ -236,7 +271,7 @@ static void wait_for_cal(void)
// VREFH/VREFL - connected as the primary reference option
// 1.2 V VREF_OUT - connected as the VALT reference option

#if defined(__MK20DX128__) || defined(__MK20DX256__)
#if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
#define DEFAULT 0
#define INTERNAL 2
#define INTERNAL1V2 2
@@ -257,7 +292,7 @@ void analogReference(uint8_t type)
analog_reference_internal = 1;
if (calibrating) {
ADC0_SC3 = 0; // cancel cal
#if defined(__MK20DX256__)
#ifdef HAS_KINETIS_ADC1
ADC1_SC3 = 0; // cancel cal
#endif
}
@@ -269,7 +304,7 @@ void analogReference(uint8_t type)
analog_reference_internal = 0;
if (calibrating) {
ADC0_SC3 = 0; // cancel cal
#if defined(__MK20DX256__)
#ifdef HAS_KINETIS_ADC1
ADC1_SC3 = 0; // cancel cal
#endif
}
@@ -296,7 +331,12 @@ void analogReadRes(unsigned int bits)
analog_right_shift = config - bits;
if (config != analog_config_bits) {
analog_config_bits = config;
if (calibrating) ADC0_SC3 = 0; // cancel cal
if (calibrating) {
ADC0_SC3 = 0; // cancel cal
#ifdef HAS_KINETIS_ADC1
ADC1_SC3 = 0;
#endif
}
analog_init();
}
}
@@ -311,15 +351,27 @@ void analogReadAveraging(unsigned int num)
} else if (num <= 4) {
num = 4;
ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(0);
#ifdef HAS_KINETIS_ADC1
ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(0);
#endif
} else if (num <= 8) {
num = 8;
ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(1);
#ifdef HAS_KINETIS_ADC1
ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(1);
#endif
} else if (num <= 16) {
num = 16;
ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(2);
#ifdef HAS_KINETIS_ADC1
ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(2);
#endif
} else {
num = 32;
ADC0_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(3);
#ifdef HAS_KINETIS_ADC1
ADC1_SC3 = ADC_SC3_AVGE + ADC_SC3_AVGS(3);
#endif
}
analog_num_average = num;
}
@@ -327,98 +379,77 @@ void analogReadAveraging(unsigned int num)
// The SC1A register is used for both software and hardware trigger modes of operation.

#if defined(__MK20DX128__)
static const uint8_t channel2sc1a[] = {
5, 14, 8, 9, 13, 12, 6, 7, 15, 4,
0, 19, 3, 21, 26, 22, 23
static const uint8_t pin2sc1a[] = {
5, 14, 8, 9, 13, 12, 6, 7, 15, 4, 0, 19, 3, 21, // 0-13 -> A0-A13
5, 14, 8, 9, 13, 12, 6, 7, 15, 4, // 14-23 are A0-A9
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 24-33 are digital only
0, 19, 3, 21, // 34-37 are A10-A13
26, // 38 is temp sensor
22, // 39 is vref
23 // 40 is unused analog pin
};
#elif defined(__MK20DX256__)
static const uint8_t channel2sc1a[] = {
5, 14, 8, 9, 13, 12, 6, 7, 15, 4,
0, 19, 3, 19+128, 26, 18+128, 23,
5+192, 5+128, 4+128, 6+128, 7+128, 4+192
// A15 26 E1 ADC1_SE5a 5+64
// A16 27 C9 ADC1_SE5b 5
// A17 28 C8 ADC1_SE4b 4
// A18 29 C10 ADC1_SE6b 6
// A19 30 C11 ADC1_SE7b 7
// A20 31 E0 ADC1_SE4a 4+64
static const uint8_t pin2sc1a[] = {
5, 14, 8, 9, 13, 12, 6, 7, 15, 4, 0, 19, 3, 19+128, // 0-13 -> A0-A13
5, 14, 8, 9, 13, 12, 6, 7, 15, 4, // 14-23 are A0-A9
255, 255, // 24-25 are digital only
5+192, 5+128, 4+128, 6+128, 7+128, 4+192, // 26-31 are A15-A20
255, 255, // 32-33 are digital only
0, 19, 3, 19+128, // 34-37 are A10-A13
26, // 38 is temp sensor,
18+128, // 39 is vref
23 // 40 is A14
};
#elif defined(__MKL26Z64__)
static const uint8_t channel2sc1a[] = {
5, 14, 8, 9, 13, 12, 6, 7, 15, 11,
0, 4+64, 23, 26, 27
static const uint8_t pin2sc1a[] = {
5, 14, 8, 9, 13, 12, 6, 7, 15, 11, 0, 4+64, 23, // 0-12 -> A0-A12
255, // 13 is digital only (no A13 alias)
5, 14, 8, 9, 13, 12, 6, 7, 15, 11, 0, 4+64, 23, // 14-26 are A0-A12
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 27-37 unused
26, // 38=temperature
27 // 39=bandgap ref (PMC_REGSC |= PMC_REGSC_BGBE)
};
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
static const uint8_t pin2sc1a[] = {
5, 14, 8, 9, 13, 12, 6, 7, 15, 4, 3, 19+128, 14+128, 15+128, // 0-13 -> A0-A13
5, 14, 8, 9, 13, 12, 6, 7, 15, 4, // 14-23 are A0-A9
255, 255, 255, 255, 255, 255, 255, // 24-30 are digital only
14+128, 15+128, 17, 18, 4+128, 5+128, 6+128, 7+128, 17+128, // 31-39 are A12-A20
255, 255, 255, 255, 255, 255, 255, 255, 255, // 40-48 are digital only
10+128, 11+128, // 49-50 are A23-A24
255, 255, 255, 255, 255, 255, 255, // 51-57 are digital only
255, 255, 255, 255, 255, 255, // 58-63 (sd card pins) are digital only
3, 19+128, // 64-65 are A10-A11
23, 23+128,// 66-67 are A21-A22 (DAC pins)
1, 1+128, // 68-69 are A25-A26 (unused USB host port on Teensy 3.5)
26, // 70 is Temperature Sensor
18+128 // 71 is Vref
};


#endif



// TODO: perhaps this should store the NVIC priority, so it works recursively?
static volatile uint8_t analogReadBusyADC0 = 0;
#if defined(__MK20DX256__)
#ifdef HAS_KINETIS_ADC1
static volatile uint8_t analogReadBusyADC1 = 0;
#endif

int analogRead(uint8_t pin)
{
int result;
uint8_t index, channel;
uint8_t channel;

//serial_phex(pin);
//serial_print(" ");

#if defined(__MK20DX128__)
if (pin <= 13) {
index = pin; // 0-13 refer to A0-A13
} else if (pin <= 23) {
index = pin - 14; // 14-23 are A0-A9
} else if (pin >= 34 && pin <= 40) {
index = pin - 24; // 34-37 are A10-A13, 38 is temp sensor,
// 39 is vref, 40 is unused analog pin
} else {
return 0;
}
#elif defined(__MK20DX256__)
if (pin <= 13) {
index = pin; // 0-13 refer to A0-A13
} else if (pin <= 23) {
index = pin - 14; // 14-23 are A0-A9
} else if (pin >= 26 && pin <= 31) {
index = pin - 9; // 26-31 are A15-A20
} else if (pin >= 34 && pin <= 40) {
index = pin - 24; // 34-37 are A10-A13, 38 is temp sensor,
// 39 is vref, 40 is A14
} else {
return 0;
}
#elif defined(__MKL26Z64__)
if (pin <= 12) {
index = pin; // 0-12 refer to A0-A12
} else if (pin >= 14 && pin <= 26) {
index = pin - 14; // 14-26 are A0-A12
} else if (pin >= 38 && pin <= 39) {
index = pin - 25; // 38=temperature
// 39=bandgap ref (PMC_REGSC |= PMC_REGSC_BGBE)
} else {
return 0;
}

#endif

//serial_phex(index);
//serial_print(" ");
if (pin >= sizeof(pin2sc1a)) return 0;
channel = pin2sc1a[pin];
if (channel == 255) return 0;

channel = channel2sc1a[index];
//serial_phex(channel);
//serial_print(" ");

//serial_print("analogRead");
//return 0;
if (calibrating) wait_for_cal();
//pin = 5; // PTD1/SE5b, pin 14, analog 0

#if defined(__MK20DX256__)
#ifdef HAS_KINETIS_ADC1
if (channel & 0x80) goto beginADC1;
#endif

@@ -453,11 +484,11 @@ startADC0:
yield();
}

#if defined(__MK20DX256__)
#ifdef HAS_KINETIS_ADC1
beginADC1:
__disable_irq();
startADC1:
//serial_print("startADC0\n");
//serial_print("startADC1\n");
// ADC1_CFG2[MUXSEL] bit selects between ADCx_SEn channels a and b.
if (channel & 0x40) {
ADC1_CFG2 &= ~ADC_CFG2_MUXSEL;
@@ -486,20 +517,20 @@ startADC1:
#endif
}

typedef int16_t __attribute__((__may_alias__)) aliased_int16_t;

void analogWriteDAC0(int val)
{
#if defined(__MK20DX256__)
#if defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
SIM_SCGC2 |= SIM_SCGC2_DAC0;
if (analog_reference_internal) {
DAC0_C0 = DAC_C0_DACEN; // 1.2V ref is DACREF_1
} else {
DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2
}
if (val < 0) val = 0; // TODO: saturate instruction?
else if (val > 4095) val = 4095;
*(int16_t *)&(DAC0_DAT0L) = val;
__asm__ ("usat %[value], #12, %[value]\n\t" : [value] "+r" (val)); // 0 <= val <= 4095
*(volatile aliased_int16_t *)&(DAC0_DAT0L) = val;
#elif defined(__MKL26Z64__)
SIM_SCGC6 |= SIM_SCGC6_DAC0;
if (analog_reference_internal == 0) {
@@ -511,7 +542,8 @@ void analogWriteDAC0(int val)
}
if (val < 0) val = 0;
else if (val > 4095) val = 4095;
*(int16_t *)&(DAC0_DAT0L) = val;

*(volatile aliased_int16_t *)&(DAC0_DAT0L) = val;
#endif
}

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


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

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

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

#ifndef _AVR_EEPROM_H_
#define _AVR_EEPROM_H_ 1


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

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

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

@@ -75,19 +75,57 @@ typedef uint64_t prog_uint64_t;
#define vsprintf_P(s, ...) vsprintf((s), __VA_ARGS__)
#define vsnprintf_P(s, n, ...) vsnprintf((s), (n), __VA_ARGS__)
#define fprintf_P(fp, ...) fprintf((fp), __VA_ARGS__)
#define strlen_PF(a) strlen((a))
#define strnlen_PF(src, len) strnlen((src), (len))
#define memcpy_PF(dest, src, len) memcpy((dest), (src), (len))
#define strcpy_PF(dest, src) strcpy((dest), (src))
#define strncpy_PF(dest, src, len) strncpy((dest), (src), (len))
#define strcat_PF(dest, src) strcat((dest), (src))
#define strlcat_PF(dest, src, len) strlcat((dest), (src), (len))
#define strncat_PF(dest, src, len) strncat((dest), (src), (len))
#define strcmp_PF(s1, s2) strcmp((s1), (s2))
#define strncmp_PF(s1, s2, n) strncmp((s1), (s2), (n))
#define strcasecmp_PF(s1, s2) strcasecmp((s1), (s2))
#define strncasecmp_PF(s1, s2, n) strncasecmp((s1), (s2), (n))
#define strstr_PF(s1, s2) strstr((s1), (s2))
#define strlcpy_PF(dest, src, n) strlcpy((dest), (src), (n))
#define memcmp_PF(s1, s2, n) memcmp((s1), (s2), (n))


#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#if 0
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
#define pgm_read_dword(addr) (*(const unsigned long *)(addr))
#define pgm_read_float(addr) (*(const float *)(addr))
#else
#define pgm_read_word(addr) ({ \
typeof(addr) _addr = (addr); \
*(const unsigned short *)(_addr); \
})
#define pgm_read_dword(addr) ({ \
typeof(addr) _addr = (addr); \
*(const unsigned long *)(_addr); \
})
#define pgm_read_float(addr) ({ \
typeof(addr) _addr = (addr); \
*(const float *)(_addr); \
})
#define pgm_read_ptr(addr) ({ \
typeof(addr) _addr = (addr); \
*(void * const *)(_addr); \
})
#endif


#define pgm_read_byte_near(addr) pgm_read_byte(addr)
#define pgm_read_word_near(addr) pgm_read_word(addr)
#define pgm_read_dword_near(addr) pgm_read_dword(addr)
#define pgm_read_float_near(addr) pgm_read_float(addr)
#define pgm_read_ptr_near(addr) pgm_read_ptr(addr)
#define pgm_read_byte_far(addr) pgm_read_byte(addr)
#define pgm_read_word_far(addr) pgm_read_word(addr)
#define pgm_read_dword_far(addr) pgm_read_dword(addr)
#define pgm_read_float_far(addr) pgm_read_float(addr)
#define pgm_read_ptr_far(addr) pgm_read_ptr(addr)

#endif

+ 2
- 2
teensy3/avr/sleep.h View File

@@ -33,9 +33,9 @@
#define set_sleep_mode(mode) // TODO: actually set the mode...
#define sleep_enable()
#define sleep_disable()
#define sleep_cpu() (asm("wfi"))
#define sleep_cpu() ({__asm__ volatile("wfi");})
#define sleep_bod_disable()
#define sleep_mode() sleep_cpu()
#define sleep_mode() ({__asm__ volatile("wfi");})

// workaround for early versions of Nordic's BLE library
// EIMSK moved to a dummy byte in avr_emulation...

+ 2
- 0
teensy3/avr/wdt.h View File

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

#ifndef _AVR_WDT_H_
#define _AVR_WDT_H_


+ 12
- 5
teensy3/avr_emulation.cpp View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -10,10 +10,10 @@
* 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
* 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
* 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.
@@ -29,14 +29,21 @@
*/


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

uint8_t SPCRemulation::pinout = 0;
SPCRemulation SPCR;
#if defined(KINETISL)
uint8_t SPCR1emulation::pinout = 0;
SPCR1emulation SPCR1;
#endif
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
uint8_t SPCR1emulation::pinout = 0;
SPCR1emulation SPCR1;
uint8_t SPCR2emulation::pinout = 0;
SPCR2emulation SPCR2;
#endif

#ifdef HAS_SPIFIFO

uint8_t SPIFIFOclass::pcs = 0;

+ 771
- 47
teensy3/avr_emulation.h View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -590,22 +590,22 @@ class PINCemulation
public:
inline int operator & (int val) const __attribute__((always_inline)) {
int ret = 0;
if ((val & (1<<0)) && digitalReadFast(8)) ret |= (1<<0);
if ((val & (1<<1)) && digitalReadFast(9)) ret |= (1<<1);
if ((val & (1<<2)) && digitalReadFast(10)) ret |= (1<<2);
if ((val & (1<<3)) && digitalReadFast(11)) ret |= (1<<3);
if ((val & (1<<4)) && digitalReadFast(12)) ret |= (1<<4);
if ((val & (1<<5)) && digitalReadFast(13)) ret |= (1<<5);
if ((val & (1<<0)) && digitalReadFast(14)) ret |= (1<<0);
if ((val & (1<<1)) && digitalReadFast(15)) ret |= (1<<1);
if ((val & (1<<2)) && digitalReadFast(16)) ret |= (1<<2);
if ((val & (1<<3)) && digitalReadFast(17)) ret |= (1<<3);
if ((val & (1<<4)) && digitalReadFast(18)) ret |= (1<<4);
if ((val & (1<<5)) && digitalReadFast(19)) ret |= (1<<5);
return ret;
}
operator int () const __attribute__((always_inline)) {
int ret = 0;
if (digitalReadFast(8)) ret |= (1<<0);
if (digitalReadFast(9)) ret |= (1<<1);
if (digitalReadFast(10)) ret |= (1<<2);
if (digitalReadFast(11)) ret |= (1<<3);
if (digitalReadFast(12)) ret |= (1<<4);
if (digitalReadFast(13)) ret |= (1<<5);
if (digitalReadFast(14)) ret |= (1<<0);
if (digitalReadFast(15)) ret |= (1<<1);
if (digitalReadFast(16)) ret |= (1<<2);
if (digitalReadFast(17)) ret |= (1<<3);
if (digitalReadFast(18)) ret |= (1<<4);
if (digitalReadFast(19)) ret |= (1<<5);
return ret;
}
};
@@ -884,16 +884,31 @@ public:
uint32_t ctar = SPI0_CTAR0;
if (val & (1<<DORD)) ctar |= SPI_CTAR_LSBFE; // TODO: use bitband
if (val & (1<<CPOL)) ctar |= SPI_CTAR_CPOL;
if ((val & 3) == 1) {
// TODO: implement - is this ever really needed
} else if ((val & 3) == 2) {
// TODO: implement - is this ever really needed
} else if ((val & 3) == 3) {
// TODO: implement - is this ever really needed
}
if (val & (1<<CPHA) && !(ctar & SPI_CTAR_CPHA)) {
ctar |= SPI_CTAR_CPHA;
// TODO: clear SPI_CTAR_CSSCK, set SPI_CTAR_ASC
ctar &= 0xFFFF00FF;
ctar |= SPI_CTAR_ASC(ctar & 15);
}
if ((val & 3) != 0) {
uint32_t br = ctar & 15;
uint32_t priorval;
if (br <= 1) priorval = 0;
else if (br <= 4) priorval = 1;
else if (br <= 6) priorval = 2;
else priorval = 3;
uint32_t newval = priorval | (val & 3);
if (newval != priorval) {
if (newval == 0) br = 1;
else if (newval == 0) br = 4;
else if (newval == 0) br = 6;
else br = 7;
ctar &= 0xFFFF00F0; // clear BR, ASC, CSSCK
if ((ctar & SPI_CTAR_CPHA)) {
ctar |= SPI_CTAR_BR(br) | SPI_CTAR_ASC(br);
} else {
ctar |= SPI_CTAR_BR(br) | SPI_CTAR_CSSCK(br);
}
}
}
update_ctar(ctar);
}
@@ -922,16 +937,31 @@ public:
uint32_t ctar = SPI0_CTAR0;
if (!(val & (1<<DORD))) ctar &= ~SPI_CTAR_LSBFE; // TODO: use bitband
if (!(val & (1<<CPOL))) ctar &= ~SPI_CTAR_CPOL;
if ((val & 3) == 0) {
// TODO: implement - is this ever really needed
} else if ((val & 3) == 1) {
// TODO: implement - is this ever really needed
} else if ((val & 3) == 2) {
// TODO: implement - is this ever really needed
}
if (!(val & (1<<CPHA)) && (ctar & SPI_CTAR_CPHA)) {
ctar &= ~SPI_CTAR_CPHA;
// TODO: set SPI_CTAR_ASC, clear SPI_CTAR_CSSCK
ctar &= 0xFFFF00FF;
ctar |= SPI_CTAR_CSSCK(ctar & 15);
}
if ((val & 3) != 3) {
uint32_t br = ctar & 15;
uint32_t priorval;
if (br <= 1) priorval = 0;
else if (br <= 4) priorval = 1;
else if (br <= 6) priorval = 2;
else priorval = 3;
uint32_t newval = priorval & (val & 3);
if (newval != priorval) {
if (newval == 0) br = 1;
else if (newval == 0) br = 4;
else if (newval == 0) br = 6;
else br = 7;
ctar &= 0xFFFF00F0; // clear BR, ASC, CSSCK
if ((ctar & SPI_CTAR_CPHA)) {
ctar |= SPI_CTAR_BR(br) | SPI_CTAR_ASC(br);
} else {
ctar |= SPI_CTAR_BR(br) | SPI_CTAR_CSSCK(br);
}
}
}
update_ctar(ctar);
}
@@ -947,20 +977,19 @@ public:
if ((val & (1<<DORD)) && (SPI0_CTAR0 & SPI_CTAR_LSBFE)) ret |= (1<<DORD);
if ((val & (1<<CPOL)) && (SPI0_CTAR0 & SPI_CTAR_CPOL)) ret |= (1<<CPOL);
if ((val & (1<<CPHA)) && (SPI0_CTAR0 & SPI_CTAR_CPHA)) ret |= (1<<CPHA);
if ((val & 3) == 3) {
if ((val & 3) != 0) {
uint32_t dbr = SPI0_CTAR0 & 15;
uint32_t spr10;
if (dbr <= 1) {
spr10 = 0;
} else if (dbr <= 4) {
ret |= (1<<SPR0);
spr10 |= (1<<SPR0);
} else if (dbr <= 6) {
ret |= (1<<SPR1);
spr10 |= (1<<SPR1);
} else {
ret |= (1<<SPR1)|(1<<SPR0);
spr10 |= (1<<SPR1)|(1<<SPR0);
}
} else if ((val & 3) == 1) {
// TODO: implement - is this ever really needed
} else if ((val & 3) == 2) {
// TODO: implement - is this ever really needed
ret |= spr10 & (val & 3);
}
if (val & (1<<SPE) && (!(SPI0_MCR & SPI_MCR_MDIS))) ret |= (1<<SPE);
if (val & (1<<MSTR) && (SPI0_MCR & SPI_MCR_MSTR)) ret |= (1<<MSTR);
@@ -992,16 +1021,145 @@ public:
return ret;
}
inline void setMOSI(uint8_t pin) __attribute__((always_inline)) {
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
uint8_t newpinout = pinout;
// More than two options so now 2 bits
if (pin == 11) newpinout &= ~3;
if (pin == 7) newpinout =(newpinout & ~0x3) | 1;
if (pin == 28) newpinout = (newpinout & ~0x3) | 2;
if ((SIM_SCGC6 & SIM_SCGC6_SPI0) && newpinout != pinout) {
// First unconfigure previous pin
switch (pinout & 3) {
case 0: CORE_PIN11_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); break;
case 1: CORE_PIN7_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); break;
default: CORE_PIN28_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
}
switch (newpinout & 3) {
case 0: CORE_PIN11_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2); break;
case 1: CORE_PIN7_CONFIG = PORT_PCR_MUX(2); break;
default: CORE_PIN28_CONFIG = PORT_PCR_MUX(2);
}
}
pinout = newpinout;
#else
uint8_t newpinout = pinout;
if (pin == 11) newpinout &= ~1;
if (pin == 7) newpinout |= 1;
if ((SIM_SCGC6 & SIM_SCGC6_SPI0) && newpinout != pinout) {
if ((newpinout & 1) == 0) {
CORE_PIN7_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
CORE_PIN11_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2);
} else {
CORE_PIN11_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
CORE_PIN7_CONFIG = PORT_PCR_MUX(2);
}
}
pinout = newpinout;
#endif
}
inline void setMOSI_soft(uint8_t pin) __attribute__((always_inline)) {
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
if (pin == 11) pinout &= ~3;
if (pin == 7) pinout = (pinout & ~0x3) | 1;
if (pin == 28) pinout = (pinout & ~0x3) | 2;
#else
if (pin == 11) pinout &= ~1;
if (pin == 7) pinout |= 1;
if (pin == 7) pinout |= 1;
#endif
}
inline void setMISO(uint8_t pin) __attribute__((always_inline)) {
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
uint8_t newpinout = pinout;
// More than two options so now 2 bits
if (pin == 12) newpinout &= ~0xc;
if (pin == 8) newpinout =(newpinout & ~0xc) | 4;
if (pin == 39) newpinout = (newpinout & ~0xc) | 8;
if ((SIM_SCGC6 & SIM_SCGC6_SPI0) && newpinout != pinout) {
// First unconfigure previous pin
switch (pinout & 0xc) {
case 0: CORE_PIN12_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); break;
case 0x4: CORE_PIN8_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); break;
default: CORE_PIN39_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
}
switch (newpinout & 0xc) {
case 0: CORE_PIN12_CONFIG = PORT_PCR_MUX(2); break;
case 0x4: CORE_PIN8_CONFIG = PORT_PCR_MUX(2); break;
default: CORE_PIN39_CONFIG = PORT_PCR_MUX(2);
}
}
pinout = newpinout;
#else
uint8_t newpinout = pinout;
if (pin == 12) newpinout &= ~2;
if (pin == 8) newpinout |= 2;
if ((SIM_SCGC6 & SIM_SCGC6_SPI0) && newpinout != pinout) {
if ((newpinout & 2) == 0) {
CORE_PIN8_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
CORE_PIN12_CONFIG = PORT_PCR_MUX(2);
} else {
CORE_PIN12_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
CORE_PIN8_CONFIG = PORT_PCR_MUX(2);
}
}
pinout = newpinout;
#endif
}
inline void setMISO_soft(uint8_t pin) __attribute__((always_inline)) {
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
if (pin == 12) pinout &= ~0xc;
if (pin == 8) pinout = (pinout & ~0xc) | 4;
if (pin == 39) pinout = (pinout & ~0xc) | 8;
#else
if (pin == 12) pinout &= ~2;
if (pin == 8) pinout |= 2;
if (pin == 8) pinout |= 2;
#endif
}
inline void setSCK(uint8_t pin) __attribute__((always_inline)) {
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
uint8_t newpinout = pinout;
// More than two options so now 2 bits
if (pin == 13) newpinout &= ~0x30;
if (pin == 14) newpinout =(newpinout & ~0x30) | 0x10;
if (pin == 27) newpinout = (newpinout & ~0x30) | 0x20;
if ((SIM_SCGC6 & SIM_SCGC6_SPI0) && newpinout != pinout) {
// First unconfigure previous pin
switch (pinout & 0x30) {
case 0: CORE_PIN13_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); break;
case 0x10: CORE_PIN14_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); break;
default: CORE_PIN27_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
}
switch (newpinout & 0x30) {
case 0: CORE_PIN13_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2); break;
case 0x10: CORE_PIN14_CONFIG = PORT_PCR_MUX(2); break;
default: CORE_PIN27_CONFIG = PORT_PCR_MUX(2);
}
}
pinout = newpinout;
#else
uint8_t newpinout = pinout;
if (pin == 13) newpinout &= ~4;
if (pin == 14) newpinout |= 4;
if ((SIM_SCGC6 & SIM_SCGC6_SPI0) && newpinout != pinout) {
if ((newpinout & 4) == 0) {
CORE_PIN14_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
CORE_PIN13_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2);
} else {
CORE_PIN13_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
CORE_PIN14_CONFIG = PORT_PCR_MUX(2);
}
}
pinout = newpinout;
#endif
}
inline void setSCK_soft(uint8_t pin) __attribute__((always_inline)) {
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
if (pin == 13) pinout &= ~0x30;
if (pin == 14) pinout = (pinout & ~0x30) | 0x10;
if (pin == 27) pinout = (pinout & ~0x30) | 0x20;
#else
if (pin == 13) pinout &= ~4;
if (pin == 14) pinout |= 4;
#endif
}
friend class SPSRemulation;
friend class SPIFIFOclass;
@@ -1021,6 +1179,23 @@ private:
public:
inline void enable_pins(void) __attribute__((always_inline)) {
//serial_print("enable_pins\n");
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
switch (pinout & 3) {
case 0: CORE_PIN11_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2); break;
case 1: CORE_PIN7_CONFIG = PORT_PCR_MUX(2); break;
default: CORE_PIN28_CONFIG = PORT_PCR_MUX(2);
}
switch (pinout & 0xc) {
case 0: CORE_PIN12_CONFIG = PORT_PCR_MUX(2); break;
case 0x4: CORE_PIN8_CONFIG = PORT_PCR_MUX(2); break;
default: CORE_PIN39_CONFIG = PORT_PCR_MUX(2);
}
switch (pinout & 0x30) {
case 0: CORE_PIN13_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2); break;
case 0x10: CORE_PIN14_CONFIG = PORT_PCR_MUX(2); break;
default: CORE_PIN27_CONFIG = PORT_PCR_MUX(2);
}
#else
if ((pinout & 1) == 0) {
CORE_PIN11_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2); // DOUT/MOSI = 11 (PTC6)
} else {
@@ -1036,8 +1211,27 @@ public:
} else {
CORE_PIN14_CONFIG = PORT_PCR_MUX(2); // SCK = 14 (PTD1)
}
#endif
}
inline void disable_pins(void) __attribute__((always_inline)) {
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
switch (pinout & 3) {
case 0: CORE_PIN11_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); break;
case 1: CORE_PIN7_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); break;
default: CORE_PIN28_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
}

switch (pinout & 0xc) {
case 0: CORE_PIN12_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); break;
case 0x4: CORE_PIN8_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); break;
default: CORE_PIN39_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
}
switch (pinout & 0x30) {
case 0: CORE_PIN13_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); break;
case 0x10: CORE_PIN14_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); break;
default: CORE_PIN27_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
}
#else
//serial_print("disable_pins\n");
if ((pinout & 1) == 0) {
CORE_PIN11_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
@@ -1054,10 +1248,507 @@ public:
} else {
CORE_PIN14_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
}
#endif
}
};
extern SPCRemulation SPCR;

#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
class SPCR1emulation
{
public:
inline SPCR1emulation & operator = (int val) __attribute__((always_inline)) {
uint32_t ctar, mcr, sim6;
//serial_print("SPCR=");
//serial_phex(val);
//serial_print("\n");
sim6 = SIM_SCGC6;
if (!(sim6 & SIM_SCGC6_SPI1)) {
//serial_print("init1\n");
SIM_SCGC6 = sim6 | SIM_SCGC6_SPI1;
SPI1_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
}
if (!(val & (1<<SPE))) {
SPI1_MCR |= SPI_MCR_MDIS; // TODO: use bitband for atomic access
}
ctar = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1);
if (val & (1<<DORD)) ctar |= SPI_CTAR_LSBFE;
if (val & (1<<CPOL)) ctar |= SPI_CTAR_CPOL;
if (val & (1<<CPHA)) {
ctar |= SPI_CTAR_CPHA;
if ((val & 3) == 0) {
ctar |= SPI_CTAR_BR(1) | SPI_CTAR_ASC(1);
} else if ((val & 3) == 1) {
ctar |= SPI_CTAR_BR(4) | SPI_CTAR_ASC(4);
} else if ((val & 3) == 2) {
ctar |= SPI_CTAR_BR(6) | SPI_CTAR_ASC(6);
} else {
ctar |= SPI_CTAR_BR(7) | SPI_CTAR_ASC(7);
}
} else {
if ((val & 3) == 0) {
ctar |= SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
} else if ((val & 3) == 1) {
ctar |= SPI_CTAR_BR(4) | SPI_CTAR_CSSCK(4);
} else if ((val & 3) == 2) {
ctar |= SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(6);
} else {
ctar |= SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(7);
}
}
ctar |= (SPI1_CTAR0 & SPI_CTAR_DBR);
update_ctar(ctar);
mcr = SPI_MCR_DCONF(0) | SPI_MCR_PCSIS(0x1F);
if (val & (1<<MSTR)) mcr |= SPI_MCR_MSTR;
if (val & (1<<SPE)) {
mcr &= ~(SPI_MCR_MDIS | SPI_MCR_HALT);
SPI1_MCR = mcr;
enable_pins();
} else {
mcr |= (SPI_MCR_MDIS | SPI_MCR_HALT);
SPI1_MCR = mcr;
disable_pins();
}
//serial_print("MCR:");
//serial_phex32(SPI1_MCR);
//serial_print(", CTAR0:");
//serial_phex32(SPI1_CTAR0);
//serial_print("\n");
return *this;
}
inline SPCR1emulation & operator |= (int val) __attribute__((always_inline)) {
uint32_t sim6;
//serial_print("SPCR |= ");
//serial_phex(val);
//serial_print("\n");
sim6 = SIM_SCGC6;
if (!(sim6 & SIM_SCGC6_SPI1)) {
//serial_print("init2\n");
SIM_SCGC6 = sim6 | SIM_SCGC6_SPI1;
SPI1_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1) | SPI_CTAR_BR(1);
}
if (val & ((1<<DORD)|(1<<CPOL)|(1<<CPHA)|3)) {
uint32_t ctar = SPI1_CTAR0;
if (val & (1<<DORD)) ctar |= SPI_CTAR_LSBFE; // TODO: use bitband
if (val & (1<<CPOL)) ctar |= SPI_CTAR_CPOL;
if ((val & 3) == 1) {
// TODO: implement - is this ever really needed
} else if ((val & 3) == 2) {
// TODO: implement - is this ever really needed
} else if ((val & 3) == 3) {
// TODO: implement - is this ever really needed
}
if (val & (1<<CPHA) && !(ctar & SPI_CTAR_CPHA)) {
ctar |= SPI_CTAR_CPHA;
// TODO: clear SPI_CTAR_CSSCK, set SPI_CTAR_ASC
}
update_ctar(ctar);
}
if (val & (1<<MSTR)) SPI1_MCR |= SPI_MCR_MSTR;
if (val & (1<<SPE)) {
SPI1_MCR &= ~(SPI_MCR_MDIS | SPI_MCR_HALT);
enable_pins();
}
//serial_print("MCR:");
//serial_phex32(SPI1_MCR);
//serial_print(", CTAR0:");
//serial_phex32(SPI1_CTAR0);
//serial_print("\n");
return *this;
}
inline SPCR1emulation & operator &= (int val) __attribute__((always_inline)) {
//serial_print("SPCR &= ");
//serial_phex(val);
//serial_print("\n");
SIM_SCGC6 |= SIM_SCGC6_SPI1;
if (!(val & (1<<SPE))) {
SPI1_MCR |= (SPI_MCR_MDIS | SPI_MCR_HALT);
disable_pins();
}
if ((val & ((1<<DORD)|(1<<CPOL)|(1<<CPHA)|3)) != ((1<<DORD)|(1<<CPOL)|(1<<CPHA)|3)) {
uint32_t ctar = SPI1_CTAR0;
if (!(val & (1<<DORD))) ctar &= ~SPI_CTAR_LSBFE; // TODO: use bitband
if (!(val & (1<<CPOL))) ctar &= ~SPI_CTAR_CPOL;
if ((val & 3) == 0) {
// TODO: implement - is this ever really needed
} else if ((val & 3) == 1) {
// TODO: implement - is this ever really needed
} else if ((val & 3) == 2) {
// TODO: implement - is this ever really needed
}
if (!(val & (1<<CPHA)) && (ctar & SPI_CTAR_CPHA)) {
ctar &= ~SPI_CTAR_CPHA;
// TODO: set SPI_CTAR_ASC, clear SPI_CTAR_CSSCK
}
update_ctar(ctar);
}
if (!(val & (1<<MSTR))) SPI1_MCR &= ~SPI_MCR_MSTR;
return *this;
}
inline int operator & (int val) const __attribute__((always_inline)) {
int ret = 0;
//serial_print("SPCR & ");
//serial_phex(val);
//serial_print(" MCR:");
//serial_phex32(SPI1_MCR);
//serial_print(", CTAR0:");
//serial_phex32(SPI1_CTAR0);
//serial_print("\n");

//serial_print("\n");
SIM_SCGC6 |= SIM_SCGC6_SPI1;
if ((val & (1<<DORD)) && (SPI1_CTAR0 & SPI_CTAR_LSBFE)) ret |= (1<<DORD);
if ((val & (1<<CPOL)) && (SPI1_CTAR0 & SPI_CTAR_CPOL)) ret |= (1<<CPOL);
if ((val & (1<<CPHA)) && (SPI1_CTAR0 & SPI_CTAR_CPHA)) ret |= (1<<CPHA);
if ((val & 3) == 3) {
uint32_t dbr = SPI1_CTAR0 & 15;
if (dbr <= 1) {
} else if (dbr <= 4) {
ret |= (1<<SPR0);
} else if (dbr <= 6) {
ret |= (1<<SPR1);
} else {
ret |= (1<<SPR1)|(1<<SPR0);
}
} else if ((val & 3) == 1) {
// TODO: implement - is this ever really needed
} else if ((val & 3) == 2) {
// TODO: implement - is this ever really needed
}
if (val & (1<<SPE) && (!(SPI1_MCR & SPI_MCR_MDIS))) ret |= (1<<SPE);
if (val & (1<<MSTR) && (SPI1_MCR & SPI_MCR_MSTR)) ret |= (1<<MSTR);
//serial_print("ret = ");
//serial_phex(ret);
//serial_print("\n");
return ret;
}
inline void setMOSI(uint8_t pin) __attribute__((always_inline)) {
// More options, so 2 bits
pinout &= ~3;
switch (pin) {
case 0: break;
case 21: pinout |= 1; break;
case 61: pinout |= 2; break;
case 59: pinout |= 3; break;
}
}
inline void setMISO(uint8_t pin) __attribute__((always_inline)) {
// More options, so 2 bits
pinout &= ~0xc;
switch (pin) {
case 1: break;
case 5: pinout |= 0x4; break;
case 61: pinout |= 0x8; break;
case 59: pinout |= 0xc; break;
}
}
inline void setSCK(uint8_t pin) __attribute__((always_inline)) {
// More options, so 2 bits
pinout &= ~0x30;
switch (pin) {
case 32: break;
case 20: pinout |= 0x10; break;
case 60: pinout |= 0x20; break;
}
}
inline void enable_pins(void) __attribute__((always_inline)) {
//serial_print("enable_pins\n");
// MOSI (SOUT)
switch (pinout & 0x3) {
case 0: CORE_PIN0_CONFIG = PORT_PCR_MUX(2); break;
case 1: CORE_PIN21_CONFIG = PORT_PCR_MUX(7); break;
case 2: CORE_PIN61_CONFIG = PORT_PCR_MUX(7); break;
case 3: CORE_PIN59_CONFIG = PORT_PCR_MUX(2); break;
}
// MISO (SIN)
switch (pinout & 0xc) {
case 0x0: CORE_PIN1_CONFIG = PORT_PCR_MUX(2); break;
case 0x4: CORE_PIN5_CONFIG = PORT_PCR_MUX(7); break;
case 0x8: CORE_PIN61_CONFIG = PORT_PCR_MUX(2); break;
case 0xc: CORE_PIN59_CONFIG = PORT_PCR_MUX(7); break;
}
// SCK
switch (pinout & 0x30) {
case 0x0: CORE_PIN32_CONFIG = PORT_PCR_MUX(2); break;
case 0x10: CORE_PIN20_CONFIG = PORT_PCR_MUX(7); break;
case 0x20: CORE_PIN60_CONFIG = PORT_PCR_MUX(2); break;
}
}
inline void disable_pins(void) __attribute__((always_inline)) {
switch (pinout & 0x3) {
case 0: CORE_PIN0_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1); break;
case 1: CORE_PIN21_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1); break;
case 2: CORE_PIN61_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1); break;
case 3: CORE_PIN59_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1); break;
}
switch (pinout & 0xc) {
case 0x0: CORE_PIN1_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1); break;
case 0x4: CORE_PIN5_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1); break;
case 0x8: CORE_PIN61_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1); break;
case 0xc: CORE_PIN59_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1); break;
}
switch (pinout & 0x30) {
case 0x0: CORE_PIN32_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1); break;
case 0x10: CORE_PIN20_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1); break;
case 0x20: CORE_PIN60_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1); break;
}
}
friend class SPIFIFO1class;
private:
static uint8_t pinout;
static inline void update_ctar(uint32_t ctar) __attribute__((always_inline)) {
if (SPI1_CTAR0 == ctar) return;
uint32_t mcr = SPI1_MCR;
if (mcr & SPI_MCR_MDIS) {
SPI1_CTAR0 = ctar;
} else {
SPI1_MCR = mcr | SPI_MCR_MDIS | SPI_MCR_HALT;
SPI1_CTAR0 = ctar;
SPI1_MCR = mcr;
}
}
};
extern SPCR1emulation SPCR1;

////////////////////
// SPI2
class SPCR2emulation
{
public:
inline SPCR2emulation & operator = (int val) __attribute__((always_inline)) {
uint32_t ctar, mcr, sim3;
//serial_print("SPCR=");
//serial_phex(val);
//serial_print("\n");
sim3 = SIM_SCGC3;
if (!(sim3 & SIM_SCGC3_SPI2)) {
//serial_print("init1\n");
SIM_SCGC3 = sim3 | SIM_SCGC3_SPI2;
SPI2_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
}
if (!(val & (1<<SPE))) {
SPI2_MCR |= SPI_MCR_MDIS; // TODO: use bitband for atomic access
}
ctar = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1);
if (val & (1<<DORD)) ctar |= SPI_CTAR_LSBFE;
if (val & (1<<CPOL)) ctar |= SPI_CTAR_CPOL;
if (val & (1<<CPHA)) {
ctar |= SPI_CTAR_CPHA;
if ((val & 3) == 0) {
ctar |= SPI_CTAR_BR(1) | SPI_CTAR_ASC(1);
} else if ((val & 3) == 1) {
ctar |= SPI_CTAR_BR(4) | SPI_CTAR_ASC(4);
} else if ((val & 3) == 2) {
ctar |= SPI_CTAR_BR(6) | SPI_CTAR_ASC(6);
} else {
ctar |= SPI_CTAR_BR(7) | SPI_CTAR_ASC(7);
}
} else {
if ((val & 3) == 0) {
ctar |= SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
} else if ((val & 3) == 1) {
ctar |= SPI_CTAR_BR(4) | SPI_CTAR_CSSCK(4);
} else if ((val & 3) == 2) {
ctar |= SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(6);
} else {
ctar |= SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(7);
}
}
ctar |= (SPI2_CTAR0 & SPI_CTAR_DBR);
update_ctar(ctar);
mcr = SPI_MCR_DCONF(0) | SPI_MCR_PCSIS(0x1F);
if (val & (1<<MSTR)) mcr |= SPI_MCR_MSTR;
if (val & (1<<SPE)) {
mcr &= ~(SPI_MCR_MDIS | SPI_MCR_HALT);
SPI2_MCR = mcr;
enable_pins();
} else {
mcr |= (SPI_MCR_MDIS | SPI_MCR_HALT);
SPI2_MCR = mcr;
disable_pins();
}
//serial_print("MCR:");
//serial_phex32(SPI2_MCR);
//serial_print(", CTAR0:");
//serial_phex32(SPI2_CTAR0);
//serial_print("\n");
return *this;
}
inline SPCR2emulation & operator |= (int val) __attribute__((always_inline)) {
uint32_t sim3;
//serial_print("SPCR |= ");
//serial_phex(val);
//serial_print("\n");
sim3 = SIM_SCGC3;
if (!(sim3 & SIM_SCGC3_SPI2)) {
//serial_print("init2\n");
SIM_SCGC6 = sim3 | SIM_SCGC3_SPI2;
SPI2_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1) | SPI_CTAR_BR(1);
}
if (val & ((1<<DORD)|(1<<CPOL)|(1<<CPHA)|3)) {
uint32_t ctar = SPI2_CTAR0;
if (val & (1<<DORD)) ctar |= SPI_CTAR_LSBFE; // TODO: use bitband
if (val & (1<<CPOL)) ctar |= SPI_CTAR_CPOL;
if ((val & 3) == 1) {
// TODO: implement - is this ever really needed
} else if ((val & 3) == 2) {
// TODO: implement - is this ever really needed
} else if ((val & 3) == 3) {
// TODO: implement - is this ever really needed
}
if (val & (1<<CPHA) && !(ctar & SPI_CTAR_CPHA)) {
ctar |= SPI_CTAR_CPHA;
// TODO: clear SPI_CTAR_CSSCK, set SPI_CTAR_ASC
}
update_ctar(ctar);
}
if (val & (1<<MSTR)) SPI2_MCR |= SPI_MCR_MSTR;
if (val & (1<<SPE)) {
SPI2_MCR &= ~(SPI_MCR_MDIS | SPI_MCR_HALT);
enable_pins();
}
//serial_print("MCR:");
//serial_phex32(SPI2_MCR);
//serial_print(", CTAR0:");
//serial_phex32(SPI2_CTAR0);
//serial_print("\n");
return *this;
}
inline SPCR2emulation & operator &= (int val) __attribute__((always_inline)) {
//serial_print("SPCR &= ");
//serial_phex(val);
//serial_print("\n");
SIM_SCGC3 |= SIM_SCGC3_SPI2;
if (!(val & (1<<SPE))) {
SPI2_MCR |= (SPI_MCR_MDIS | SPI_MCR_HALT);
disable_pins();
}
if ((val & ((1<<DORD)|(1<<CPOL)|(1<<CPHA)|3)) != ((1<<DORD)|(1<<CPOL)|(1<<CPHA)|3)) {
uint32_t ctar = SPI2_CTAR0;
if (!(val & (1<<DORD))) ctar &= ~SPI_CTAR_LSBFE; // TODO: use bitband
if (!(val & (1<<CPOL))) ctar &= ~SPI_CTAR_CPOL;
if ((val & 3) == 0) {
// TODO: implement - is this ever really needed
} else if ((val & 3) == 1) {
// TODO: implement - is this ever really needed
} else if ((val & 3) == 2) {
// TODO: implement - is this ever really needed
}
if (!(val & (1<<CPHA)) && (ctar & SPI_CTAR_CPHA)) {
ctar &= ~SPI_CTAR_CPHA;
// TODO: set SPI_CTAR_ASC, clear SPI_CTAR_CSSCK
}
update_ctar(ctar);
}
if (!(val & (1<<MSTR))) SPI2_MCR &= ~SPI_MCR_MSTR;
return *this;
}
inline int operator & (int val) const __attribute__((always_inline)) {
int ret = 0;
//serial_print("SPCR & ");
//serial_phex(val);
//serial_print(" MCR:");
//serial_phex32(SPI2_MCR);
//serial_print(", CTAR0:");
//serial_phex32(SPI2_CTAR0);
//serial_print("\n");

//serial_print("\n");
SIM_SCGC3 |= SIM_SCGC3_SPI2;
if ((val & (1<<DORD)) && (SPI2_CTAR0 & SPI_CTAR_LSBFE)) ret |= (1<<DORD);
if ((val & (1<<CPOL)) && (SPI2_CTAR0 & SPI_CTAR_CPOL)) ret |= (1<<CPOL);
if ((val & (1<<CPHA)) && (SPI2_CTAR0 & SPI_CTAR_CPHA)) ret |= (1<<CPHA);
if ((val & 3) == 3) {
uint32_t dbr = SPI2_CTAR0 & 15;
if (dbr <= 1) {
} else if (dbr <= 4) {
ret |= (1<<SPR0);
} else if (dbr <= 6) {
ret |= (1<<SPR1);
} else {
ret |= (1<<SPR1)|(1<<SPR0);
}
} else if ((val & 3) == 1) {
// TODO: implement - is this ever really needed
} else if ((val & 3) == 2) {
// TODO: implement - is this ever really needed
}
if (val & (1<<SPE) && (!(SPI2_MCR & SPI_MCR_MDIS))) ret |= (1<<SPE);
if (val & (1<<MSTR) && (SPI2_MCR & SPI_MCR_MSTR)) ret |= (1<<MSTR);
//serial_print("ret = ");
//serial_phex(ret);
//serial_print("\n");
return ret;
}
inline void setMOSI(uint8_t pin) __attribute__((always_inline)) {
if (pin == 44) pinout &= ~1;
if (pin == 52) pinout |= 1;
}
inline void setMISO(uint8_t pin) __attribute__((always_inline)) {
if (pin == 45) pinout &= ~2;
if (pin == 51) pinout |= 2;
}
inline void setSCK(uint8_t pin) __attribute__((always_inline)) {
if (pin == 46) pinout &= ~4;
if (pin == 53) pinout |= 4;
}
inline void enable_pins(void) __attribute__((always_inline)) {
//serial_print("enable_pins\n");
if ((pinout & 1) == 0) {
CORE_PIN44_CONFIG = PORT_PCR_MUX(2);
} else {
CORE_PIN52_CONFIG = PORT_PCR_MUX(2);
}
if ((pinout & 2) == 0) {
CORE_PIN45_CONFIG = PORT_PCR_MUX(2);
} else {
CORE_PIN51_CONFIG = PORT_PCR_MUX(2);
}
if ((pinout & 4) == 0) {
CORE_PIN46_CONFIG = PORT_PCR_MUX(2);
} else {
CORE_PIN53_CONFIG = PORT_PCR_MUX(2);
}
}
inline void disable_pins(void) __attribute__((always_inline)) {
//serial_print("disable_pins\n");
if ((pinout & 1) == 0) {
CORE_PIN44_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1);
} else {
CORE_PIN52_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1);
}
if ((pinout & 2) == 0) {
CORE_PIN45_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1);
} else {
CORE_PIN51_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1);
}
if ((pinout & 4) == 0) {
CORE_PIN46_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1);
} else {
CORE_PIN53_CONFIG = PORT_PCR_SRE | PORT_PCR_MUX(1);
}
}
friend class SPIFIFO1class;
private:
static uint8_t pinout;
static inline void update_ctar(uint32_t ctar) __attribute__((always_inline)) {
if (SPI2_CTAR0 == ctar) return;
uint32_t mcr = SPI2_MCR;
if (mcr & SPI_MCR_MDIS) {
SPI2_CTAR0 = ctar;
} else {
SPI2_MCR = mcr | SPI_MCR_MDIS | SPI_MCR_HALT;
SPI2_CTAR0 = ctar;
SPI2_MCR = mcr;
}
}
};
extern SPCR2emulation SPCR2;



#endif

class SPSRemulation
{
public:
@@ -1293,16 +1984,49 @@ public:
return ret;
}
inline void setMOSI(uint8_t pin) __attribute__((always_inline)) {
if (pin == 11) pinout &= ~1;
if (pin == 7) pinout |= 1;
uint8_t newpinout = pinout;
if (pin == 11) newpinout &= ~1;
if (pin == 7) newpinout |= 1;
if ((SIM_SCGC4 & SIM_SCGC4_SPI0) && newpinout != pinout) {
if ((newpinout & 1) == 0) {
CORE_PIN7_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
CORE_PIN11_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2);
} else {
CORE_PIN11_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
CORE_PIN7_CONFIG = PORT_PCR_MUX(2);
}
}
pinout = newpinout;
}
inline void setMISO(uint8_t pin) __attribute__((always_inline)) {
if (pin == 12) pinout &= ~2;
if (pin == 8) pinout |= 2;
uint8_t newpinout = pinout;
if (pin == 12) newpinout &= ~2;
if (pin == 8) newpinout |= 2;
if ((SIM_SCGC4 & SIM_SCGC4_SPI0) && newpinout != pinout) {
if ((newpinout & 2) == 0) {
CORE_PIN8_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
CORE_PIN12_CONFIG = PORT_PCR_MUX(2);
} else {
CORE_PIN12_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
CORE_PIN8_CONFIG = PORT_PCR_MUX(2);
}
}
pinout = newpinout;
}
inline void setSCK(uint8_t pin) __attribute__((always_inline)) {
if (pin == 13) pinout &= ~4;
if (pin == 14) pinout |= 4;
uint8_t newpinout = pinout;
if (pin == 13) newpinout &= ~4;
if (pin == 14) newpinout |= 4;
if ((SIM_SCGC4 & SIM_SCGC4_SPI0) && newpinout != pinout) {
if ((newpinout & 4) == 0) {
CORE_PIN14_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
CORE_PIN13_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2);
} else {
CORE_PIN13_CONFIG = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
CORE_PIN14_CONFIG = PORT_PCR_MUX(2);
}
}
pinout = newpinout;
}
friend class SPSRemulation;
friend class SPIFIFOclass;
@@ -1487,9 +2211,9 @@ public:
extern SREGemulation SREG;


// 22211
// 22211
// 84062840
// 322111
// 322111
// 17395173
#if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)


+ 1
- 1
teensy3/avr_functions.h View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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

+ 2
- 0
teensy3/binary.h View File

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

#ifndef Binary_h
#define Binary_h


+ 2
- 0
teensy3/core_id.h View File

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

#ifndef CORE_TEENSY
#define CORE_TEENSY
#endif

+ 508
- 14
teensy3/core_pins.h View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -34,7 +34,6 @@
#include "kinetis.h"
#include "pins_arduino.h"


#define HIGH 1
#define LOW 0
#define INPUT 0
@@ -42,6 +41,7 @@
#define INPUT_PULLUP 2
#define INPUT_PULLDOWN 3
#define OUTPUT_OPENDRAIN 4
#define INPUT_DISABLE 5
#define LSBFIRST 0
#define MSBFIRST 1
#define _BV(n) (1<<(n))
@@ -113,14 +113,43 @@
#define CORE_NUM_INTERRUPT 24 // really only 18, but 6 "holes"
#define CORE_NUM_ANALOG 13
#define CORE_NUM_PWM 10
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
#define CORE_NUM_TOTAL_PINS 40
#define CORE_NUM_DIGITAL 40
#define CORE_NUM_INTERRUPT 40
#define CORE_NUM_ANALOG 23
#elif defined(__MK64FX512__)
#define CORE_NUM_TOTAL_PINS 64
#define CORE_NUM_DIGITAL 64
#define CORE_NUM_INTERRUPT 64
#define CORE_NUM_ANALOG 27
#define CORE_NUM_PWM 20
#elif defined(__MK66FX1M0__)
#define CORE_NUM_TOTAL_PINS 64
#define CORE_NUM_DIGITAL 64
#define CORE_NUM_INTERRUPT 64
#define CORE_NUM_ANALOG 25
#define CORE_NUM_PWM 22
#endif

// These MAX_PIN_PORTx values have the highest Kinetis pin index
// that is used for a given port.
#if defined(__MK20DX128__) || defined(__MK20DX256__)
#define CORE_MAX_PIN_PORTA 13
#define CORE_MAX_PIN_PORTB 19
#define CORE_MAX_PIN_PORTC 11
#define CORE_MAX_PIN_PORTD 7
#define CORE_MAX_PIN_PORTE 1
#elif defined(__MKL26Z64__)
#define CORE_MAX_PIN_PORTA 2
#define CORE_MAX_PIN_PORTB 17
#define CORE_MAX_PIN_PORTC 7
#define CORE_MAX_PIN_PORTD 7
#define CORE_MAX_PIN_PORTE 30
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
#define CORE_MAX_PIN_PORTA 29
#define CORE_MAX_PIN_PORTB 23
#define CORE_MAX_PIN_PORTC 11
#define CORE_MAX_PIN_PORTD 15
#define CORE_MAX_PIN_PORTE 26
#endif


#if defined(__MK20DX128__) || defined(__MK20DX256__)

#define CORE_PIN0_BIT 16
@@ -771,6 +800,30 @@
#define CORE_PIN37_BIT 10
#define CORE_PIN38_BIT 11
#define CORE_PIN39_BIT 17
#define CORE_PIN40_BIT 28
#define CORE_PIN41_BIT 29
#define CORE_PIN42_BIT 26
#define CORE_PIN43_BIT 20
#define CORE_PIN44_BIT 22
#define CORE_PIN45_BIT 23
#define CORE_PIN46_BIT 21
#define CORE_PIN47_BIT 8
#define CORE_PIN48_BIT 9
#define CORE_PIN49_BIT 4
#define CORE_PIN50_BIT 5
#define CORE_PIN51_BIT 14
#define CORE_PIN52_BIT 13
#define CORE_PIN53_BIT 12
#define CORE_PIN54_BIT 15
#define CORE_PIN55_BIT 11
#define CORE_PIN56_BIT 10
#define CORE_PIN57_BIT 11
#define CORE_PIN58_BIT 0
#define CORE_PIN59_BIT 1
#define CORE_PIN60_BIT 2
#define CORE_PIN61_BIT 3
#define CORE_PIN62_BIT 4
#define CORE_PIN63_BIT 5

#define CORE_PIN0_BITMASK (1<<(CORE_PIN0_BIT))
#define CORE_PIN1_BITMASK (1<<(CORE_PIN1_BIT))
@@ -812,6 +865,31 @@
#define CORE_PIN37_BITMASK (1<<(CORE_PIN37_BIT))
#define CORE_PIN38_BITMASK (1<<(CORE_PIN38_BIT))
#define CORE_PIN39_BITMASK (1<<(CORE_PIN39_BIT))
#define CORE_PIN40_BITMASK (1<<(CORE_PIN40_BIT))
#define CORE_PIN41_BITMASK (1<<(CORE_PIN41_BIT))
#define CORE_PIN42_BITMASK (1<<(CORE_PIN42_BIT))
#define CORE_PIN43_BITMASK (1<<(CORE_PIN43_BIT))
#define CORE_PIN44_BITMASK (1<<(CORE_PIN44_BIT))
#define CORE_PIN45_BITMASK (1<<(CORE_PIN45_BIT))
#define CORE_PIN46_BITMASK (1<<(CORE_PIN46_BIT))
#define CORE_PIN47_BITMASK (1<<(CORE_PIN47_BIT))
#define CORE_PIN48_BITMASK (1<<(CORE_PIN48_BIT))
#define CORE_PIN49_BITMASK (1<<(CORE_PIN49_BIT))
#define CORE_PIN50_BITMASK (1<<(CORE_PIN50_BIT))
#define CORE_PIN51_BITMASK (1<<(CORE_PIN51_BIT))
#define CORE_PIN52_BITMASK (1<<(CORE_PIN52_BIT))
#define CORE_PIN53_BITMASK (1<<(CORE_PIN53_BIT))
#define CORE_PIN54_BITMASK (1<<(CORE_PIN54_BIT))
#define CORE_PIN55_BITMASK (1<<(CORE_PIN55_BIT))
#define CORE_PIN56_BITMASK (1<<(CORE_PIN56_BIT))
#define CORE_PIN57_BITMASK (1<<(CORE_PIN57_BIT))
#define CORE_PIN58_BITMASK (1<<(CORE_PIN58_BIT))
#define CORE_PIN59_BITMASK (1<<(CORE_PIN59_BIT))
#define CORE_PIN60_BITMASK (1<<(CORE_PIN60_BIT))
#define CORE_PIN61_BITMASK (1<<(CORE_PIN61_BIT))
#define CORE_PIN62_BITMASK (1<<(CORE_PIN62_BIT))
#define CORE_PIN63_BITMASK (1<<(CORE_PIN63_BIT))


#define CORE_PIN0_PORTREG GPIOB_PDOR
#define CORE_PIN1_PORTREG GPIOB_PDOR
@@ -853,6 +931,30 @@
#define CORE_PIN37_PORTREG GPIOC_PDOR
#define CORE_PIN38_PORTREG GPIOC_PDOR
#define CORE_PIN39_PORTREG GPIOA_PDOR
#define CORE_PIN40_PORTREG GPIOA_PDOR
#define CORE_PIN41_PORTREG GPIOA_PDOR
#define CORE_PIN42_PORTREG GPIOA_PDOR
#define CORE_PIN43_PORTREG GPIOB_PDOR
#define CORE_PIN44_PORTREG GPIOB_PDOR
#define CORE_PIN45_PORTREG GPIOB_PDOR
#define CORE_PIN46_PORTREG GPIOB_PDOR
#define CORE_PIN47_PORTREG GPIOD_PDOR
#define CORE_PIN48_PORTREG GPIOD_PDOR
#define CORE_PIN49_PORTREG GPIOB_PDOR
#define CORE_PIN50_PORTREG GPIOB_PDOR
#define CORE_PIN51_PORTREG GPIOD_PDOR
#define CORE_PIN52_PORTREG GPIOD_PDOR
#define CORE_PIN53_PORTREG GPIOD_PDOR
#define CORE_PIN54_PORTREG GPIOD_PDOR
#define CORE_PIN55_PORTREG GPIOD_PDOR
#define CORE_PIN56_PORTREG GPIOE_PDOR
#define CORE_PIN57_PORTREG GPIOE_PDOR
#define CORE_PIN58_PORTREG GPIOE_PDOR
#define CORE_PIN59_PORTREG GPIOE_PDOR
#define CORE_PIN60_PORTREG GPIOE_PDOR
#define CORE_PIN61_PORTREG GPIOE_PDOR
#define CORE_PIN62_PORTREG GPIOE_PDOR
#define CORE_PIN63_PORTREG GPIOE_PDOR

#define CORE_PIN0_PORTSET GPIOB_PSOR
#define CORE_PIN1_PORTSET GPIOB_PSOR
@@ -894,6 +996,30 @@
#define CORE_PIN37_PORTSET GPIOC_PSOR
#define CORE_PIN38_PORTSET GPIOC_PSOR
#define CORE_PIN39_PORTSET GPIOA_PSOR
#define CORE_PIN40_PORTSET GPIOA_PSOR
#define CORE_PIN41_PORTSET GPIOA_PSOR
#define CORE_PIN42_PORTSET GPIOA_PSOR
#define CORE_PIN43_PORTSET GPIOB_PSOR
#define CORE_PIN44_PORTSET GPIOB_PSOR
#define CORE_PIN45_PORTSET GPIOB_PSOR
#define CORE_PIN46_PORTSET GPIOB_PSOR
#define CORE_PIN47_PORTSET GPIOD_PSOR
#define CORE_PIN48_PORTSET GPIOD_PSOR
#define CORE_PIN49_PORTSET GPIOB_PSOR
#define CORE_PIN50_PORTSET GPIOB_PSOR
#define CORE_PIN51_PORTSET GPIOD_PSOR
#define CORE_PIN52_PORTSET GPIOD_PSOR
#define CORE_PIN53_PORTSET GPIOD_PSOR
#define CORE_PIN54_PORTSET GPIOD_PSOR
#define CORE_PIN55_PORTSET GPIOD_PSOR
#define CORE_PIN56_PORTSET GPIOE_PSOR
#define CORE_PIN57_PORTSET GPIOE_PSOR
#define CORE_PIN58_PORTSET GPIOE_PSOR
#define CORE_PIN59_PORTSET GPIOE_PSOR
#define CORE_PIN60_PORTSET GPIOE_PSOR
#define CORE_PIN61_PORTSET GPIOE_PSOR
#define CORE_PIN62_PORTSET GPIOE_PSOR
#define CORE_PIN63_PORTSET GPIOE_PSOR

#define CORE_PIN0_PORTCLEAR GPIOB_PCOR
#define CORE_PIN1_PORTCLEAR GPIOB_PCOR
@@ -935,6 +1061,30 @@
#define CORE_PIN37_PORTCLEAR GPIOC_PCOR
#define CORE_PIN38_PORTCLEAR GPIOC_PCOR
#define CORE_PIN39_PORTCLEAR GPIOA_PCOR
#define CORE_PIN40_PORTCLEAR GPIOA_PCOR
#define CORE_PIN41_PORTCLEAR GPIOA_PCOR
#define CORE_PIN42_PORTCLEAR GPIOA_PCOR
#define CORE_PIN43_PORTCLEAR GPIOB_PCOR
#define CORE_PIN44_PORTCLEAR GPIOB_PCOR
#define CORE_PIN45_PORTCLEAR GPIOB_PCOR
#define CORE_PIN46_PORTCLEAR GPIOB_PCOR
#define CORE_PIN47_PORTCLEAR GPIOD_PCOR
#define CORE_PIN48_PORTCLEAR GPIOD_PCOR
#define CORE_PIN49_PORTCLEAR GPIOB_PCOR
#define CORE_PIN50_PORTCLEAR GPIOB_PCOR
#define CORE_PIN51_PORTCLEAR GPIOD_PCOR
#define CORE_PIN52_PORTCLEAR GPIOD_PCOR
#define CORE_PIN53_PORTCLEAR GPIOD_PCOR
#define CORE_PIN54_PORTCLEAR GPIOD_PCOR
#define CORE_PIN55_PORTCLEAR GPIOD_PCOR
#define CORE_PIN56_PORTCLEAR GPIOE_PCOR
#define CORE_PIN57_PORTCLEAR GPIOE_PCOR
#define CORE_PIN58_PORTCLEAR GPIOE_PCOR
#define CORE_PIN59_PORTCLEAR GPIOE_PCOR
#define CORE_PIN60_PORTCLEAR GPIOE_PCOR
#define CORE_PIN61_PORTCLEAR GPIOE_PCOR
#define CORE_PIN62_PORTCLEAR GPIOE_PCOR
#define CORE_PIN63_PORTCLEAR GPIOE_PCOR

#define CORE_PIN0_DDRREG GPIOB_PDDR
#define CORE_PIN1_DDRREG GPIOB_PDDR
@@ -976,6 +1126,30 @@
#define CORE_PIN37_DDRREG GPIOC_PDDR
#define CORE_PIN38_DDRREG GPIOC_PDDR
#define CORE_PIN39_DDRREG GPIOA_PDDR
#define CORE_PIN40_DDRREG GPIOA_PDDR
#define CORE_PIN41_DDRREG GPIOA_PDDR
#define CORE_PIN42_DDRREG GPIOA_PDDR
#define CORE_PIN43_DDRREG GPIOB_PDDR
#define CORE_PIN44_DDRREG GPIOB_PDDR
#define CORE_PIN45_DDRREG GPIOB_PDDR
#define CORE_PIN46_DDRREG GPIOB_PDDR
#define CORE_PIN47_DDRREG GPIOD_PDDR
#define CORE_PIN48_DDRREG GPIOD_PDDR
#define CORE_PIN49_DDRREG GPIOB_PDDR
#define CORE_PIN50_DDRREG GPIOB_PDDR
#define CORE_PIN51_DDRREG GPIOD_PDDR
#define CORE_PIN52_DDRREG GPIOD_PDDR
#define CORE_PIN53_DDRREG GPIOD_PDDR
#define CORE_PIN54_DDRREG GPIOD_PDDR
#define CORE_PIN55_DDRREG GPIOD_PDDR
#define CORE_PIN56_DDRREG GPIOE_PDDR
#define CORE_PIN57_DDRREG GPIOE_PDDR
#define CORE_PIN58_DDRREG GPIOE_PDDR
#define CORE_PIN59_DDRREG GPIOE_PDDR
#define CORE_PIN60_DDRREG GPIOE_PDDR
#define CORE_PIN61_DDRREG GPIOE_PDDR
#define CORE_PIN62_DDRREG GPIOE_PDDR
#define CORE_PIN63_DDRREG GPIOE_PDDR

#define CORE_PIN0_PINREG GPIOB_PDIR
#define CORE_PIN1_PINREG GPIOB_PDIR
@@ -1017,6 +1191,30 @@
#define CORE_PIN37_PINREG GPIOC_PDIR
#define CORE_PIN38_PINREG GPIOC_PDIR
#define CORE_PIN39_PINREG GPIOA_PDIR
#define CORE_PIN40_PINREG GPIOA_PDIR
#define CORE_PIN41_PINREG GPIOA_PDIR
#define CORE_PIN42_PINREG GPIOA_PDIR
#define CORE_PIN43_PINREG GPIOB_PDIR
#define CORE_PIN44_PINREG GPIOB_PDIR
#define CORE_PIN45_PINREG GPIOB_PDIR
#define CORE_PIN46_PINREG GPIOB_PDIR
#define CORE_PIN47_PINREG GPIOD_PDIR
#define CORE_PIN48_PINREG GPIOD_PDIR
#define CORE_PIN49_PINREG GPIOB_PDIR
#define CORE_PIN50_PINREG GPIOB_PDIR
#define CORE_PIN51_PINREG GPIOD_PDIR
#define CORE_PIN52_PINREG GPIOD_PDIR
#define CORE_PIN53_PINREG GPIOD_PDIR
#define CORE_PIN54_PINREG GPIOD_PDIR
#define CORE_PIN55_PINREG GPIOD_PDIR
#define CORE_PIN56_PINREG GPIOE_PDIR
#define CORE_PIN57_PINREG GPIOE_PDIR
#define CORE_PIN58_PINREG GPIOE_PDIR
#define CORE_PIN59_PINREG GPIOE_PDIR
#define CORE_PIN60_PINREG GPIOE_PDIR
#define CORE_PIN61_PINREG GPIOE_PDIR
#define CORE_PIN62_PINREG GPIOE_PDIR
#define CORE_PIN63_PINREG GPIOE_PDIR

#define CORE_PIN0_CONFIG PORTB_PCR16
#define CORE_PIN1_CONFIG PORTB_PCR17
@@ -1058,6 +1256,30 @@
#define CORE_PIN37_CONFIG PORTC_PCR10
#define CORE_PIN38_CONFIG PORTC_PCR11
#define CORE_PIN39_CONFIG PORTA_PCR17
#define CORE_PIN40_CONFIG PORTA_PCR28
#define CORE_PIN41_CONFIG PORTA_PCR29
#define CORE_PIN42_CONFIG PORTA_PCR26
#define CORE_PIN43_CONFIG PORTB_PCR20
#define CORE_PIN44_CONFIG PORTB_PCR22
#define CORE_PIN45_CONFIG PORTB_PCR23
#define CORE_PIN46_CONFIG PORTB_PCR21
#define CORE_PIN47_CONFIG PORTD_PCR8
#define CORE_PIN48_CONFIG PORTD_PCR9
#define CORE_PIN49_CONFIG PORTB_PCR4
#define CORE_PIN50_CONFIG PORTB_PCR5
#define CORE_PIN51_CONFIG PORTD_PCR14
#define CORE_PIN52_CONFIG PORTD_PCR13
#define CORE_PIN53_CONFIG PORTD_PCR12
#define CORE_PIN54_CONFIG PORTD_PCR15
#define CORE_PIN55_CONFIG PORTD_PCR11
#define CORE_PIN56_CONFIG PORTE_PCR10
#define CORE_PIN57_CONFIG PORTE_PCR11
#define CORE_PIN58_CONFIG PORTE_PCR0
#define CORE_PIN59_CONFIG PORTE_PCR1
#define CORE_PIN60_CONFIG PORTE_PCR2
#define CORE_PIN61_CONFIG PORTE_PCR3
#define CORE_PIN62_CONFIG PORTE_PCR4
#define CORE_PIN63_CONFIG PORTE_PCR5

#define CORE_ADC0_PIN 14
#define CORE_ADC1_PIN 15
@@ -1069,8 +1291,8 @@
#define CORE_ADC7_PIN 21
#define CORE_ADC8_PIN 22
#define CORE_ADC9_PIN 23
#define CORE_ADC10_PIN 40
#define CORE_ADC11_PIN 41
#define CORE_ADC10_PIN 64
#define CORE_ADC11_PIN 65
#define CORE_ADC12_PIN 31
#define CORE_ADC13_PIN 32
#define CORE_ADC14_PIN 33
@@ -1080,6 +1302,12 @@
#define CORE_ADC18_PIN 37
#define CORE_ADC19_PIN 38
#define CORE_ADC20_PIN 39
#define CORE_ADC21_PIN 66
#define CORE_ADC22_PIN 67
#define CORE_ADC23_PIN 49
#define CORE_ADC24_PIN 50
#define CORE_ADC25_PIN 68
#define CORE_ADC26_PIN 69

#define CORE_RXD0_PIN 0
#define CORE_TXD0_PIN 1
@@ -1132,11 +1360,115 @@
#define CORE_INT37_PIN 37
#define CORE_INT38_PIN 38
#define CORE_INT39_PIN 39
#define CORE_INT40_PIN 40
#define CORE_INT41_PIN 41
#define CORE_INT42_PIN 42
#define CORE_INT43_PIN 43
#define CORE_INT44_PIN 44
#define CORE_INT45_PIN 45
#define CORE_INT46_PIN 46
#define CORE_INT47_PIN 47
#define CORE_INT48_PIN 48
#define CORE_INT49_PIN 49
#define CORE_INT50_PIN 50
#define CORE_INT51_PIN 51
#define CORE_INT52_PIN 52
#define CORE_INT53_PIN 53
#define CORE_INT54_PIN 54
#define CORE_INT55_PIN 55
#define CORE_INT56_PIN 56
#define CORE_INT57_PIN 57
#define CORE_INT58_PIN 58
#define CORE_INT59_PIN 59
#define CORE_INT60_PIN 60
#define CORE_INT61_PIN 61
#define CORE_INT62_PIN 62
#define CORE_INT63_PIN 63
#define CORE_INT_EVERY_PIN 1

#endif


#if defined(__MK20DX128__)
#define CORE_FTM0_CH0_PIN 22
#define CORE_FTM0_CH1_PIN 23
#define CORE_FTM0_CH2_PIN 9
#define CORE_FTM0_CH3_PIN 10
#define CORE_FTM0_CH4_PIN 6
#define CORE_FTM0_CH5_PIN 20
#define CORE_FTM0_CH6_PIN 21
#define CORE_FTM0_CH7_PIN 5
#define CORE_FTM1_CH0_PIN 3
#define CORE_FTM1_CH1_PIN 4
#elif defined(__MK20DX256__)
#define CORE_FTM0_CH0_PIN 22
#define CORE_FTM0_CH1_PIN 23
#define CORE_FTM0_CH2_PIN 9
#define CORE_FTM0_CH3_PIN 10
#define CORE_FTM0_CH4_PIN 6
#define CORE_FTM0_CH5_PIN 20
#define CORE_FTM0_CH6_PIN 21
#define CORE_FTM0_CH7_PIN 5
#define CORE_FTM1_CH0_PIN 3
#define CORE_FTM1_CH1_PIN 4
#define CORE_FTM2_CH0_PIN 32
#define CORE_FTM2_CH1_PIN 25
#elif defined(__MKL26Z64__)
#define CORE_TPM0_CH0_PIN 22
#define CORE_TPM0_CH1_PIN 23
#define CORE_TPM0_CH2_PIN 9
#define CORE_TPM0_CH3_PIN 10
#define CORE_TPM0_CH4_PIN 6
#define CORE_TPM0_CH5_PIN 20
#define CORE_TPM1_CH0_PIN 16
#define CORE_TPM1_CH1_PIN 17
#define CORE_TPM2_CH0_PIN 3
#define CORE_TPM2_CH1_PIN 4
#elif defined(__MK64FX512__)
#define CORE_FTM0_CH0_PIN 22
#define CORE_FTM0_CH1_PIN 23
#define CORE_FTM0_CH2_PIN 9
#define CORE_FTM0_CH3_PIN 10
#define CORE_FTM0_CH4_PIN 6
#define CORE_FTM0_CH5_PIN 20
#define CORE_FTM0_CH6_PIN 21
#define CORE_FTM0_CH7_PIN 5
#define CORE_FTM1_CH0_PIN 3
#define CORE_FTM1_CH1_PIN 4
#define CORE_FTM2_CH0_PIN 29
#define CORE_FTM2_CH1_PIN 30
#define CORE_FTM3_CH0_PIN 2
#define CORE_FTM3_CH1_PIN 14
#define CORE_FTM3_CH2_PIN 7
#define CORE_FTM3_CH3_PIN 8
#define CORE_FTM3_CH4_PIN 35
#define CORE_FTM3_CH5_PIN 36
#define CORE_FTM3_CH6_PIN 37
#define CORE_FTM3_CH7_PIN 38
#elif defined(__MK66FX1M0__)
#define CORE_FTM0_CH0_PIN 22
#define CORE_FTM0_CH1_PIN 23
#define CORE_FTM0_CH2_PIN 9
#define CORE_FTM0_CH3_PIN 10
#define CORE_FTM0_CH4_PIN 6
#define CORE_FTM0_CH5_PIN 20
#define CORE_FTM0_CH6_PIN 21
#define CORE_FTM0_CH7_PIN 5
#define CORE_FTM1_CH0_PIN 3
#define CORE_FTM1_CH1_PIN 4
#define CORE_FTM2_CH0_PIN 29
#define CORE_FTM2_CH1_PIN 30
#define CORE_FTM3_CH0_PIN 2
#define CORE_FTM3_CH1_PIN 14
#define CORE_FTM3_CH2_PIN 7
#define CORE_FTM3_CH3_PIN 8
#define CORE_FTM3_CH4_PIN 35
#define CORE_FTM3_CH5_PIN 36
#define CORE_FTM3_CH6_PIN 37
#define CORE_FTM3_CH7_PIN 38
#define CORE_TPM1_CH0_PIN 16
#define CORE_TPM1_CH1_PIN 17
#endif


#ifdef __cplusplus
@@ -1234,6 +1566,54 @@ static inline void digitalWriteFast(uint8_t pin, uint8_t val)
CORE_PIN38_PORTSET = CORE_PIN38_BITMASK;
} else if (pin == 39) {
CORE_PIN39_PORTSET = CORE_PIN39_BITMASK;
} else if (pin == 40) {
CORE_PIN40_PORTSET = CORE_PIN40_BITMASK;
} else if (pin == 41) {
CORE_PIN41_PORTSET = CORE_PIN41_BITMASK;
} else if (pin == 42) {
CORE_PIN42_PORTSET = CORE_PIN42_BITMASK;
} else if (pin == 43) {
CORE_PIN43_PORTSET = CORE_PIN43_BITMASK;
} else if (pin == 44) {
CORE_PIN44_PORTSET = CORE_PIN44_BITMASK;
} else if (pin == 45) {
CORE_PIN45_PORTSET = CORE_PIN45_BITMASK;
} else if (pin == 46) {
CORE_PIN46_PORTSET = CORE_PIN46_BITMASK;
} else if (pin == 47) {
CORE_PIN47_PORTSET = CORE_PIN47_BITMASK;
} else if (pin == 48) {
CORE_PIN48_PORTSET = CORE_PIN48_BITMASK;
} else if (pin == 49) {
CORE_PIN49_PORTSET = CORE_PIN49_BITMASK;
} else if (pin == 50) {
CORE_PIN50_PORTSET = CORE_PIN50_BITMASK;
} else if (pin == 51) {
CORE_PIN51_PORTSET = CORE_PIN51_BITMASK;
} else if (pin == 52) {
CORE_PIN52_PORTSET = CORE_PIN52_BITMASK;
} else if (pin == 53) {
CORE_PIN53_PORTSET = CORE_PIN53_BITMASK;
} else if (pin == 54) {
CORE_PIN54_PORTSET = CORE_PIN54_BITMASK;
} else if (pin == 55) {
CORE_PIN55_PORTSET = CORE_PIN55_BITMASK;
} else if (pin == 56) {
CORE_PIN56_PORTSET = CORE_PIN56_BITMASK;
} else if (pin == 57) {
CORE_PIN57_PORTSET = CORE_PIN57_BITMASK;
} else if (pin == 58) {
CORE_PIN58_PORTSET = CORE_PIN58_BITMASK;
} else if (pin == 59) {
CORE_PIN59_PORTSET = CORE_PIN59_BITMASK;
} else if (pin == 60) {
CORE_PIN60_PORTSET = CORE_PIN60_BITMASK;
} else if (pin == 61) {
CORE_PIN61_PORTSET = CORE_PIN61_BITMASK;
} else if (pin == 62) {
CORE_PIN62_PORTSET = CORE_PIN62_BITMASK;
} else if (pin == 63) {
CORE_PIN63_PORTSET = CORE_PIN63_BITMASK;
}
#endif
} else {
@@ -1322,6 +1702,54 @@ static inline void digitalWriteFast(uint8_t pin, uint8_t val)
CORE_PIN38_PORTCLEAR = CORE_PIN38_BITMASK;
} else if (pin == 39) {
CORE_PIN39_PORTCLEAR = CORE_PIN39_BITMASK;
} else if (pin == 40) {
CORE_PIN40_PORTCLEAR = CORE_PIN40_BITMASK;
} else if (pin == 41) {
CORE_PIN41_PORTCLEAR = CORE_PIN41_BITMASK;
} else if (pin == 42) {
CORE_PIN42_PORTCLEAR = CORE_PIN42_BITMASK;
} else if (pin == 43) {
CORE_PIN43_PORTCLEAR = CORE_PIN43_BITMASK;
} else if (pin == 44) {
CORE_PIN44_PORTCLEAR = CORE_PIN44_BITMASK;
} else if (pin == 45) {
CORE_PIN45_PORTCLEAR = CORE_PIN45_BITMASK;
} else if (pin == 46) {
CORE_PIN46_PORTCLEAR = CORE_PIN46_BITMASK;
} else if (pin == 47) {
CORE_PIN47_PORTCLEAR = CORE_PIN47_BITMASK;
} else if (pin == 48) {
CORE_PIN48_PORTCLEAR = CORE_PIN48_BITMASK;
} else if (pin == 49) {
CORE_PIN49_PORTCLEAR = CORE_PIN49_BITMASK;
} else if (pin == 50) {
CORE_PIN50_PORTCLEAR = CORE_PIN50_BITMASK;
} else if (pin == 51) {
CORE_PIN51_PORTCLEAR = CORE_PIN51_BITMASK;
} else if (pin == 52) {
CORE_PIN52_PORTCLEAR = CORE_PIN52_BITMASK;
} else if (pin == 53) {
CORE_PIN53_PORTCLEAR = CORE_PIN53_BITMASK;
} else if (pin == 54) {
CORE_PIN54_PORTCLEAR = CORE_PIN54_BITMASK;
} else if (pin == 55) {
CORE_PIN55_PORTCLEAR = CORE_PIN55_BITMASK;
} else if (pin == 56) {
CORE_PIN56_PORTCLEAR = CORE_PIN56_BITMASK;
} else if (pin == 57) {
CORE_PIN57_PORTCLEAR = CORE_PIN57_BITMASK;
} else if (pin == 58) {
CORE_PIN58_PORTCLEAR = CORE_PIN58_BITMASK;
} else if (pin == 59) {
CORE_PIN59_PORTCLEAR = CORE_PIN59_BITMASK;
} else if (pin == 60) {
CORE_PIN60_PORTCLEAR = CORE_PIN60_BITMASK;
} else if (pin == 61) {
CORE_PIN61_PORTCLEAR = CORE_PIN61_BITMASK;
} else if (pin == 62) {
CORE_PIN62_PORTCLEAR = CORE_PIN62_BITMASK;
} else if (pin == 63) {
CORE_PIN63_PORTCLEAR = CORE_PIN63_BITMASK;
}
#endif
}
@@ -1424,6 +1852,54 @@ static inline uint8_t digitalReadFast(uint8_t pin)
return (CORE_PIN38_PINREG & CORE_PIN38_BITMASK) ? 1 : 0;
} else if (pin == 39) {
return (CORE_PIN39_PINREG & CORE_PIN39_BITMASK) ? 1 : 0;
} else if (pin == 40) {
return (CORE_PIN40_PINREG & CORE_PIN40_BITMASK) ? 1 : 0;
} else if (pin == 41) {
return (CORE_PIN41_PINREG & CORE_PIN41_BITMASK) ? 1 : 0;
} else if (pin == 42) {
return (CORE_PIN42_PINREG & CORE_PIN42_BITMASK) ? 1 : 0;
} else if (pin == 43) {
return (CORE_PIN43_PINREG & CORE_PIN43_BITMASK) ? 1 : 0;
} else if (pin == 44) {
return (CORE_PIN44_PINREG & CORE_PIN44_BITMASK) ? 1 : 0;
} else if (pin == 45) {
return (CORE_PIN45_PINREG & CORE_PIN45_BITMASK) ? 1 : 0;
} else if (pin == 46) {
return (CORE_PIN46_PINREG & CORE_PIN46_BITMASK) ? 1 : 0;
} else if (pin == 47) {
return (CORE_PIN47_PINREG & CORE_PIN47_BITMASK) ? 1 : 0;
} else if (pin == 48) {
return (CORE_PIN48_PINREG & CORE_PIN48_BITMASK) ? 1 : 0;
} else if (pin == 49) {
return (CORE_PIN49_PINREG & CORE_PIN49_BITMASK) ? 1 : 0;
} else if (pin == 50) {
return (CORE_PIN50_PINREG & CORE_PIN50_BITMASK) ? 1 : 0;
} else if (pin == 51) {
return (CORE_PIN51_PINREG & CORE_PIN51_BITMASK) ? 1 : 0;
} else if (pin == 52) {
return (CORE_PIN52_PINREG & CORE_PIN52_BITMASK) ? 1 : 0;
} else if (pin == 53) {
return (CORE_PIN53_PINREG & CORE_PIN53_BITMASK) ? 1 : 0;
} else if (pin == 54) {
return (CORE_PIN54_PINREG & CORE_PIN54_BITMASK) ? 1 : 0;
} else if (pin == 55) {
return (CORE_PIN55_PINREG & CORE_PIN55_BITMASK) ? 1 : 0;
} else if (pin == 56) {
return (CORE_PIN56_PINREG & CORE_PIN56_BITMASK) ? 1 : 0;
} else if (pin == 57) {
return (CORE_PIN57_PINREG & CORE_PIN57_BITMASK) ? 1 : 0;
} else if (pin == 58) {
return (CORE_PIN58_PINREG & CORE_PIN58_BITMASK) ? 1 : 0;
} else if (pin == 59) {
return (CORE_PIN59_PINREG & CORE_PIN59_BITMASK) ? 1 : 0;
} else if (pin == 60) {
return (CORE_PIN60_PINREG & CORE_PIN60_BITMASK) ? 1 : 0;
} else if (pin == 61) {
return (CORE_PIN61_PINREG & CORE_PIN61_BITMASK) ? 1 : 0;
} else if (pin == 62) {
return (CORE_PIN62_PINREG & CORE_PIN62_BITMASK) ? 1 : 0;
} else if (pin == 63) {
return (CORE_PIN63_PINREG & CORE_PIN63_BITMASK) ? 1 : 0;
}
#endif
else {
@@ -1442,8 +1918,8 @@ static inline uint8_t digitalReadFast(uint8_t pin)
void pinMode(uint8_t pin, uint8_t mode);
void init_pins(void);
void analogWrite(uint8_t pin, int val);
void analogWriteRes(uint32_t bits);
static inline void analogWriteResolution(uint32_t bits) { analogWriteRes(bits); }
uint32_t analogWriteRes(uint32_t bits);
static inline uint32_t analogWriteResolution(uint32_t bits) { return analogWriteRes(bits); }
void analogWriteFrequency(uint8_t pin, float frequency);
void analogWriteDAC0(int val);
void analogWriteDAC1(int val);
@@ -1529,7 +2005,17 @@ extern volatile uint32_t systick_millis_count;
static inline uint32_t millis(void) __attribute__((always_inline, unused));
static inline uint32_t millis(void)
{
return systick_millis_count; // single aligned 32 bit is atomic;
// Reading a volatile variable to another volatile
// seems redundant, but isn't for some cases.
// Eventually this should probably be replaced by a
// proper memory barrier or other technique. Please
// do not remove this "redundant" code without
// carefully verifying the case mentioned here:
//
// https://forum.pjrc.com/threads/17469-millis%28%29-on-teensy-3?p=104924&viewfull=1#post104924
//
volatile uint32_t ret = systick_millis_count; // single aligned 32 bit is atomic
return ret;
}

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


+ 84
- 13
teensy3/eeprom.c View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -28,20 +28,34 @@
* SOFTWARE.
*/

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

#include "kinetis.h"
#include <avr/eeprom.h>
//#include "HardwareSerial.h"
#if F_CPU > 120000000 && defined(__MK66FX1M0__)
#include "core_pins.h" // delayMicroseconds()
#endif


#if defined(__MK20DX128__) || defined(__MK20DX256__)
#define EEPROM_MAX 2048
#define EEPARTITION 0x03 // all 32K dataflash for EEPROM, none for Data
#define EEESPLIT 0x30 // must be 0x30 on these chips
#elif defined(__MK64FX512__)
#define EEPROM_MAX 4096
#define EEPARTITION 0x04 // 64K dataflash for EEPROM, 64K for Data
#define EEPARTITION 0x05 // all 128K dataflash for EEPROM
#define EEESPLIT 0x10 // best endurance: 0x00 = first 12%, 0x10 = first 25%, 0x30 = all equal
#elif defined(__MK66FX1M0__)
#define EEPROM_MAX 4096
#define EEPARTITION 0x05 // 128K dataflash for EEPROM, 128K for Data
#define EEESPLIT 0x10 // best endurance: 0x00 = first 12%, 0x10 = first 25%, 0x30 = all equal
#elif defined(__MKL26Z64__)
#define EEPROM_MAX 255
#endif
@@ -63,28 +77,28 @@

#if E2END < 32
#define EEPROM_SIZE 32
#define EEESIZE 0x39
#define EEESIZE 0x09
#elif E2END < 64
#define EEPROM_SIZE 64
#define EEESIZE 0x38
#define EEESIZE 0x08
#elif E2END < 128
#define EEPROM_SIZE 128
#define EEESIZE 0x37
#define EEESIZE 0x07
#elif E2END < 256
#define EEPROM_SIZE 256
#define EEESIZE 0x36
#define EEESIZE 0x06
#elif E2END < 512
#define EEPROM_SIZE 512
#define EEESIZE 0x35
#define EEESIZE 0x05
#elif E2END < 1024
#define EEPROM_SIZE 1024
#define EEESIZE 0x34
#define EEESIZE 0x04
#elif E2END < 2048
#define EEPROM_SIZE 2048
#define EEESIZE 0x33
#define EEESIZE 0x03
#elif E2END < 4096
#define EEPROM_SIZE 4096
#define EEESIZE 0x32
#define EEESIZE 0x02
#endif

// Writing unaligned 16 or 32 bit data is handled automatically when
@@ -105,15 +119,20 @@ void eeprom_initialize(void)
uint8_t status;

if (FTFL_FCNFG & FTFL_FCNFG_RAMRDY) {
uint8_t stat = FTFL_FSTAT & 0x70;
if (stat) FTFL_FSTAT = stat;
// FlexRAM is configured as traditional RAM
// We need to reconfigure for EEPROM usage
kinetis_hsrun_disable();
FTFL_FCCOB0 = 0x80; // PGMPART = Program Partition Command
FTFL_FCCOB4 = EEESIZE; // EEPROM Size
FTFL_FCCOB3 = 0;
FTFL_FCCOB4 = EEESPLIT | EEESIZE;
FTFL_FCCOB5 = EEPARTITION;
__disable_irq();
// do_flash_cmd() must execute from RAM. Luckily the C syntax is simple...
(*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&FTFL_FSTAT);
__enable_irq();
kinetis_hsrun_enable();
status = FTFL_FSTAT;
if (status & 0x70) {
FTFL_FSTAT = (status & 0x70);
@@ -122,11 +141,11 @@ void eeprom_initialize(void)
}
// wait for eeprom to become ready (is this really necessary?)
while (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) {
if (++count > 20000) break;
if (++count > 200000) break;
}
}

#define FlexRAM ((uint8_t *)0x14000000)
#define FlexRAM ((volatile uint8_t *)0x14000000)

uint8_t eeprom_read_byte(const uint8_t *addr)
{
@@ -184,8 +203,12 @@ void eeprom_write_byte(uint8_t *addr, uint8_t value)
if (offset >= EEPROM_SIZE) return;
if (!(FTFL_FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
if (FlexRAM[offset] != value) {
kinetis_hsrun_disable();
uint8_t stat = FTFL_FSTAT & 0x70;
if (stat) FTFL_FSTAT = stat;
FlexRAM[offset] = value;
flexram_wait();
kinetis_hsrun_enable();
}
}

@@ -199,18 +222,30 @@ void eeprom_write_word(uint16_t *addr, uint16_t value)
if ((offset & 1) == 0) {
#endif
if (*(uint16_t *)(&FlexRAM[offset]) != value) {
kinetis_hsrun_disable();
uint8_t stat = FTFL_FSTAT & 0x70;
if (stat) FTFL_FSTAT = stat;
*(uint16_t *)(&FlexRAM[offset]) = value;
flexram_wait();
kinetis_hsrun_enable();
}
#ifdef HANDLE_UNALIGNED_WRITES
} else {
if (FlexRAM[offset] != value) {
kinetis_hsrun_disable();
uint8_t stat = FTFL_FSTAT & 0x70;
if (stat) FTFL_FSTAT = stat;
FlexRAM[offset] = value;
flexram_wait();
kinetis_hsrun_enable();
}
if (FlexRAM[offset + 1] != (value >> 8)) {
kinetis_hsrun_disable();
uint8_t stat = FTFL_FSTAT & 0x70;
if (stat) FTFL_FSTAT = stat;
FlexRAM[offset + 1] = value >> 8;
flexram_wait();
kinetis_hsrun_enable();
}
}
#endif
@@ -227,33 +262,57 @@ void eeprom_write_dword(uint32_t *addr, uint32_t value)
case 0:
#endif
if (*(uint32_t *)(&FlexRAM[offset]) != value) {
kinetis_hsrun_disable();
uint8_t stat = FTFL_FSTAT & 0x70;
if (stat) FTFL_FSTAT = stat;
*(uint32_t *)(&FlexRAM[offset]) = value;
flexram_wait();
kinetis_hsrun_enable();
}
return;
#ifdef HANDLE_UNALIGNED_WRITES
case 2:
if (*(uint16_t *)(&FlexRAM[offset]) != value) {
kinetis_hsrun_disable();
uint8_t stat = FTFL_FSTAT & 0x70;
if (stat) FTFL_FSTAT = stat;
*(uint16_t *)(&FlexRAM[offset]) = value;
flexram_wait();
kinetis_hsrun_enable();
}
if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) {
kinetis_hsrun_disable();
uint8_t stat = FTFL_FSTAT & 0x70;
if (stat) FTFL_FSTAT = stat;
*(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16;
flexram_wait();
kinetis_hsrun_enable();
}
return;
default:
if (FlexRAM[offset] != value) {
kinetis_hsrun_disable();
uint8_t stat = FTFL_FSTAT & 0x70;
if (stat) FTFL_FSTAT = stat;
FlexRAM[offset] = value;
flexram_wait();
kinetis_hsrun_enable();
}
if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) {
kinetis_hsrun_disable();
uint8_t stat = FTFL_FSTAT & 0x70;
if (stat) FTFL_FSTAT = stat;
*(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8;
flexram_wait();
kinetis_hsrun_enable();
}
if (FlexRAM[offset + 3] != (value >> 24)) {
kinetis_hsrun_disable();
uint8_t stat = FTFL_FSTAT & 0x70;
if (stat) FTFL_FSTAT = stat;
FlexRAM[offset + 3] = value >> 24;
flexram_wait();
kinetis_hsrun_enable();
}
}
#endif
@@ -278,8 +337,12 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len)
val32 |= (*src++ << 16);
val32 |= (*src++ << 24);
if (*(uint32_t *)(&FlexRAM[offset]) != val32) {
kinetis_hsrun_disable();
uint8_t stat = FTFL_FSTAT & 0x70;
if (stat) FTFL_FSTAT = stat;
*(uint32_t *)(&FlexRAM[offset]) = val32;
flexram_wait();
kinetis_hsrun_enable();
}
offset += 4;
len -= 4;
@@ -289,8 +352,12 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len)
val16 = *src++;
val16 |= (*src++ << 8);
if (*(uint16_t *)(&FlexRAM[offset]) != val16) {
kinetis_hsrun_disable();
uint8_t stat = FTFL_FSTAT & 0x70;
if (stat) FTFL_FSTAT = stat;
*(uint16_t *)(&FlexRAM[offset]) = val16;
flexram_wait();
kinetis_hsrun_enable();
}
offset += 2;
len -= 2;
@@ -298,8 +365,12 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len)
// write 8 bits
uint8_t val8 = *src++;
if (FlexRAM[offset] != val8) {
kinetis_hsrun_disable();
uint8_t stat = FTFL_FSTAT & 0x70;
if (stat) FTFL_FSTAT = stat;
FlexRAM[offset] = val8;
flexram_wait();
kinetis_hsrun_enable();
}
offset++;
len--;

+ 1
- 1
teensy3/elapsedMillis.h View File

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

+ 1
- 1
teensy3/keylayouts.c View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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

+ 5
- 4
teensy3/keylayouts.h View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -93,7 +93,7 @@ extern "C"{
#define KEY_MEDIA_PREV_TRACK ( 0xB6 | 0xE400 )
#define KEY_MEDIA_STOP ( 0xB7 | 0xE400 )
#define KEY_MEDIA_EJECT ( 0xB8 | 0xE400 )
#define KEY_MEDIA_RANDOM_PLAY ( 0xB0 | 0xE400 )
#define KEY_MEDIA_RANDOM_PLAY ( 0xB9 | 0xE400 )
#define KEY_MEDIA_PLAY_PAUSE ( 0xCD | 0xE400 )
#define KEY_MEDIA_PLAY_SKIP ( 0xCE | 0xE400 )
#define KEY_MEDIA_MUTE ( 0xE2 | 0xE400 )
@@ -196,6 +196,7 @@ extern "C"{
#define KEYPAD_9 ( 97 | 0xF000 )
#define KEYPAD_0 ( 98 | 0xF000 )
#define KEYPAD_PERIOD ( 99 | 0xF000 )
#define KEY_NON_US_BS ( 100 | 0xF000 )
#define KEY_MENU ( 101 | 0xF000 )
#define KEY_F13 ( 104 | 0xF000 )
#define KEY_F14 ( 105 | 0xF000 )
@@ -1450,7 +1451,7 @@ extern "C"{
#define ASCII_20 KEY_SPACE // 32
#define ASCII_21 KEY_1 + SHIFT_MASK // 33 !
#define ASCII_22 KEY_2 + SHIFT_MASK // 34 "
#define ASCII_23 KEY_BACKSPACE // 35 #
#define ASCII_23 KEY_BACKSLASH // 35 #
#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $
#define ASCII_25 KEY_5 + SHIFT_MASK // 37 %
#define ASCII_26 KEY_7 + SHIFT_MASK // 38 &
@@ -4532,7 +4533,7 @@ extern "C"{
#define ASCII_20 KEY_SPACE // 32
#define ASCII_21 KEY_1 + SHIFT_MASK // 33 !
#define ASCII_22 KEY_2 + SHIFT_MASK // 34 "
#define ASCII_23 KEY_BACKSPACE // 35 #
#define ASCII_23 KEY_BACKSLASH // 35 #
#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $
#define ASCII_25 KEY_5 + SHIFT_MASK // 37 %
#define ASCII_26 KEY_7 + SHIFT_MASK // 38 &

+ 955
- 38
teensy3/kinetis.h
File diff suppressed because it is too large
View File


+ 31
- 1
teensy3/main.cpp View File

@@ -1,4 +1,34 @@
#include "WProgram.h"
/* 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>

extern "C" int main(void)
{

+ 63
- 71
teensy3/math_helper.c View File

@@ -1,40 +1,40 @@
/* ----------------------------------------------------------------------
* Copyright (C) 2010 ARM Limited. All rights reserved.
*
* $Date: 29. November 2010
* $Revision: V1.0.3
*
* Project: CMSIS DSP Library
* Copyright (C) 2010 ARM Limited. All rights reserved.
*
* $Date: 29. November 2010
* $Revision: V1.0.3
*
* Project: CMSIS DSP Library
*
* Title: math_helper.c
*
* Description: Definition of all helper functions required.
*
* Description: Definition of all helper functions required.
*
* Target Processor: Cortex-M4/Cortex-M3
*
* Version 1.0.3 2010/11/29
* Re-organized the CMSIS folders and updated documentation.
*
* Version 1.0.2 2010/11/11
* Documentation updated.
*
* Version 1.0.1 2010/10/05
* Production release and review comments incorporated.
*
* Version 1.0.0 2010/09/20
* Production release and review comments incorporated.
*
* Version 0.0.7 2010/06/10
* Misra-C changes done
*
* Version 1.0.3 2010/11/29
* Re-organized the CMSIS folders and updated documentation.
*
* Version 1.0.2 2010/11/11
* Documentation updated.
*
* Version 1.0.1 2010/10/05
* Production release and review comments incorporated.
*
* Version 1.0.0 2010/09/20
* Production release and review comments incorporated.
*
* Version 0.0.7 2010/06/10
* Misra-C changes done
* -------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
* Include standard header files
* Include standard header files
* -------------------------------------------------------------------- */
#include<math.h>
#include <math.h>
/* ----------------------------------------------------------------------
* Include project header files
* Include project header files
* -------------------------------------------------------------------- */
#include "math_helper.h"
@@ -50,49 +50,43 @@
float arm_snr_f32(float *pRef, float *pTest, uint32_t buffSize)
{
float EnergySignal = 0.0, EnergyError = 0.0;
uint32_t i;
float SNR;
int temp;
int *test;
for (i = 0; i < buffSize; i++)
{
/* Checking for a NAN value in pRef array */
test = (int *)(&pRef[i]);
temp = *test;
if(temp == 0x7FC00000)
{
return(0);
}
/* Checking for a NAN value in pTest array */
test = (int *)(&pTest[i]);
temp = *test;
if(temp == 0x7FC00000)
{
return(0);
}
EnergySignal += pRef[i] * pRef[i];
EnergyError += (pRef[i] - pTest[i]) * (pRef[i] - pTest[i]);
}
float EnergySignal = 0.0;
float EnergyError = 0.0;
uint32_t i;
float SNR;
int temp;
int *test;
for (i = 0; i < buffSize; i++) {
/* Checking for a NAN value in pRef array */
test = (int *)(&pRef[i]);
temp = *test;
if (temp == 0x7FC00000) {
return(0);
}
/* Checking for a NAN value in pTest array */
test = (int *)(&pTest[i]);
temp = *test;
if (temp == 0x7FC00000) {
return(0);
}
EnergySignal += pRef[i] * pRef[i];
EnergyError += (pRef[i] - pTest[i]) * (pRef[i] - pTest[i]);
}
/* Checking for a NAN value in EnergyError */
test = (int *)(&EnergyError);
temp = *test;
if(temp == 0x7FC00000)
{
return(0);
}
SNR = 10 * log10 (EnergySignal / EnergyError);
temp = *test;
return (SNR);
if(temp == 0x7FC00000) {
return(0);
}
SNR = 10 * log10f(EnergySignal / EnergyError);
return (SNR);
}
@@ -128,18 +122,16 @@ void arm_float_to_q12_20(float *pIn, q31_t * pOut, uint32_t numSamples)
{
uint32_t i;
for (i = 0; i < numSamples; i++)
{
/* 1048576.0f corresponds to pow(2, 20) */
for (i = 0; i < numSamples; i++) {
/* 1048576.0f corresponds to pow(2, 20) */
pOut[i] = (q31_t) (pIn[i] * 1048576.0f);
pOut[i] += pIn[i] > 0 ? 0.5 : -0.5;
if (pIn[i] == (float) 1.0)
{
if (pIn[i] == (float) 1.0) {
pOut[i] = 0x000FFFFF;
}
}
}
}
}
/**

+ 7
- 0
teensy3/memcpy-armv7m.S View File

@@ -28,7 +28,14 @@

#if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
#if defined (__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__)
/*
* Let __ARM_FEATURE_UNALIGNED be set by the achitechture and the compiler flags:
* -munaligned-access
* -mno-unaligned-access
* instead of always setting it here.
*
#define __ARM_FEATURE_UNALIGNED 1
*/
/* This memcpy routine is optimised for Cortex-M3/M4 cores with/without
unaligned access.

+ 288
- 37
teensy3/mk20dx128.c View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -10,10 +10,10 @@
* 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
* 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
* 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.
@@ -31,6 +31,26 @@
#include "kinetis.h"
#include "core_pins.h" // testing only
#include "ser_print.h" // testing only
#include <errno.h>


// Flash Security Setting. On Teensy 3.2, you can lock the MK20 chip to prevent
// anyone from reading your code. You CAN still reprogram your Teensy while
// security is set, but the bootloader will be unable to respond to auto-reboot
// requests from Arduino. Pressing the program button will cause a full chip
// erase to gain access, because the bootloader chip is locked out. Normally,
// erase occurs when uploading begins, so if you press the Program button
// accidentally, simply power cycling will run your program again. When
// security is locked, any Program button press causes immediate full erase.
// Special care must be used with the Program button, because it must be made
// accessible to initiate reprogramming, but it must not be accidentally
// pressed when Teensy Loader is not being used to reprogram. To set lock the
// security change this to 0xDC. Teensy 3.0 and 3.1 do not support security lock.
#define FSEC 0xDE

// Flash Options
#define FOPT 0xF9


extern unsigned long _stext;
extern unsigned long _etext;
@@ -46,7 +66,7 @@ extern unsigned long _estack;

extern int main (void);
void ResetHandler(void);
void _init_Teensyduino_internal_(void);
void _init_Teensyduino_internal_(void) __attribute__((noinline));
void __libc_init_array(void);


@@ -117,12 +137,6 @@ void unused_isr(void)
fault_isr();
}

extern volatile uint32_t systick_millis_count;
void systick_default_isr(void)
{
systick_millis_count++;
}

void nmi_isr(void) __attribute__ ((weak, alias("unused_isr")));
void hard_fault_isr(void) __attribute__ ((weak, alias("fault_isr")));
void memmanage_fault_isr(void) __attribute__ ((weak, alias("fault_isr")));
@@ -131,7 +145,7 @@ void usage_fault_isr(void) __attribute__ ((weak, alias("fault_isr")));
void svcall_isr(void) __attribute__ ((weak, alias("unused_isr")));
void debugmonitor_isr(void) __attribute__ ((weak, alias("unused_isr")));
void pendablesrvreq_isr(void) __attribute__ ((weak, alias("unused_isr")));
void systick_isr(void) __attribute__ ((weak, alias("systick_default_isr")));
void systick_isr(void);

void dma_ch0_isr(void) __attribute__ ((weak, alias("unused_isr")));
void dma_ch1_isr(void) __attribute__ ((weak, alias("unused_isr")));
@@ -640,7 +654,7 @@ void (* const _VectorsFlash[NVIC_NUM_INTERRUPTS+16])(void) =
__attribute__ ((section(".flashconfig"), used))
const uint8_t flashconfigbytes[16] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF
0xFF, 0xFF, 0xFF, 0xFF, FSEC, FOPT, 0xFF, 0xFF
};


@@ -666,10 +680,11 @@ void startup_early_hook(void) __attribute__ ((weak, alias("startup_default_earl
void startup_late_hook(void) __attribute__ ((weak, alias("startup_default_late_hook")));


#ifdef __clang__
// Clang seems to generate slightly larger code with Os than gcc
#if defined(__PURE_CODE__) || !defined(__OPTIMIZE__) || defined(__clang__)
// cases known to compile too large for 0-0x400 memory region
__attribute__ ((optimize("-Os")))
#else
// hopefully all others fit into startup section (below 0x400)
__attribute__ ((section(".startup"),optimize("-Os")))
#endif
void ResetHandler(void)
@@ -704,9 +719,9 @@ void ResetHandler(void)
SIM_SCGC3 = SIM_SCGC3_ADC1 | SIM_SCGC3_FTM2 | SIM_SCGC3_FTM3;
SIM_SCGC5 = 0x00043F82; // clocks active to all GPIO
SIM_SCGC6 = SIM_SCGC6_RTC | SIM_SCGC6_FTM0 | SIM_SCGC6_FTM1 | SIM_SCGC6_ADC0 | SIM_SCGC6_FTFL;
PORTC_PCR5 = PORT_PCR_MUX(1) | PORT_PCR_DSE | PORT_PCR_SRE;
GPIOC_PDDR |= (1<<5);
GPIOC_PSOR = (1<<5);
//PORTC_PCR5 = PORT_PCR_MUX(1) | PORT_PCR_DSE | PORT_PCR_SRE;
//GPIOC_PDDR |= (1<<5);
//GPIOC_PSOR = (1<<5);
//while (1);
#elif defined(__MKL26Z64__)
SIM_SCGC4 = SIM_SCGC4_USBOTG | 0xF0000030;
@@ -730,8 +745,10 @@ void ResetHandler(void)
UART0_C2 = UART_C2_TE;
PORTB_PCR17 = PORT_PCR_MUX(3);
#endif
#ifdef KINETISK
// if the RTC oscillator isn't enabled, get it started early
#if defined(KINETISK) && !defined(__MK66FX1M0__)
// If the RTC oscillator isn't enabled, get it started early.
// But don't do this early on Teensy 3.6 - RTC_CR depends on 3.3V+VBAT
// which may be ~0.4V "behind" 3.3V if the power ramps up slowly.
if (!(RTC_CR & RTC_CR_OSCE)) {
RTC_SR = 0;
RTC_CR = RTC_CR_SC16P | RTC_CR_SC4P | RTC_CR_OSCE;
@@ -790,7 +807,7 @@ void ResetHandler(void)
#else
#if defined(KINETISK)
// enable capacitors for crystal
OSC0_CR = OSC_SC8P | OSC_SC2P;
OSC0_CR = OSC_SC8P | OSC_SC2P | OSC_ERCLKEN;
#elif defined(KINETISL)
// enable capacitors for crystal
OSC0_CR = OSC_SC8P | OSC_SC2P | OSC_ERCLKEN;
@@ -826,7 +843,18 @@ void ResetHandler(void)
SMC_PMCTRL = SMC_PMCTRL_RUNM(3); // enter HSRUN mode
while (SMC_PMSTAT != SMC_PMSTAT_HSRUN) ; // wait for HSRUN
#endif
#if F_CPU == 192000000
#if F_CPU == 256000000
//See table in 27.4.6 MCG Control 6 Register (MCG_C6)
//16 -> Multiply factor 32. 32*8MHz =256MHz
MCG_C5 = MCG_C5_PRDIV0(0);
MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(16);
#elif F_CPU == 240000000
MCG_C5 = MCG_C5_PRDIV0(0);
MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(14);
#elif F_CPU == 216000000
MCG_C5 = MCG_C5_PRDIV0(0);
MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(11);
#elif F_CPU == 192000000
MCG_C5 = MCG_C5_PRDIV0(0);
MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(8);
#elif F_CPU == 180000000
@@ -879,39 +907,115 @@ void ResetHandler(void)
#endif
#endif
// now program the clock dividers
#if F_CPU == 192000000
// config divisors: 192 MHz core, 48 MHz bus, 27.4 MHz flash, USB = 192 * 4
#if F_CPU == 256000000
// config divisors: 256 MHz core, 64 MHz bus, 32 MHz flash, USB = IRC48M
// TODO: gradual ramp-up for HSRUN mode
#if F_BUS == 64000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(3) | SIM_CLKDIV1_OUTDIV4(7);
#elif F_BUS == 128000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(7);
#else
#error "This F_CPU & F_BUS combination is not supported"
#endif
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(0);
#elif F_CPU == 240000000
// config divisors: 240 MHz core, 60 MHz bus, 30 MHz flash, USB = 240 / 5
// TODO: gradual ramp-up for HSRUN mode
#if F_BUS == 60000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(3) | SIM_CLKDIV1_OUTDIV4(7);
#elif F_BUS == 80000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(2) | SIM_CLKDIV1_OUTDIV4(7);
#elif F_BUS == 120000000
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(4);
#elif F_CPU == 216000000
// config divisors: 216 MHz core, 54 MHz bus, 27 MHz flash, USB = IRC48M
// TODO: gradual ramp-up for HSRUN mode
#if F_BUS == 54000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(3) | SIM_CLKDIV1_OUTDIV4(7);
#elif F_BUS == 72000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(2) | SIM_CLKDIV1_OUTDIV4(7);
#elif F_BUS == 108000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(7);
#else
#error "This F_CPU & F_BUS combination is not supported"
#endif
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(0);
#elif F_CPU == 192000000
// config divisors: 192 MHz core, 48 MHz bus, 27.4 MHz flash, USB = 192 / 4
// TODO: gradual ramp-up for HSRUN mode
#if F_BUS == 48000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(3) | SIM_CLKDIV1_OUTDIV4(6);
#elif F_BUS == 64000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(2) | SIM_CLKDIV1_OUTDIV4(6);
#elif F_BUS == 96000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(6);
#else
#error "This F_CPU & F_BUS combination is not supported"
#endif
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(3);
#elif F_CPU == 180000000
// config divisors: 180 MHz core, 60 MHz bus, 25.7 MHz flash, USB = not feasible
// config divisors: 180 MHz core, 60 MHz bus, 25.7 MHz flash, USB = IRC48M
#if F_BUS == 60000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(2) | SIM_CLKDIV1_OUTDIV4(6);
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(6) | SIM_CLKDIV2_USBFRAC;
#elif F_BUS == 90000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(6);
#else
#error "This F_CPU & F_BUS combination is not supported"
#endif
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(0);
#elif F_CPU == 168000000
// config divisors: 168 MHz core, 56 MHz bus, 28 MHz flash, USB = 168 * 2 / 7
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(2) | SIM_CLKDIV1_OUTDIV4(5);
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(6) | SIM_CLKDIV2_USBFRAC;
#elif F_CPU == 144000000
// config divisors: 144 MHz core, 48 MHz bus, 28.8 MHz flash, USB = 144 / 3
#if F_BUS == 48000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(2) | SIM_CLKDIV1_OUTDIV4(4);
#elif F_BUS == 72000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(4);
#else
#error "This F_CPU & F_BUS combination is not supported"
#endif
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(2);
#elif F_CPU == 120000000
// config divisors: 120 MHz core, 60 MHz bus, 24 MHz flash, USB = 128 * 2 / 5
#if F_BUS == 60000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(4);
#elif F_BUS == 120000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) | SIM_CLKDIV1_OUTDIV4(4);
#else
#error "This F_CPU & F_BUS combination is not supported"
#endif
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(4) | SIM_CLKDIV2_USBFRAC;
#elif F_CPU == 96000000
// config divisors: 96 MHz core, 48 MHz bus, 24 MHz flash, USB = 96 / 2
#if F_BUS == 48000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(3);
#elif F_BUS == 96000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) | SIM_CLKDIV1_OUTDIV4(3);
#else
#error "This F_CPU & F_BUS combination is not supported"
#endif
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1);
#elif F_CPU == 72000000
// config divisors: 72 MHz core, 36 MHz bus, 24 MHz flash, USB = 72 * 2 / 3
#if F_BUS == 36000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(2);
#elif F_BUS == 72000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) | SIM_CLKDIV1_OUTDIV4(2);
#else
#error "This F_CPU & F_BUS combination is not supported"
#endif
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(2) | SIM_CLKDIV2_USBFRAC;
#elif F_CPU == 48000000
// config divisors: 48 MHz core, 48 MHz bus, 24 MHz flash, USB = 96 / 2
#if defined(KINETISK)
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(3);
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV3(1) | SIM_CLKDIV1_OUTDIV4(3);
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1);
#elif defined(KINETISL)
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV4(1);
@@ -919,7 +1023,7 @@ void ResetHandler(void)
#elif F_CPU == 24000000
// config divisors: 24 MHz core, 24 MHz bus, 24 MHz flash, USB = 96 / 2
#if defined(KINETISK)
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV2(3) | SIM_CLKDIV1_OUTDIV4(3);
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV2(3) | SIM_CLKDIV1_OUTDIV3(3) | SIM_CLKDIV1_OUTDIV4(3);
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(1);
#elif defined(KINETISL)
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV4(0);
@@ -927,14 +1031,14 @@ void ResetHandler(void)
#elif F_CPU == 16000000
// config divisors: 16 MHz core, 16 MHz bus, 16 MHz flash
#if defined(KINETISK)
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) | SIM_CLKDIV1_OUTDIV4(0);
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) | SIM_CLKDIV1_OUTDIV3(0) | SIM_CLKDIV1_OUTDIV4(0);
#elif defined(KINETISL)
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV4(0);
#endif
#elif F_CPU == 8000000
// config divisors: 8 MHz core, 8 MHz bus, 8 MHz flash
#if defined(KINETISK)
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV4(1);
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV2(1) | SIM_CLKDIV1_OUTDIV3(1) | SIM_CLKDIV1_OUTDIV4(1);
#elif defined(KINETISL)
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(1) | SIM_CLKDIV1_OUTDIV4(0);
#endif
@@ -945,7 +1049,7 @@ void ResetHandler(void)
// here we can go into vlpr?
// config divisors: 4 MHz core, 4 MHz bus, 4 MHz flash
#if defined(KINETISK)
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV2(3) | SIM_CLKDIV1_OUTDIV4(3);
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV2(3) | SIM_CLKDIV1_OUTDIV3(3) | SIM_CLKDIV1_OUTDIV4(3);
#elif defined(KINETISL)
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(3) | SIM_CLKDIV1_OUTDIV4(0);
#endif
@@ -961,7 +1065,7 @@ void ResetHandler(void)
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV4(1);
#endif
#else
#error "Error, F_CPU must be 192, 180, 168, 144, 120, 96, 72, 48, 24, 16, 8, 4, or 2 MHz"
#error "Error, F_CPU must be 256, 240, 216, 192, 180, 168, 144, 120, 96, 72, 48, 24, 16, 8, 4, or 2 MHz"
#endif

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

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

// initialize the SysTick counter
SYST_RVR = (F_CPU / 1000) - 1;
SYST_CVR = 0;
@@ -1040,15 +1158,40 @@ void ResetHandler(void)

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

char *__brkval = (char *)&_ebss;

#ifndef STACK_MARGIN
#if defined(__MKL26Z64__)
#define STACK_MARGIN 512
#elif defined(__MK20DX128__)
#define STACK_MARGIN 1024
#elif defined(__MK20DX256__)
#define STACK_MARGIN 4096
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
#define STACK_MARGIN 8192
#endif
#endif

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"

void * _sbrk(int incr)
{
char *prev = __brkval;
__brkval += incr;
char *prev, *stack;

prev = __brkval;
if (incr != 0) {
__asm__ volatile("mov %0, sp" : "=r" (stack) ::);
if (prev + incr >= stack - STACK_MARGIN) {
errno = ENOMEM;
return (void *)-1;
}
__brkval = prev + incr;
}
return prev;
}

@@ -1109,9 +1252,17 @@ void __cxa_guard_release(char *g)
*g = 1;
}

__attribute__((weak))
void abort(void)
{
while (1) ;
}

#pragma GCC diagnostic pop

int nvic_execution_priority(void)
{
int priority=256;
uint32_t priority=256;
uint32_t primask, faultmask, basepri, ipsr;

// full algorithm in ARM DDI0403D, page B1-639
@@ -1130,3 +1281,103 @@ int nvic_execution_priority(void)
return priority;
}


#if defined(HAS_KINETIS_HSRUN) && F_CPU > 120000000
int kinetis_hsrun_disable(void)
{
if (SMC_PMSTAT == SMC_PMSTAT_HSRUN) {
// First, reduce the CPU clock speed, but do not change
// the peripheral speed (F_BUS). Serial1 & Serial2 baud
// rates will be impacted, but most other peripherals
// will continue functioning at the same speed.
#if F_CPU == 256000000 && F_BUS == 64000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // TODO: TEST
#elif F_CPU == 256000000 && F_BUS == 128000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // TODO: TEST
#elif F_CPU == 240000000 && F_BUS == 60000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // ok
#elif F_CPU == 240000000 && F_BUS == 80000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok
#elif F_CPU == 240000000 && F_BUS == 120000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok
#elif F_CPU == 216000000 && F_BUS == 54000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // ok
#elif F_CPU == 216000000 && F_BUS == 72000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok
#elif F_CPU == 216000000 && F_BUS == 108000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok
#elif F_CPU == 192000000 && F_BUS == 48000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 3, 1, 7); // ok
#elif F_CPU == 192000000 && F_BUS == 64000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok
#elif F_CPU == 192000000 && F_BUS == 96000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok
#elif F_CPU == 180000000 && F_BUS == 60000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 8); // ok
#elif F_CPU == 180000000 && F_BUS == 90000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 7); // ok
#elif F_CPU == 168000000 && F_BUS == 56000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 5); // ok
#elif F_CPU == 144000000 && F_BUS == 48000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(2, 2, 2, 5); // ok
#elif F_CPU == 144000000 && F_BUS == 72000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(1, 1, 1, 5); // ok
#else
return 0;
#endif
// Then turn off HSRUN mode
SMC_PMCTRL = SMC_PMCTRL_RUNM(0);
while (SMC_PMSTAT == SMC_PMSTAT_HSRUN) ; // wait
return 1;
}
return 0;
}

int kinetis_hsrun_enable(void)
{
if (SMC_PMSTAT == SMC_PMSTAT_RUN) {
// Turn HSRUN mode on
SMC_PMCTRL = SMC_PMCTRL_RUNM(3);
while (SMC_PMSTAT != SMC_PMSTAT_HSRUN) {;} // wait
// Then configure clock for full speed
#if F_CPU == 256000000 && F_BUS == 64000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7);
#elif F_CPU == 256000000 && F_BUS == 128000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 7);
#elif F_CPU == 240000000 && F_BUS == 60000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7);
#elif F_CPU == 240000000 && F_BUS == 80000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 7);
#elif F_CPU == 240000000 && F_BUS == 120000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 7);
#elif F_CPU == 216000000 && F_BUS == 54000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 7);
#elif F_CPU == 216000000 && F_BUS == 72000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 7);
#elif F_CPU == 216000000 && F_BUS == 108000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 7);
#elif F_CPU == 192000000 && F_BUS == 48000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 3, 0, 6);
#elif F_CPU == 192000000 && F_BUS == 64000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 6);
#elif F_CPU == 192000000 && F_BUS == 96000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 6);
#elif F_CPU == 180000000 && F_BUS == 60000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 6);
#elif F_CPU == 180000000 && F_BUS == 90000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 6);
#elif F_CPU == 168000000 && F_BUS == 56000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 5);
#elif F_CPU == 144000000 && F_BUS == 48000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 2, 0, 4);
#elif F_CPU == 144000000 && F_BUS == 72000000
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIVS(0, 1, 0, 4);
#else
return 0;
#endif
return 1;
}
return 0;
}
#endif // HAS_KINETIS_HSRUN && F_CPU > 120000000


+ 2
- 0
teensy3/mk20dx128.h View File

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

#ifndef _mk20dx128_h_
#define _mk20dx128_h_
#include "kinetis.h" // mk20dx128.h renamed to kinetis.h

+ 4
- 2
teensy3/mk20dx128.ld View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -10,7 +10,7 @@
* 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
* 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
@@ -34,6 +34,7 @@ MEMORY
RAM (rwx) : ORIGIN = 0x1FFFE000, LENGTH = 16K
}

ENTRY(_VectorsFlash)

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

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



+ 5
- 3
teensy3/mk20dx256.ld View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -10,10 +10,10 @@
* 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
* 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
* 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.
@@ -34,6 +34,7 @@ MEMORY
RAM (rwx) : ORIGIN = 0x1FFF8000, LENGTH = 64K
}

ENTRY(_VectorsFlash)

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

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



+ 6
- 4
teensy3/mk64fx512.ld View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -10,10 +10,10 @@
* 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
* 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
* 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.
@@ -31,9 +31,10 @@
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 512K
RAM (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 192K
RAM (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 262136
}

ENTRY(_VectorsFlash)

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

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



+ 5
- 3
teensy3/mk66fx1m0.ld View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -10,10 +10,10 @@
* 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
* 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
* 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.
@@ -34,6 +34,7 @@ MEMORY
RAM (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 256K
}

ENTRY(_VectorsFlash)

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

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



+ 5
- 3
teensy3/mkl26z64.ld View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2014 PJRC.COM, LLC.
* 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
@@ -10,10 +10,10 @@
* 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
* 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
* 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.
@@ -34,6 +34,7 @@ MEMORY
RAM (rwx) : ORIGIN = 0x1FFFF800, LENGTH = 8K
}

ENTRY(_VectorsFlash)

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

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



+ 35
- 0
teensy3/new.cpp View File

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

void * operator new(size_t size)
@@ -20,6 +45,16 @@ void operator delete[](void * ptr)
free(ptr);
}

void operator delete(void * ptr, size_t size)
{
free(ptr);
}

void operator delete[](void * ptr, size_t size)
{
free(ptr);
}

//int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);};
//void __cxa_guard_release (__guard *g) {*(char *)g = 1;};
//void __cxa_guard_abort (__guard *) {};

+ 28
- 1
teensy3/new.h View File

@@ -1,5 +1,30 @@
/* 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.
*
* 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.
*/

/* Header to define new/delete operators as they aren't provided by avr-gcc by default
Taken from http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=59453
Adapted from from http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=59453
*/

#ifndef NEW_H
@@ -13,6 +38,8 @@ void * operator new(size_t size);
void * operator new[](size_t size);
void operator delete(void * ptr);
void operator delete[](void * ptr);
void operator delete(void * ptr, size_t size);
void operator delete[](void * ptr, size_t size);

__extension__ typedef int __guard __attribute__((mode (__DI__)));


+ 107
- 10
teensy3/nonstd.c View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -10,10 +10,10 @@
* 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
* 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
* 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.
@@ -31,9 +31,10 @@
#include "avr_functions.h"
#include <string.h>
#include <stdlib.h>
#include <math.h>


char * ultoa(unsigned long val, char *buf, int radix)
char * ultoa(unsigned long val, char *buf, int radix)
{
unsigned digit;
int i=0, j;
@@ -66,22 +67,117 @@ char * ltoa(long val, char *buf, int radix)
}
}

#define DTOA_UPPER 0x04

char * fcvtf(float, int, int *, int *);
int isnanf (float x);
int isinff (float x);

char * dtostrf(float val, int width, unsigned int precision, char *buf)
{
int decpt, sign, reqd, pad;
const char *s, *e;
char *p;

int awidth = abs(width);
if (isnanf(val)) {
int ndigs = (val<0) ? 4 : 3;
awidth = (awidth > ndigs) ? awidth - ndigs : 0;
if (width<0) {
while (awidth) {
*buf++ = ' ';
awidth--;
}
}
if (copysignf(1.0f, val)<0) *buf++ = '-';
if (DTOA_UPPER) {
*buf++ = 'N'; *buf++ = 'A'; *buf++ = 'N';
} else {
*buf++ = 'n'; *buf++ = 'a'; *buf++ = 'n';
}
while (awidth) {
*buf++ = ' ';
awidth--;
}
*buf = 0;
return buf;
}
if (isinff(val)) {
int ndigs = (val<0) ? 4 : 3;
awidth = (awidth > ndigs) ? awidth - ndigs : 0;
if (width<0) {
while (awidth) {
*buf++ = ' ';
awidth--;
}
}
if (val<0) *buf++ = '-';
if (DTOA_UPPER) {
*buf++ = 'I'; *buf++ = 'N'; *buf++ = 'F';
} else {
*buf++ = 'i'; *buf++ = 'n'; *buf++ = 'f';
}
while (awidth) {
*buf++ = ' ';
awidth--;
}
*buf = 0;
return buf;
}

s = fcvtf(val, precision, &decpt, &sign);

// if only 1 digit in output
if (precision == 0 && decpt == 0) {
// round and move decimal point
s = (*s < '5') ? "0" : "1";
reqd = 1;
} else {
reqd = strlen(s);
if (reqd > decpt) reqd++;
if (decpt == 0) reqd++;
decpt++;
}

// if all zeros, limit to precision
if (-decpt > (int)precision) {
s = "0";
decpt = -precision;
}

reqd = strlen(s);

// add 1 for decimal point
if (reqd > decpt) reqd++;

// add 1 for zero in front of decimal point
if (decpt == 0) reqd++;

// if leading zeros after decimal point
if (decpt < 0 && precision > 0) {
// ensure enough trailing zeros, add 2 for '0.'
reqd = precision + 2;

if (strlen(s) > precision + decpt) {
// bug in fcvtf. e.g. 0.012, precision 2 should return 1 instead of 12.
// However, 1.2, precision 0 returns correct value. So shift values so
// that decimal point is after the first digit, then convert again

int newPrecision = precision;
int newDecimalPoint;

// shift decimal point
while (newPrecision > 0) {
val *= 10.0;
newPrecision--;
}

// round after accounting for leading 0's
s = fcvtf(val, newPrecision, &newDecimalPoint, &sign);

// if rounded up to new digit (e.g. 0.09 to 0.1), move decimal point
if (newDecimalPoint - decpt == precision + 1) decpt++;
}
}

// add 1 for sign if negative
if (sign) reqd++;

p = buf;
e = p + reqd;
pad = width - reqd;
@@ -97,12 +193,13 @@ char * dtostrf(float val, int width, unsigned int precision, char *buf)
else if (decpt < 0 && precision > 0) {
*p++ = '0';
*p++ = '.';
e++;
// print leading zeros
while ( decpt < 0 ) {
decpt++;
*p++ = '0';
}
}
// print digits
while (p < e) {
*p++ = *s++;
if (p == e) break;

+ 2
- 0
teensy3/pgmspace.h View File

@@ -0,0 +1,2 @@
// For compatibility with some ESP8266 programs
#include <avr/pgmspace.h>

+ 121
- 45
teensy3/pins_arduino.h View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -34,61 +34,125 @@
#include <stdint.h>

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

#if defined(__MK20DX128__)
const static uint8_t A10 = 34;
const static uint8_t A11 = 35;
const static uint8_t A12 = 36;
const static uint8_t A13 = 37;
#define PIN_A10 (34)
#define PIN_A11 (35)
#define PIN_A12 (36)
#define PIN_A13 (37)
const static uint8_t A10 = PIN_A10;
const static uint8_t A11 = PIN_A11;
const static uint8_t A12 = PIN_A12;
const static uint8_t A13 = PIN_A13;

#elif defined(__MK20DX256__)
const static uint8_t A10 = 34;
const static uint8_t A11 = 35;
const static uint8_t A12 = 36;
const static uint8_t A13 = 37;
const static uint8_t A14 = 40;
const static uint8_t A15 = 26;
const static uint8_t A16 = 27;
const static uint8_t A17 = 28;
const static uint8_t A18 = 29;
const static uint8_t A19 = 30;
const static uint8_t A20 = 31;
#define PIN_A10 (34)
#define PIN_A11 (35)
#define PIN_A12 (36)
#define PIN_A13 (37)
#define PIN_A14 (40)
#define PIN_A15 (26)
#define PIN_A16 (27)
#define PIN_A17 (28)
#define PIN_A18 (29)
#define PIN_A19 (30)
#define PIN_A20 (31)
const static uint8_t A10 = PIN_A10;
const static uint8_t A11 = PIN_A11;
const static uint8_t A12 = PIN_A12;
const static uint8_t A13 = PIN_A13;
const static uint8_t A14 = PIN_A14;
const static uint8_t A15 = PIN_A15;
const static uint8_t A16 = PIN_A16;
const static uint8_t A17 = PIN_A17;
const static uint8_t A18 = PIN_A18;
const static uint8_t A19 = PIN_A19;
const static uint8_t A20 = PIN_A20;

#elif defined(__MKL26Z64__)
const static uint8_t A10 = 24;
const static uint8_t A11 = 25;
const static uint8_t A12 = 26;
#define PIN_A10 (24)
#define PIN_A11 (25)
#define PIN_A12 (26)
const static uint8_t A10 = PIN_A10;
const static uint8_t A11 = PIN_A11;
const static uint8_t A12 = PIN_A12;

#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
const static uint8_t A10 = 40;
const static uint8_t A11 = 41;
const static uint8_t A12 = 31;
const static uint8_t A13 = 32;
const static uint8_t A14 = 33;
const static uint8_t A15 = 34;
const static uint8_t A16 = 35;
const static uint8_t A17 = 36;
const static uint8_t A18 = 37;
const static uint8_t A19 = 38;
const static uint8_t A20 = 39;
const static uint8_t A21 = 42;
const static uint8_t A22 = 43;
#define PIN_A10 (64)
#define PIN_A11 (65)
#define PIN_A12 (31)
#define PIN_A13 (32)
#define PIN_A14 (33)
#define PIN_A15 (34)
#define PIN_A16 (35)
#define PIN_A17 (36)
#define PIN_A18 (37)
#define PIN_A19 (38)
#define PIN_A20 (39)
#define PIN_A21 (66)
#define PIN_A22 (67)
#define PIN_A23 (49)
#define PIN_A24 (50)
#define PIN_A25 (68)
#define PIN_A26 (69)
const static uint8_t A10 = PIN_A10;
const static uint8_t A11 = PIN_A11;
const static uint8_t A12 = PIN_A12;
const static uint8_t A13 = PIN_A13;
const static uint8_t A14 = PIN_A14;
const static uint8_t A15 = PIN_A15;
const static uint8_t A16 = PIN_A16;
const static uint8_t A17 = PIN_A17;
const static uint8_t A18 = PIN_A18;
const static uint8_t A19 = PIN_A19;
const static uint8_t A20 = PIN_A20;
const static uint8_t A21 = PIN_A21;
const static uint8_t A22 = PIN_A22;
const static uint8_t A23 = PIN_A23;
const static uint8_t A24 = PIN_A24;
const static uint8_t A25 = PIN_A25;
const static uint8_t A26 = PIN_A26;
#endif

#define LED_BUILTIN (13)

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

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

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


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

#define digitalPinToPCICR(p) ((volatile uint8_t *)0)
@@ -204,6 +272,14 @@ static inline uint8_t digitalPinToTimer(uint8_t pin)
#define SERIAL_PORT_HARDWARE_OPEN Serial1
#define SERIAL_PORT_HARDWARE_OPEN1 Serial2
#define SERIAL_PORT_HARDWARE_OPEN2 Serial3
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
#define SERIAL_PORT_HARDWARE3 Serial4
#define SERIAL_PORT_HARDWARE4 Serial5
#define SERIAL_PORT_HARDWARE5 Serial6
#define SERIAL_PORT_HARDWARE_OPEN3 Serial4
#define SERIAL_PORT_HARDWARE_OPEN4 Serial5
#define SERIAL_PORT_HARDWARE_OPEN5 Serial6
#endif

#define SerialUSB Serial


+ 353
- 223
teensy3/pins_teensy.c View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -10,10 +10,10 @@
* 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
* 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
* 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.
@@ -80,6 +80,30 @@ const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM
{GPIO_BITBAND_PTR(CORE_PIN37_PORTREG, CORE_PIN37_BIT), &CORE_PIN37_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN38_PORTREG, CORE_PIN38_BIT), &CORE_PIN38_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN39_PORTREG, CORE_PIN39_BIT), &CORE_PIN39_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN40_PORTREG, CORE_PIN40_BIT), &CORE_PIN40_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN41_PORTREG, CORE_PIN41_BIT), &CORE_PIN41_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN42_PORTREG, CORE_PIN42_BIT), &CORE_PIN42_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN43_PORTREG, CORE_PIN43_BIT), &CORE_PIN43_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN44_PORTREG, CORE_PIN44_BIT), &CORE_PIN44_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN45_PORTREG, CORE_PIN45_BIT), &CORE_PIN45_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN46_PORTREG, CORE_PIN46_BIT), &CORE_PIN46_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN47_PORTREG, CORE_PIN47_BIT), &CORE_PIN47_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN48_PORTREG, CORE_PIN48_BIT), &CORE_PIN48_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN49_PORTREG, CORE_PIN49_BIT), &CORE_PIN49_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN50_PORTREG, CORE_PIN50_BIT), &CORE_PIN50_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN51_PORTREG, CORE_PIN51_BIT), &CORE_PIN51_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN52_PORTREG, CORE_PIN52_BIT), &CORE_PIN52_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN53_PORTREG, CORE_PIN53_BIT), &CORE_PIN53_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN54_PORTREG, CORE_PIN54_BIT), &CORE_PIN54_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN55_PORTREG, CORE_PIN55_BIT), &CORE_PIN55_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN56_PORTREG, CORE_PIN56_BIT), &CORE_PIN56_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN57_PORTREG, CORE_PIN57_BIT), &CORE_PIN57_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN58_PORTREG, CORE_PIN58_BIT), &CORE_PIN58_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN59_PORTREG, CORE_PIN59_BIT), &CORE_PIN59_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN60_PORTREG, CORE_PIN60_BIT), &CORE_PIN60_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN61_PORTREG, CORE_PIN61_BIT), &CORE_PIN61_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN62_PORTREG, CORE_PIN62_BIT), &CORE_PIN62_CONFIG},
{GPIO_BITBAND_PTR(CORE_PIN63_PORTREG, CORE_PIN63_BIT), &CORE_PIN63_CONFIG},
#endif
};

@@ -116,16 +140,50 @@ const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM

#endif

static void dummy_isr() {};

typedef void (*voidFuncPtr)(void);
volatile static voidFuncPtr intFunc[CORE_NUM_DIGITAL];
#if defined(KINETISK)
static void porta_interrupt(void);
static void portb_interrupt(void);
static void portc_interrupt(void);
static void portd_interrupt(void);
static void porte_interrupt(void);
#ifdef NO_PORT_ISR_FASTRUN
static void port_A_isr(void);
static void port_B_isr(void);
static void port_C_isr(void);
static void port_D_isr(void);
static void port_E_isr(void);
#else
static void port_A_isr(void) __attribute__ ((section(".fastrun"), noinline, noclone ));
static void port_B_isr(void) __attribute__ ((section(".fastrun"), noinline, noclone ));
static void port_C_isr(void) __attribute__ ((section(".fastrun"), noinline, noclone ));
static void port_D_isr(void) __attribute__ ((section(".fastrun"), noinline, noclone ));
static void port_E_isr(void) __attribute__ ((section(".fastrun"), noinline, noclone ));
#endif

voidFuncPtr isr_table_portA[CORE_MAX_PIN_PORTA+1] = { [0 ... CORE_MAX_PIN_PORTA] = dummy_isr };
voidFuncPtr isr_table_portB[CORE_MAX_PIN_PORTB+1] = { [0 ... CORE_MAX_PIN_PORTB] = dummy_isr };
voidFuncPtr isr_table_portC[CORE_MAX_PIN_PORTC+1] = { [0 ... CORE_MAX_PIN_PORTC] = dummy_isr };
voidFuncPtr isr_table_portD[CORE_MAX_PIN_PORTD+1] = { [0 ... CORE_MAX_PIN_PORTD] = dummy_isr };
voidFuncPtr isr_table_portE[CORE_MAX_PIN_PORTE+1] = { [0 ... CORE_MAX_PIN_PORTE] = dummy_isr };

// The Pin Config Register is used to look up the correct interrupt table
// for the corresponding port.
static inline voidFuncPtr* getIsrTable(volatile uint32_t *config) {
voidFuncPtr* isr_table = NULL;
if(&PORTA_PCR0 <= config && config <= &PORTA_PCR31) isr_table = isr_table_portA;
else if(&PORTB_PCR0 <= config && config <= &PORTB_PCR31) isr_table = isr_table_portB;
else if(&PORTC_PCR0 <= config && config <= &PORTC_PCR31) isr_table = isr_table_portC;
else if(&PORTD_PCR0 <= config && config <= &PORTD_PCR31) isr_table = isr_table_portD;
else if(&PORTE_PCR0 <= config && config <= &PORTE_PCR31) isr_table = isr_table_portE;
return isr_table;
}

inline uint32_t getPinIndex(volatile uint32_t *config) {
uintptr_t v = (uintptr_t) config;
// There are 32 pin config registers for each port, each port starting at a round address.
// They are spaced 4 bytes apart.
return (v % 128) / 4;
}
#elif defined(KINETISL)
volatile static voidFuncPtr intFunc[CORE_NUM_DIGITAL] = { [0 ... CORE_NUM_DIGITAL-1] = dummy_isr };
static void porta_interrupt(void);
static void portcd_interrupt(void);
#endif
@@ -151,17 +209,31 @@ void attachInterrupt(uint8_t pin, void (*function)(void), int mode)
}
mask = (mask << 16) | 0x01000000;
config = portConfigRegister(pin);

if ((*config & 0x00000700) == 0) {
// for compatibility with programs which depend
// on AVR hardware default to input mode.
pinMode(pin, INPUT);
}
#if defined(KINETISK)
attachInterruptVector(IRQ_PORTA, porta_interrupt);
attachInterruptVector(IRQ_PORTB, portb_interrupt);
attachInterruptVector(IRQ_PORTC, portc_interrupt);
attachInterruptVector(IRQ_PORTD, portd_interrupt);
attachInterruptVector(IRQ_PORTE, porte_interrupt);
attachInterruptVector(IRQ_PORTA, port_A_isr);
attachInterruptVector(IRQ_PORTB, port_B_isr);
attachInterruptVector(IRQ_PORTC, port_C_isr);
attachInterruptVector(IRQ_PORTD, port_D_isr);
attachInterruptVector(IRQ_PORTE, port_E_isr);
voidFuncPtr* isr_table = getIsrTable(config);
if(!isr_table) return;
uint32_t pin_index = getPinIndex(config);
__disable_irq();
cfg = *config;
cfg &= ~0x000F0000; // disable any previous interrupt
*config = cfg;
isr_table[pin_index] = function; // set the function pointer
cfg |= mask;
*config = cfg; // enable the new interrupt
__enable_irq();
#elif defined(KINETISL)
attachInterruptVector(IRQ_PORTA, porta_interrupt);
attachInterruptVector(IRQ_PORTCD, portcd_interrupt);
#endif
__disable_irq();
cfg = *config;
cfg &= ~0x000F0000; // disable any previous interrupt
@@ -170,6 +242,7 @@ void attachInterrupt(uint8_t pin, void (*function)(void), int mode)
cfg |= mask;
*config = cfg; // enable the new interrupt
__enable_irq();
#endif
}

void detachInterrupt(uint8_t pin)
@@ -177,185 +250,87 @@ void detachInterrupt(uint8_t pin)
volatile uint32_t *config;

config = portConfigRegister(pin);
#if defined(KINETISK)
voidFuncPtr* isr_table = getIsrTable(config);
if(!isr_table) return;
uint32_t pin_index = getPinIndex(config);
__disable_irq();
*config = ((*config & ~0x000F0000) | 0x01000000);
intFunc[pin] = NULL;
isr_table[pin_index] = dummy_isr;
__enable_irq();
#elif defined(KINETISL)
__disable_irq();
*config = ((*config & ~0x000F0000) | 0x01000000);
intFunc[pin] = dummy_isr;
__enable_irq();
#endif
}

#if defined(__MK20DX128__) || defined(__MK20DX256__)

static void porta_interrupt(void)
{
uint32_t isfr = PORTA_ISFR;
PORTA_ISFR = isfr;
if ((isfr & CORE_PIN3_BITMASK) && intFunc[3]) intFunc[3]();
if ((isfr & CORE_PIN4_BITMASK) && intFunc[4]) intFunc[4]();
if ((isfr & CORE_PIN24_BITMASK) && intFunc[24]) intFunc[24]();
if ((isfr & CORE_PIN33_BITMASK) && intFunc[33]) intFunc[33]();
}

static void portb_interrupt(void)
{
uint32_t isfr = PORTB_ISFR;
PORTB_ISFR = isfr;
if ((isfr & CORE_PIN0_BITMASK) && intFunc[0]) intFunc[0]();
if ((isfr & CORE_PIN1_BITMASK) && intFunc[1]) intFunc[1]();
if ((isfr & CORE_PIN16_BITMASK) && intFunc[16]) intFunc[16]();
if ((isfr & CORE_PIN17_BITMASK) && intFunc[17]) intFunc[17]();
if ((isfr & CORE_PIN18_BITMASK) && intFunc[18]) intFunc[18]();
if ((isfr & CORE_PIN19_BITMASK) && intFunc[19]) intFunc[19]();
if ((isfr & CORE_PIN25_BITMASK) && intFunc[25]) intFunc[25]();
if ((isfr & CORE_PIN32_BITMASK) && intFunc[32]) intFunc[32]();
}

static void portc_interrupt(void)
{
// TODO: these are inefficent. Use CLZ somehow....
uint32_t isfr = PORTC_ISFR;
PORTC_ISFR = isfr;
if ((isfr & CORE_PIN9_BITMASK) && intFunc[9]) intFunc[9]();
if ((isfr & CORE_PIN10_BITMASK) && intFunc[10]) intFunc[10]();
if ((isfr & CORE_PIN11_BITMASK) && intFunc[11]) intFunc[11]();
if ((isfr & CORE_PIN12_BITMASK) && intFunc[12]) intFunc[12]();
if ((isfr & CORE_PIN13_BITMASK) && intFunc[13]) intFunc[13]();
if ((isfr & CORE_PIN15_BITMASK) && intFunc[15]) intFunc[15]();
if ((isfr & CORE_PIN22_BITMASK) && intFunc[22]) intFunc[22]();
if ((isfr & CORE_PIN23_BITMASK) && intFunc[23]) intFunc[23]();
if ((isfr & CORE_PIN27_BITMASK) && intFunc[27]) intFunc[27]();
if ((isfr & CORE_PIN28_BITMASK) && intFunc[28]) intFunc[28]();
if ((isfr & CORE_PIN29_BITMASK) && intFunc[29]) intFunc[29]();
if ((isfr & CORE_PIN30_BITMASK) && intFunc[30]) intFunc[30]();
}
typedef void (*voidFuncPtr)(void);

static void portd_interrupt(void)
{
uint32_t isfr = PORTD_ISFR;
PORTD_ISFR = isfr;
if ((isfr & CORE_PIN2_BITMASK) && intFunc[2]) intFunc[2]();
if ((isfr & CORE_PIN5_BITMASK) && intFunc[5]) intFunc[5]();
if ((isfr & CORE_PIN6_BITMASK) && intFunc[6]) intFunc[6]();
if ((isfr & CORE_PIN7_BITMASK) && intFunc[7]) intFunc[7]();
if ((isfr & CORE_PIN8_BITMASK) && intFunc[8]) intFunc[8]();
if ((isfr & CORE_PIN14_BITMASK) && intFunc[14]) intFunc[14]();
if ((isfr & CORE_PIN20_BITMASK) && intFunc[20]) intFunc[20]();
if ((isfr & CORE_PIN21_BITMASK) && intFunc[21]) intFunc[21]();
}
// Using CTZ instead of CLZ is faster, since it allows more efficient bit
// clearing and fast indexing into the pin ISR table.
#define PORT_ISR_FUNCTION_CLZ(port_name) \
static void port_ ## port_name ## _isr(void) { \
uint32_t isfr = PORT ## port_name ##_ISFR; \
PORT ## port_name ##_ISFR = isfr; \
voidFuncPtr* isr_table = isr_table_port ## port_name; \
uint32_t bit_nr; \
while(isfr) { \
bit_nr = __builtin_ctz(isfr); \
isr_table[bit_nr](); \
isfr = isfr & (isfr-1); \
if(!isfr) return; \
} \
}
// END PORT_ISR_FUNCTION_CLZ

static void porte_interrupt(void)
{
uint32_t isfr = PORTE_ISFR;
PORTE_ISFR = isfr;
if ((isfr & CORE_PIN26_BITMASK) && intFunc[26]) intFunc[26]();
if ((isfr & CORE_PIN31_BITMASK) && intFunc[31]) intFunc[31]();
}
#if defined(KINETISK)
PORT_ISR_FUNCTION_CLZ(A)
PORT_ISR_FUNCTION_CLZ(B)
PORT_ISR_FUNCTION_CLZ(C)
PORT_ISR_FUNCTION_CLZ(D)
PORT_ISR_FUNCTION_CLZ(E)
#elif defined(KINETISL)
// Kinetis L (Teensy LC) is based on Cortex M0 and doesn't have hardware
// support for CLZ.

#elif defined(__MKL26Z64__)
#define DISPATCH_PIN_ISR(pin_nr) { voidFuncPtr pin_isr = intFunc[pin_nr]; \
if(isfr & CORE_PIN ## pin_nr ## _BITMASK) pin_isr(); }

static void porta_interrupt(void)
{
uint32_t isfr = PORTA_ISFR;
PORTA_ISFR = isfr;
if ((isfr & CORE_PIN3_BITMASK) && intFunc[3]) intFunc[3]();
if ((isfr & CORE_PIN4_BITMASK) && intFunc[4]) intFunc[4]();
DISPATCH_PIN_ISR(3);
DISPATCH_PIN_ISR(4);
}

static void portcd_interrupt(void)
{
uint32_t isfr = PORTC_ISFR;
PORTC_ISFR = isfr;
if ((isfr & CORE_PIN9_BITMASK) && intFunc[9]) intFunc[9]();
if ((isfr & CORE_PIN10_BITMASK) && intFunc[10]) intFunc[10]();
if ((isfr & CORE_PIN11_BITMASK) && intFunc[11]) intFunc[11]();
if ((isfr & CORE_PIN12_BITMASK) && intFunc[12]) intFunc[12]();
if ((isfr & CORE_PIN13_BITMASK) && intFunc[13]) intFunc[13]();
if ((isfr & CORE_PIN15_BITMASK) && intFunc[15]) intFunc[15]();
if ((isfr & CORE_PIN22_BITMASK) && intFunc[22]) intFunc[22]();
if ((isfr & CORE_PIN23_BITMASK) && intFunc[23]) intFunc[23]();
DISPATCH_PIN_ISR(9);
DISPATCH_PIN_ISR(10);
DISPATCH_PIN_ISR(11);
DISPATCH_PIN_ISR(12);
DISPATCH_PIN_ISR(13);
DISPATCH_PIN_ISR(15);
DISPATCH_PIN_ISR(22);
DISPATCH_PIN_ISR(23);
isfr = PORTD_ISFR;
PORTD_ISFR = isfr;
if ((isfr & CORE_PIN2_BITMASK) && intFunc[2]) intFunc[2]();
if ((isfr & CORE_PIN5_BITMASK) && intFunc[5]) intFunc[5]();
if ((isfr & CORE_PIN6_BITMASK) && intFunc[6]) intFunc[6]();
if ((isfr & CORE_PIN7_BITMASK) && intFunc[7]) intFunc[7]();
if ((isfr & CORE_PIN8_BITMASK) && intFunc[8]) intFunc[8]();
if ((isfr & CORE_PIN14_BITMASK) && intFunc[14]) intFunc[14]();
if ((isfr & CORE_PIN20_BITMASK) && intFunc[20]) intFunc[20]();
if ((isfr & CORE_PIN21_BITMASK) && intFunc[21]) intFunc[21]();
}

#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)

static void porta_interrupt(void)
{
uint32_t isfr = PORTA_ISFR;
PORTA_ISFR = isfr;
if ((isfr & CORE_PIN3_BITMASK) && intFunc[3]) intFunc[3]();
if ((isfr & CORE_PIN4_BITMASK) && intFunc[4]) intFunc[4]();
if ((isfr & CORE_PIN25_BITMASK) && intFunc[25]) intFunc[25]();
if ((isfr & CORE_PIN26_BITMASK) && intFunc[26]) intFunc[26]();
if ((isfr & CORE_PIN27_BITMASK) && intFunc[27]) intFunc[27]();
if ((isfr & CORE_PIN28_BITMASK) && intFunc[28]) intFunc[28]();
if ((isfr & CORE_PIN39_BITMASK) && intFunc[39]) intFunc[39]();
}

static void portb_interrupt(void)
{
uint32_t isfr = PORTB_ISFR;
PORTB_ISFR = isfr;
if ((isfr & CORE_PIN0_BITMASK) && intFunc[0]) intFunc[0]();
if ((isfr & CORE_PIN1_BITMASK) && intFunc[1]) intFunc[1]();
if ((isfr & CORE_PIN16_BITMASK) && intFunc[16]) intFunc[16]();
if ((isfr & CORE_PIN17_BITMASK) && intFunc[17]) intFunc[17]();
if ((isfr & CORE_PIN18_BITMASK) && intFunc[18]) intFunc[18]();
if ((isfr & CORE_PIN19_BITMASK) && intFunc[19]) intFunc[19]();
if ((isfr & CORE_PIN29_BITMASK) && intFunc[29]) intFunc[29]();
if ((isfr & CORE_PIN30_BITMASK) && intFunc[30]) intFunc[30]();
if ((isfr & CORE_PIN31_BITMASK) && intFunc[31]) intFunc[31]();
if ((isfr & CORE_PIN32_BITMASK) && intFunc[32]) intFunc[32]();
}

static void portc_interrupt(void)
{
// TODO: these are inefficent. Use CLZ somehow....
uint32_t isfr = PORTC_ISFR;
PORTC_ISFR = isfr;
if ((isfr & CORE_PIN9_BITMASK) && intFunc[9]) intFunc[9]();
if ((isfr & CORE_PIN10_BITMASK) && intFunc[10]) intFunc[10]();
if ((isfr & CORE_PIN11_BITMASK) && intFunc[11]) intFunc[11]();
if ((isfr & CORE_PIN12_BITMASK) && intFunc[12]) intFunc[12]();
if ((isfr & CORE_PIN13_BITMASK) && intFunc[13]) intFunc[13]();
if ((isfr & CORE_PIN15_BITMASK) && intFunc[15]) intFunc[15]();
if ((isfr & CORE_PIN22_BITMASK) && intFunc[22]) intFunc[22]();
if ((isfr & CORE_PIN23_BITMASK) && intFunc[23]) intFunc[23]();
if ((isfr & CORE_PIN35_BITMASK) && intFunc[35]) intFunc[35]();
if ((isfr & CORE_PIN36_BITMASK) && intFunc[36]) intFunc[36]();
if ((isfr & CORE_PIN37_BITMASK) && intFunc[37]) intFunc[37]();
if ((isfr & CORE_PIN38_BITMASK) && intFunc[38]) intFunc[38]();
}

static void portd_interrupt(void)
{
uint32_t isfr = PORTD_ISFR;
PORTD_ISFR = isfr;
if ((isfr & CORE_PIN2_BITMASK) && intFunc[2]) intFunc[2]();
if ((isfr & CORE_PIN5_BITMASK) && intFunc[5]) intFunc[5]();
if ((isfr & CORE_PIN6_BITMASK) && intFunc[6]) intFunc[6]();
if ((isfr & CORE_PIN7_BITMASK) && intFunc[7]) intFunc[7]();
if ((isfr & CORE_PIN8_BITMASK) && intFunc[8]) intFunc[8]();
if ((isfr & CORE_PIN14_BITMASK) && intFunc[14]) intFunc[14]();
if ((isfr & CORE_PIN20_BITMASK) && intFunc[20]) intFunc[20]();
if ((isfr & CORE_PIN21_BITMASK) && intFunc[21]) intFunc[21]();
}

static void porte_interrupt(void)
{
uint32_t isfr = PORTE_ISFR;
PORTE_ISFR = isfr;
if ((isfr & CORE_PIN24_BITMASK) && intFunc[24]) intFunc[24]();
if ((isfr & CORE_PIN33_BITMASK) && intFunc[33]) intFunc[33]();
if ((isfr & CORE_PIN34_BITMASK) && intFunc[34]) intFunc[34]();
DISPATCH_PIN_ISR(2);
DISPATCH_PIN_ISR(5);
DISPATCH_PIN_ISR(6);
DISPATCH_PIN_ISR(7);
DISPATCH_PIN_ISR(8);
DISPATCH_PIN_ISR(14);
DISPATCH_PIN_ISR(20);
DISPATCH_PIN_ISR(21);
}
#undef DISPATCH_PIN_ISR

#endif

@@ -481,12 +456,39 @@ extern void usb_init(void);

#endif

#if F_TIMER == 60000000
#if F_TIMER == 128000000
#define DEFAULT_FTM_MOD (65536 - 1)
#define DEFAULT_FTM_PRESCALE 2
#elif F_TIMER == 120000000
#define DEFAULT_FTM_MOD (61440 - 1)
#define DEFAULT_FTM_PRESCALE 2
#elif F_TIMER == 108000000
#define DEFAULT_FTM_MOD (55296 - 1)
#define DEFAULT_FTM_PRESCALE 2
#elif F_TIMER == 96000000
#define DEFAULT_FTM_MOD (49152 - 1)
#define DEFAULT_FTM_PRESCALE 2
#elif F_TIMER == 90000000
#define DEFAULT_FTM_MOD (46080 - 1)
#define DEFAULT_FTM_PRESCALE 2
#elif F_TIMER == 80000000
#define DEFAULT_FTM_MOD (40960 - 1)
#define DEFAULT_FTM_PRESCALE 2
#elif F_TIMER == 72000000
#define DEFAULT_FTM_MOD (36864 - 1)
#define DEFAULT_FTM_PRESCALE 2
#elif F_TIMER == 64000000
#define DEFAULT_FTM_MOD (65536 - 1)
#define DEFAULT_FTM_PRESCALE 1
#elif F_TIMER == 60000000
#define DEFAULT_FTM_MOD (61440 - 1)
#define DEFAULT_FTM_PRESCALE 1
#elif F_TIMER == 56000000
#define DEFAULT_FTM_MOD (57344 - 1)
#define DEFAULT_FTM_PRESCALE 1
#elif F_TIMER == 54000000
#define DEFAULT_FTM_MOD (55296 - 1)
#define DEFAULT_FTM_PRESCALE 1
#elif F_TIMER == 48000000
#define DEFAULT_FTM_MOD (49152 - 1)
#define DEFAULT_FTM_PRESCALE 1
@@ -514,6 +516,7 @@ extern void usb_init(void);
#endif

//void init_pins(void)
__attribute__((noinline))
void _init_Teensyduino_internal_(void)
{
#if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
@@ -569,12 +572,41 @@ void _init_Teensyduino_internal_(void)
FTM3_C0SC = 0x28;
FTM3_C1SC = 0x28;
FTM3_SC = FTM_SC_CLKS(1) | FTM_SC_PS(DEFAULT_FTM_PRESCALE);
#endif
#if defined(__MK66FX1M0__)
SIM_SCGC2 |= SIM_SCGC2_TPM1;
SIM_SOPT2 |= SIM_SOPT2_TPMSRC(2);
TPM1_CNT = 0;
TPM1_MOD = 32767;
TPM1_C0SC = 0x28;
TPM1_C1SC = 0x28;
TPM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0);
#endif
analog_init();
// for background about this startup delay, please see this conversation

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

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

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

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


@@ -613,7 +645,28 @@ void _init_Teensyduino_internal_(void)
#define FTM1_CH1_PIN 17
#define FTM2_CH0_PIN 3
#define FTM2_CH1_PIN 4
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
#elif defined(__MK64FX512__)
#define FTM0_CH0_PIN 22
#define FTM0_CH1_PIN 23
#define FTM0_CH2_PIN 9
#define FTM0_CH3_PIN 10
#define FTM0_CH4_PIN 6
#define FTM0_CH5_PIN 20
#define FTM0_CH6_PIN 21
#define FTM0_CH7_PIN 5
#define FTM1_CH0_PIN 3
#define FTM1_CH1_PIN 4
#define FTM2_CH0_PIN 29
#define FTM2_CH1_PIN 30
#define FTM3_CH0_PIN 2
#define FTM3_CH1_PIN 14
#define FTM3_CH2_PIN 7
#define FTM3_CH3_PIN 8
#define FTM3_CH4_PIN 35
#define FTM3_CH5_PIN 36
#define FTM3_CH6_PIN 37
#define FTM3_CH7_PIN 38
#elif defined(__MK66FX1M0__)
#define FTM0_CH0_PIN 22
#define FTM0_CH1_PIN 23
#define FTM0_CH2_PIN 9
@@ -634,6 +687,8 @@ void _init_Teensyduino_internal_(void)
#define FTM3_CH5_PIN 36
#define FTM3_CH6_PIN 37
#define FTM3_CH7_PIN 38
#define TPM1_CH0_PIN 16
#define TPM1_CH1_PIN 17
#endif
#define FTM_PINCFG(pin) FTM_PINCFG2(pin)
#define FTM_PINCFG2(pin) CORE_PIN ## pin ## _CONFIG
@@ -708,6 +763,16 @@ void analogWrite(uint8_t pin, int val)
#if defined(FTM2_CH0_PIN)
} else if (pin == FTM2_CH0_PIN || pin == FTM2_CH1_PIN) {
cval = ((uint32_t)val * (uint32_t)(FTM2_MOD + 1)) >> analog_write_res;
#endif
#if defined(FTM3_CH0_PIN)
} else if (pin == FTM3_CH0_PIN || pin == FTM3_CH1_PIN || pin == FTM3_CH2_PIN
|| pin == FTM3_CH3_PIN || pin == FTM3_CH4_PIN || pin == FTM3_CH5_PIN
|| pin == FTM3_CH6_PIN || pin == FTM3_CH7_PIN) {
cval = ((uint32_t)val * (uint32_t)(FTM3_MOD + 1)) >> analog_write_res;
#endif
#if defined(TPM1_CH0_PIN)
} else if (pin == TPM1_CH0_PIN || pin == TPM1_CH1_PIN) {
cval = ((uint32_t)val * (uint32_t)(TPM1_MOD + 1)) >> analog_write_res;
#endif
} else {
cval = ((uint32_t)val * (uint32_t)(FTM0_MOD + 1)) >> analog_write_res;
@@ -835,6 +900,18 @@ void analogWrite(uint8_t pin, int val)
FTM3_C7V = cval;
FTM_PINCFG(FTM3_CH7_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
#endif
#ifdef TPM1_CH0_PIN
case TPM1_CH0_PIN:
TPM1_C0V = cval;
FTM_PINCFG(TPM1_CH0_PIN) = PORT_PCR_MUX(6) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
#endif
#ifdef TPM1_CH1_PIN
case TPM1_CH1_PIN:
TPM1_C1V = cval;
FTM_PINCFG(TPM1_CH1_PIN) = PORT_PCR_MUX(6) | PORT_PCR_DSE | PORT_PCR_SRE;
break;
#endif
default:
digitalWrite(pin, (val > 127) ? HIGH : LOW);
@@ -843,14 +920,17 @@ void analogWrite(uint8_t pin, int val)
}


void analogWriteRes(uint32_t bits)
uint32_t analogWriteRes(uint32_t bits)
{
uint32_t prior_res;
if (bits < 1) {
bits = 1;
} else if (bits > 16) {
bits = 16;
}
prior_res = analog_write_res;
analog_write_res = bits;
return prior_res;
}


@@ -864,14 +944,27 @@ void analogWriteFrequency(uint8_t pin, float frequency)
//serial_print(", freq = ");
//serial_phex32((uint32_t)frequency);
//serial_print("\n");
if (frequency < (float)(F_TIMER >> 7) / 65536.0f) { //If frequency is too low for working with F_TIMER:
ftmClockSource = 2; //Use alternative 31250Hz clock source
ftmClock = 31250; //Set variable for the actual timer clock frequency
} else { //Else do as before:
ftmClockSource = 1; //Use default F_Timer clock source
ftmClock = F_TIMER; //Set variable for the actual timer clock frequency
}

#ifdef TPM1_CH0_PIN
if (pin == TPM1_CH0_PIN || pin == TPM1_CH1_PIN) {
ftmClockSource = 1;
ftmClock = 16000000;
} else
#endif
#if defined(__MKL26Z64__)
// Teensy LC does not support slow clock source (ftmClockSource = 2)
ftmClockSource = 1; // Use default F_TIMER clock source
ftmClock = F_TIMER; // Set variable for the actual timer clock frequency
#else
if (frequency < (float)(F_TIMER >> 7) / 65536.0f) {
// frequency is too low for working with F_TIMER:
ftmClockSource = 2; // Use alternative 31250Hz clock source
ftmClock = 31250; // Set variable for the actual timer clock frequency
} else {
ftmClockSource = 1; // Use default F_TIMER clock source
ftmClock = F_TIMER; // Set variable for the actual timer clock frequency
}
#endif

for (prescale = 0; prescale < 7; prescale++) {
@@ -925,6 +1018,14 @@ void analogWriteFrequency(uint8_t pin, float frequency)
FTM3_SC = FTM_SC_CLKS(ftmClockSource) | FTM_SC_PS(prescale); //Use the new ftmClockSource instead of 1
}
#endif
#ifdef TPM1_CH0_PIN
else if (pin == TPM1_CH0_PIN || pin == TPM1_CH1_PIN) {
TPM1_SC = 0;
TPM1_CNT = 0;
TPM1_MOD = mod;
TPM1_SC = FTM_SC_CLKS(ftmClockSource) | FTM_SC_PS(prescale);
}
#endif
}


@@ -1001,19 +1102,16 @@ void pinMode(uint8_t pin, uint8_t mode)
#else
*portModeRegister(pin) &= ~digitalPinToBitMask(pin);
#endif
if (mode == INPUT || mode == INPUT_PULLUP || mode == INPUT_PULLDOWN) {
if (mode == INPUT) {
*config = PORT_PCR_MUX(1);
if (mode == INPUT_PULLUP) {
*config |= (PORT_PCR_PE | PORT_PCR_PS); // pullup
} else if (mode == INPUT_PULLDOWN) {
*config |= (PORT_PCR_PE); // pulldown
*config &= ~(PORT_PCR_PS);
}
} else {
*config = PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS; // pullup
} else if (mode == INPUT_PULLUP) {
*config = PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS;
} else if (mode == INPUT_PULLDOWN) {
*config = PORT_PCR_MUX(1) | PORT_PCR_PE;
} else { // INPUT_DISABLE
*config = 0;
}
}

}


@@ -1123,7 +1221,13 @@ void delay(uint32_t ms)
}

// TODO: verify these result in correct timeouts...
#if F_CPU == 192000000
#if F_CPU == 256000000
#define PULSEIN_LOOPS_PER_USEC 34
#elif F_CPU == 240000000
#define PULSEIN_LOOPS_PER_USEC 33
#elif F_CPU == 216000000
#define PULSEIN_LOOPS_PER_USEC 31
#elif F_CPU == 192000000
#define PULSEIN_LOOPS_PER_USEC 29
#elif F_CPU == 180000000
#define PULSEIN_LOOPS_PER_USEC 27
@@ -1151,12 +1255,12 @@ void delay(uint32_t ms)
#define PULSEIN_LOOPS_PER_USEC 1
#endif

#if defined(KINETISK)
uint32_t pulseIn_high(volatile uint8_t *reg, uint32_t timeout)
{
uint32_t timeout_count = timeout * PULSEIN_LOOPS_PER_USEC;
uint32_t usec_start, usec_stop;
// wait for any previous pulse to end
while (*reg) {
if (--timeout_count == 0) return 0;
@@ -1204,30 +1308,56 @@ uint32_t pulseIn(uint8_t pin, uint8_t state, uint32_t timeout)
return pulseIn_low(portInputRegister(pin), timeout);;
}

#elif defined(KINETISL)
// For TeencyLC need to use mask on the input register as the register is shared by several IO pins
uint32_t pulseIn_high(volatile uint8_t *reg, uint8_t mask, uint32_t timeout)
{
uint32_t timeout_count = timeout * PULSEIN_LOOPS_PER_USEC;
uint32_t usec_start, usec_stop;
// wait for any previous pulse to end
while (*reg & mask) {
if (--timeout_count == 0) return -1;
}
// wait for the pulse to start
while (!(*reg & mask)) {
if (--timeout_count == 0) return 0;
}
usec_start = micros();
// wait for the pulse to stop
while (*reg & mask) {
if (--timeout_count == 0) return 0;
}
usec_stop = micros();
return usec_stop - usec_start;
}

uint32_t pulseIn_low(volatile uint8_t *reg, uint8_t mask, uint32_t timeout)
{
uint32_t timeout_count = timeout * PULSEIN_LOOPS_PER_USEC;
uint32_t usec_start, usec_stop;
// wait for any previous pulse to end
while (!(*reg & mask)) {
if (--timeout_count == 0) return 0;
}
// wait for the pulse to start
while (*reg & mask) {
if (--timeout_count == 0) return 0;
}
usec_start = micros();
// wait for the pulse to stop
while (!(*reg & mask)) {
if (--timeout_count == 0) return 0;
}
usec_stop = micros();
return usec_stop - usec_start;
}


























// TODO: an inline version should handle the common case where state is const
uint32_t pulseIn(uint8_t pin, uint8_t state, uint32_t timeout)
{
if (pin >= CORE_NUM_DIGITAL) return 0;
if (state) return pulseIn_high(portInputRegister(pin), digitalPinToBitMask(pin), timeout);
return pulseIn_low(portInputRegister(pin), digitalPinToBitMask(pin), timeout);;
}
#endif

+ 30
- 0
teensy3/ser_print.c View File

@@ -1,3 +1,33 @@
/* 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 "kinetis.h"
#include "ser_print.h"


+ 29
- 0
teensy3/ser_print.h View File

@@ -1,3 +1,32 @@
/* 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.
*/

#ifdef __cplusplus
extern "C"{

+ 99
- 30
teensy3/serial1.c View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -10,10 +10,10 @@
* 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
* 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
* 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.
@@ -36,10 +36,14 @@
// Tunable parameters (relatively safe to edit these numbers)
////////////////////////////////////////////////////////////////

#define TX_BUFFER_SIZE 64 // number of outgoing bytes to buffer
#define RX_BUFFER_SIZE 64 // number of incoming bytes to buffer
#define RTS_HIGH_WATERMARK 40 // RTS requests sender to pause
#define RTS_LOW_WATERMARK 26 // RTS allows sender to resume
#ifndef SERIAL1_TX_BUFFER_SIZE
#define SERIAL1_TX_BUFFER_SIZE 64 // number of outgoing bytes to buffer
#endif
#ifndef SERIAL1_RX_BUFFER_SIZE
#define SERIAL1_RX_BUFFER_SIZE 64 // number of incoming bytes to buffer
#endif
#define RTS_HIGH_WATERMARK (SERIAL1_RX_BUFFER_SIZE-24) // RTS requests sender to pause
#define RTS_LOW_WATERMARK (SERIAL1_RX_BUFFER_SIZE-38) // RTS allows sender to resume
#define IRQ_PRIORITY 64 // 0 = highest priority, 255 = lowest


@@ -55,8 +59,8 @@ static uint8_t use9Bits = 0;
#define use9Bits 0
#endif

static volatile BUFTYPE tx_buffer[TX_BUFFER_SIZE];
static volatile BUFTYPE rx_buffer[RX_BUFFER_SIZE];
static volatile BUFTYPE tx_buffer[SERIAL1_TX_BUFFER_SIZE];
static volatile BUFTYPE rx_buffer[SERIAL1_RX_BUFFER_SIZE];
static volatile uint8_t transmitting = 0;
#if defined(KINETISK)
static volatile uint8_t *transmit_pin=NULL;
@@ -75,14 +79,20 @@ static volatile uint8_t transmitting = 0;
#define rts_assert() *(rts_pin+8) = rts_mask;
#define rts_deassert() *(rts_pin+4) = rts_mask;
#endif
#if TX_BUFFER_SIZE > 255
#if SERIAL1_TX_BUFFER_SIZE > 65535
static volatile uint32_t tx_buffer_head = 0;
static volatile uint32_t tx_buffer_tail = 0;
#elif SERIAL1_TX_BUFFER_SIZE > 255
static volatile uint16_t tx_buffer_head = 0;
static volatile uint16_t tx_buffer_tail = 0;
#else
static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0;
#endif
#if RX_BUFFER_SIZE > 255
#if SERIAL1_RX_BUFFER_SIZE > 65535
static volatile uint32_t rx_buffer_head = 0;
static volatile uint32_t rx_buffer_tail = 0;
#elif SERIAL1_RX_BUFFER_SIZE > 255
static volatile uint16_t rx_buffer_head = 0;
static volatile uint16_t rx_buffer_tail = 0;
#else
@@ -117,6 +127,10 @@ void serial_begin(uint32_t divisor)
case 21: CORE_PIN21_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break;
#if defined(KINETISL)
case 3: CORE_PIN3_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(2); break;
case 25: CORE_PIN25_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(4); break;
#endif
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
case 27: CORE_PIN27_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break;
#endif
}
switch (tx_pin_num) {
@@ -124,9 +138,14 @@ void serial_begin(uint32_t divisor)
case 5: CORE_PIN5_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); break;
#if defined(KINETISL)
case 4: CORE_PIN4_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(2); break;
case 24: CORE_PIN24_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(4); break;
#endif
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
case 26: CORE_PIN26_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); break;
#endif
}
#if defined(HAS_KINETISK_UART0)
if (divisor < 32) divisor = 32;
UART0_BDH = (divisor >> 13) & 0x1F;
UART0_BDL = (divisor >> 5) & 0xFF;
UART0_C4 = divisor & 0x1F;
@@ -140,6 +159,7 @@ void serial_begin(uint32_t divisor)
UART0_PFIFO = 0;
#endif
#elif defined(HAS_KINETISL_UART0)
if (divisor < 1) divisor = 1;
UART0_BDH = (divisor >> 8) & 0x1F;
UART0_BDL = divisor & 0xFF;
UART0_C1 = 0;
@@ -170,6 +190,14 @@ void serial_format(uint32_t format)
UART0_C4 = c;
use9Bits = format & 0x80;
#endif
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(KINETISL)
// For T3.5/T3.6/TLC See about turning on 2 stop bit mode
if ( format & 0x100) {
uint8_t bdl = UART0_BDL;
UART0_BDH |= UART_BDH_SBNS; // Turn on 2 stop bits - was turned off by set baud
UART0_BDL = bdl; // Says BDH not acted on until BDL is written
}
#endif
}

void serial_end(void)
@@ -178,8 +206,30 @@ void serial_end(void)
while (transmitting) yield(); // wait for buffered data to send
NVIC_DISABLE_IRQ(IRQ_UART0_STATUS);
UART0_C2 = 0;
CORE_PIN0_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
CORE_PIN1_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
switch (rx_pin_num) {
case 0: CORE_PIN0_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break;
case 21: CORE_PIN21_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break;
#if defined(KINETISL)
case 3: CORE_PIN3_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break;
case 25: CORE_PIN25_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break;
#endif
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
case 27: CORE_PIN27_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break;
#endif
}
switch (tx_pin_num & 127) {
case 1: CORE_PIN1_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break;
case 5: CORE_PIN5_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break;
#if defined(KINETISL)
case 4: CORE_PIN4_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break;
case 24: CORE_PIN24_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break;
#endif
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
case 26: CORE_PIN26_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break;
#endif
}
UART0_S1;
UART0_D; // clear leftover error status
rx_buffer_head = 0;
rx_buffer_tail = 0;
if (rts_pin) rts_deassert();
@@ -208,6 +258,10 @@ void serial_set_tx(uint8_t pin, uint8_t opendrain)
case 5: CORE_PIN5_CONFIG = 0; break; // PTD7
#if defined(KINETISL)
case 4: CORE_PIN4_CONFIG = 0; break; // PTA2
case 24: CORE_PIN24_CONFIG = 0; break; // PTE20
#endif
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
case 26: CORE_PIN26_CONFIG = 0; break; //PTA14
#endif
}
if (opendrain) {
@@ -220,6 +274,10 @@ void serial_set_tx(uint8_t pin, uint8_t opendrain)
case 5: CORE_PIN5_CONFIG = cfg | PORT_PCR_MUX(3); break;
#if defined(KINETISL)
case 4: CORE_PIN4_CONFIG = cfg | PORT_PCR_MUX(2); break;
case 24: CORE_PIN24_CONFIG = cfg | PORT_PCR_MUX(4); break;
#endif
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
case 26: CORE_PIN26_CONFIG = cfg | PORT_PCR_MUX(3); break;
#endif
}
}
@@ -235,6 +293,10 @@ void serial_set_rx(uint8_t pin)
case 21: CORE_PIN21_CONFIG = 0; break; // PTD6
#if defined(KINETISL)
case 3: CORE_PIN3_CONFIG = 0; break; // PTA1
case 25: CORE_PIN25_CONFIG = 0; break; // PTE21
#endif
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
case 27: CORE_PIN27_CONFIG = 0; break; // PTA15
#endif
}
switch (pin) {
@@ -242,6 +304,10 @@ void serial_set_rx(uint8_t pin)
case 21: CORE_PIN21_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break;
#if defined(KINETISL)
case 3: CORE_PIN3_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(2); break;
case 25: CORE_PIN25_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(4); break;
#endif
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
case 27: CORE_PIN27_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break;
#endif
}
}
@@ -304,13 +370,13 @@ void serial_putchar(uint32_t c)
if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return;
if (transmit_pin) transmit_assert();
head = tx_buffer_head;
if (++head >= TX_BUFFER_SIZE) head = 0;
if (++head >= SERIAL1_TX_BUFFER_SIZE) head = 0;
while (tx_buffer_tail == head) {
int priority = nvic_execution_priority();
if (priority <= IRQ_PRIORITY) {
if ((UART0_S1 & UART_S1_TDRE)) {
uint32_t tail = tx_buffer_tail;
if (++tail >= TX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL1_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART0_C3 = (UART0_C3 & ~0x40) | ((n & 0x100) >> 2);
UART0_D = n;
@@ -337,7 +403,7 @@ void serial_write(const void *buf, unsigned int count)
if (transmit_pin) transmit_assert();
while (p < end) {
head = tx_buffer_head;
if (++head >= TX_BUFFER_SIZE) head = 0;
if (++head >= SERIAL1_TX_BUFFER_SIZE) head = 0;
if (tx_buffer_tail == head) {
UART0_C2 = C2_TX_ACTIVE;
do {
@@ -345,7 +411,7 @@ void serial_write(const void *buf, unsigned int count)
if (priority <= IRQ_PRIORITY) {
if ((UART0_S1 & UART_S1_TDRE)) {
uint32_t tail = tx_buffer_tail;
if (++tail >= TX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL1_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART0_C3 = (UART0_C3 & ~0x40) | ((n & 0x100) >> 2);
UART0_D = n;
@@ -381,7 +447,7 @@ int serial_write_buffer_free(void)

head = tx_buffer_head;
tail = tx_buffer_tail;
if (head >= tail) return TX_BUFFER_SIZE - 1 - head + tail;
if (head >= tail) return SERIAL1_TX_BUFFER_SIZE - 1 - head + tail;
return tail - head - 1;
}

@@ -392,7 +458,7 @@ int serial_available(void)
head = rx_buffer_head;
tail = rx_buffer_tail;
if (head >= tail) return head - tail;
return RX_BUFFER_SIZE + head - tail;
return SERIAL1_RX_BUFFER_SIZE + head - tail;
}

int serial_getchar(void)
@@ -403,13 +469,13 @@ int serial_getchar(void)
head = rx_buffer_head;
tail = rx_buffer_tail;
if (head == tail) return -1;
if (++tail >= RX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL1_RX_BUFFER_SIZE) tail = 0;
c = rx_buffer[tail];
rx_buffer_tail = tail;
if (rts_pin) {
int avail;
if (head >= tail) avail = head - tail;
else avail = RX_BUFFER_SIZE + head - tail;
else avail = SERIAL1_RX_BUFFER_SIZE + head - tail;
if (avail <= RTS_LOW_WATERMARK) rts_assert();
}
return c;
@@ -422,7 +488,7 @@ int serial_peek(void)
head = rx_buffer_head;
tail = rx_buffer_tail;
if (head == tail) return -1;
if (++tail >= RX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL1_RX_BUFFER_SIZE) tail = 0;
return rx_buffer[tail];
}

@@ -438,7 +504,7 @@ void serial_clear(void)
if (rts_pin) rts_assert();
}

// status interrupt combines
// status interrupt combines
// Transmit data below watermark UART_S1_TDRE
// Transmit complete UART_S1_TC
// Idle line UART_S1_IDLE
@@ -487,7 +553,7 @@ void uart0_status_isr(void)
n = UART0_D;
}
newhead = head + 1;
if (newhead >= RX_BUFFER_SIZE) newhead = 0;
if (newhead >= SERIAL1_RX_BUFFER_SIZE) newhead = 0;
if (newhead != tail) {
head = newhead;
rx_buffer[head] = n;
@@ -497,7 +563,7 @@ void uart0_status_isr(void)
if (rts_pin) {
int avail;
if (head >= tail) avail = head - tail;
else avail = RX_BUFFER_SIZE + head - tail;
else avail = SERIAL1_RX_BUFFER_SIZE + head - tail;
if (avail >= RTS_HIGH_WATERMARK) rts_deassert();
}
}
@@ -508,7 +574,7 @@ void uart0_status_isr(void)
tail = tx_buffer_tail;
do {
if (tail == head) break;
if (++tail >= TX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL1_TX_BUFFER_SIZE) tail = 0;
avail = UART0_S1;
n = tx_buffer[tail];
if (use9Bits) UART0_C3 = (UART0_C3 & ~0x40) | ((n & 0x100) >> 2);
@@ -519,10 +585,13 @@ void uart0_status_isr(void)
}
#else
if (UART0_S1 & UART_S1_RDRF) {
n = UART0_D;
if (use9Bits && (UART0_C3 & 0x80)) n |= 0x100;
if (use9Bits && (UART0_C3 & 0x80)) {
n = UART0_D | 0x100;
} else {
n = UART0_D;
}
head = rx_buffer_head + 1;
if (head >= RX_BUFFER_SIZE) head = 0;
if (head >= SERIAL1_RX_BUFFER_SIZE) head = 0;
if (head != rx_buffer_tail) {
rx_buffer[head] = n;
rx_buffer_head = head;
@@ -535,7 +604,7 @@ void uart0_status_isr(void)
if (head == tail) {
UART0_C2 = C2_TX_COMPLETING;
} else {
if (++tail >= TX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL1_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART0_C3 = (UART0_C3 & ~0x40) | ((n & 0x100) >> 2);
UART0_D = n;

+ 26
- 22
teensy3/serial1_doughboy.txt View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -10,10 +10,10 @@
* 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
* 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
* 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.
@@ -40,8 +40,12 @@
// Tunable parameters (relatively safe to edit these numbers)
////////////////////////////////////////////////////////////////

#define TX_BUFFER_SIZE 64 // number of outgoing bytes to buffer
#define RX_BUFFER_SIZE 64 // number of incoming bytes to buffer
#ifndef SERIAL1_TX_BUFFER_SIZE
#define SERIAL1_TX_BUFFER_SIZE 64 // number of outgoing bytes to buffer
#endif
#ifndef SERIAL1_RX_BUFFER_SIZE
#define SERIAL1_RX_BUFFER_SIZE 64 // number of incoming bytes to buffer
#endif
#define IRQ_PRIORITY 64 // 0 = highest priority, 255 = lowest


@@ -57,8 +61,8 @@ static uint8_t use9Bits = 0;
#define use9Bits 0
#endif

static volatile BUFTYPE tx_buffer[TX_BUFFER_SIZE];
static volatile BUFTYPE rx_buffer[RX_BUFFER_SIZE];
static volatile BUFTYPE tx_buffer[SERIAL1_TX_BUFFER_SIZE];
static volatile BUFTYPE rx_buffer[SERIAL1_RX_BUFFER_SIZE];
static volatile uint8_t transmitting = 0;
#if defined(KINETISK)
static volatile uint8_t *transmit_pin=NULL;
@@ -70,14 +74,14 @@ static volatile uint8_t transmitting = 0;
#define transmit_assert() *(transmit_pin+4) = transmit_mask;
#define transmit_deassert() *(transmit_pin+8) = transmit_mask;
#endif
#if TX_BUFFER_SIZE > 255
#if SERIAL1_TX_BUFFER_SIZE > 255
static volatile uint16_t tx_buffer_head = 0;
static volatile uint16_t tx_buffer_tail = 0;
#else
static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0;
#endif
#if RX_BUFFER_SIZE > 255
#if SERIAL1_RX_BUFFER_SIZE > 255
static volatile uint16_t rx_buffer_head = 0;
static volatile uint16_t rx_buffer_tail = 0;
#else
@@ -204,13 +208,13 @@ void serial_putchar(uint32_t c)
if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return;
if (transmit_pin) transmit_assert();
head = tx_buffer_head;
if (++head >= TX_BUFFER_SIZE) head = 0;
if (++head >= SERIAL1_TX_BUFFER_SIZE) head = 0;
while (tx_buffer_tail == head) {
int priority = nvic_execution_priority();
if (priority <= IRQ_PRIORITY) {
if ((UART0_S1 & UART_S1_TDRE)) {
uint32_t tail = tx_buffer_tail;
if (++tail >= TX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL1_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART0_C3 = (UART0_C3 & ~0x40) | ((n & 0x100) >> 2);
UART0_D = n;
@@ -238,7 +242,7 @@ void serial_write(const void *buf, unsigned int count)
if (transmit_pin) transmit_assert();
while (p < end) {
head = tx_buffer_head;
if (++head >= TX_BUFFER_SIZE) head = 0;
if (++head >= SERIAL1_TX_BUFFER_SIZE) head = 0;
if (tx_buffer_tail == head) {
UART0_C2 |= UART_C2_TIE;
UART0_C2 &= ~UART_C2_TCIE;
@@ -247,7 +251,7 @@ void serial_write(const void *buf, unsigned int count)
if (priority <= IRQ_PRIORITY) {
if ((UART0_S1 & UART_S1_TDRE)) {
uint32_t tail = tx_buffer_tail;
if (++tail >= TX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL1_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART0_C3 = (UART0_C3 & ~0x40) | ((n & 0x100) >> 2);
UART0_D = n;
@@ -284,7 +288,7 @@ int serial_write_buffer_free(void)

head = tx_buffer_head;
tail = tx_buffer_tail;
if (head >= tail) return TX_BUFFER_SIZE - 1 - head + tail;
if (head >= tail) return SERIAL1_TX_BUFFER_SIZE - 1 - head + tail;
return tail - head - 1;
}

@@ -295,7 +299,7 @@ int serial_available(void)
head = rx_buffer_head;
tail = rx_buffer_tail;
if (head >= tail) return head - tail;
return RX_BUFFER_SIZE + head - tail;
return SERIAL1_RX_BUFFER_SIZE + head - tail;
}

int serial_getchar(void)
@@ -306,14 +310,14 @@ int serial_getchar(void)
head = rx_buffer_head;
tail = rx_buffer_tail;
if (head == tail) return -1;
if (++tail >= RX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL1_RX_BUFFER_SIZE) tail = 0;
c = rx_buffer[tail];
rx_buffer_tail = tail;
#ifdef HAS_KINETISK_UART0_FIFO
if ((UART0_C2 & (UART_C2_RIE | UART_C2_ILIE))==0) {//rx interrupt currently disabled
int freespace;
if (head >= tail) //rx head and tail would be unchanged from above if interrupts were disabled
freespace = RX_BUFFER_SIZE -1 + tail - head;
freespace = SERIAL1_RX_BUFFER_SIZE -1 + tail - head;
else
freespace = tail - head - 1;
if (freespace >= UART0_RCFIFO) {
@@ -333,7 +337,7 @@ int serial_peek(void)
head = rx_buffer_head;
tail = rx_buffer_tail;
if (head == tail) return -1;
if (++tail >= RX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL1_RX_BUFFER_SIZE) tail = 0;
return rx_buffer[tail];
}

@@ -389,7 +393,7 @@ void uart0_status_isr(void)
tail = rx_buffer_tail;
do {
newhead = head + 1;
if (newhead >= RX_BUFFER_SIZE) newhead = 0;
if (newhead >= SERIAL1_RX_BUFFER_SIZE) newhead = 0;
if (UART0_MODEM & UART_MODEM_RXRTSE) {
if (newhead == tail) {
UART0_C2 &= ~(UART_C2_RIE | UART_C2_ILIE);//disable rx interrupts
@@ -414,7 +418,7 @@ void uart0_status_isr(void)
tail = tx_buffer_tail;
do {
if (tail == head) break;
if (++tail >= TX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL1_TX_BUFFER_SIZE) tail = 0;
UART0_S1;
n = tx_buffer[tail];
if (use9Bits) UART0_C3 = (UART0_C3 & ~0x40) | ((n & 0x100) >> 2);
@@ -430,7 +434,7 @@ void uart0_status_isr(void)
if (UART0_S1 & UART_S1_RDRF) {
do {
head = rx_buffer_head + 1;
if (head >= RX_BUFFER_SIZE) head = 0;
if (head >= SERIAL1_RX_BUFFER_SIZE) head = 0;
if (UART0_MODEM & UART_MODEM_RXRTSE) {
if (head == rx_buffer_tail) {
UART0_C2 &= ~(UART_C2_RIE);//disable rx interrupts
@@ -452,7 +456,7 @@ void uart0_status_isr(void)
UART0_C2 |= UART_C2_TCIE;
UART0_C2 &= ~UART_C2_TIE;
} else {
if (++tail >= TX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL1_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART0_C3 = (UART0_C3 & ~0x40) | ((n & 0x100) >> 2);
UART0_D = n;

+ 106
- 40
teensy3/serial2.c View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -10,10 +10,10 @@
* 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
* 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
* 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.
@@ -36,10 +36,14 @@
// Tunable parameters (relatively safe to edit these numbers)
////////////////////////////////////////////////////////////////

#define TX_BUFFER_SIZE 40 // number of outgoing bytes to buffer
#define RX_BUFFER_SIZE 64 // number of incoming bytes to buffer
#define RTS_HIGH_WATERMARK 40 // RTS requests sender to pause
#define RTS_LOW_WATERMARK 26 // RTS allows sender to resume
#ifndef SERIAL2_TX_BUFFER_SIZE
#define SERIAL2_TX_BUFFER_SIZE 40 // number of outgoing bytes to buffer
#endif
#ifndef SERIAL2_RX_BUFFER_SIZE
#define SERIAL2_RX_BUFFER_SIZE 64 // number of incoming bytes to buffer
#endif
#define RTS_HIGH_WATERMARK (SERIAL2_RX_BUFFER_SIZE-24) // RTS requests sender to pause
#define RTS_LOW_WATERMARK (SERIAL2_RX_BUFFER_SIZE-38) // RTS allows sender to resume
#define IRQ_PRIORITY 64 // 0 = highest priority, 255 = lowest

////////////////////////////////////////////////////////////////
@@ -54,8 +58,8 @@ static uint8_t use9Bits = 0;
#define use9Bits 0
#endif

static volatile BUFTYPE tx_buffer[TX_BUFFER_SIZE];
static volatile BUFTYPE rx_buffer[RX_BUFFER_SIZE];
static volatile BUFTYPE tx_buffer[SERIAL2_TX_BUFFER_SIZE];
static volatile BUFTYPE rx_buffer[SERIAL2_RX_BUFFER_SIZE];
static volatile uint8_t transmitting = 0;
#if defined(KINETISK)
static volatile uint8_t *transmit_pin=NULL;
@@ -74,14 +78,20 @@ static volatile uint8_t transmitting = 0;
#define rts_assert() *(rts_pin+8) = rts_mask;
#define rts_deassert() *(rts_pin+4) = rts_mask;
#endif
#if TX_BUFFER_SIZE > 255
#if SERIAL2_TX_BUFFER_SIZE > 65535
static volatile uint32_t tx_buffer_head = 0;
static volatile uint32_t tx_buffer_tail = 0;
#elif SERIAL2_TX_BUFFER_SIZE > 255
static volatile uint16_t tx_buffer_head = 0;
static volatile uint16_t tx_buffer_tail = 0;
#else
static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0;
#endif
#if RX_BUFFER_SIZE > 255
#if SERIAL2_RX_BUFFER_SIZE > 65535
static volatile uint32_t rx_buffer_head = 0;
static volatile uint32_t rx_buffer_tail = 0;
#elif SERIAL2_RX_BUFFER_SIZE > 255
static volatile uint16_t rx_buffer_head = 0;
static volatile uint16_t rx_buffer_tail = 0;
#else
@@ -116,17 +126,26 @@ void serial2_begin(uint32_t divisor)
#if defined(KINETISK)
switch (rx_pin_num) {
case 9: CORE_PIN9_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break;
#if defined(__MK20DX128__) || defined(__MK20DX256__) // T3.0, T3.1, T3.2
case 26: CORE_PIN26_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break;
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__) // T3.5 or T3.6
case 59: CORE_PIN59_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break;
#endif
}
switch (tx_pin_num) {
case 10: CORE_PIN10_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); break;
#if defined(__MK20DX128__) || defined(__MK20DX256__) // T3.0, T3.1, T3.2
case 31: CORE_PIN31_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); break;
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__) // T3.5 or T3.6
case 58: CORE_PIN58_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); break;
#endif
}
#elif defined(KINETISL)
CORE_PIN9_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3);
CORE_PIN10_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3);
#endif
#if defined(HAS_KINETISK_UART1)
if (divisor < 32) divisor = 32;
UART1_BDH = (divisor >> 13) & 0x1F;
UART1_BDL = (divisor >> 5) & 0xFF;
UART1_C4 = divisor & 0x1F;
@@ -140,6 +159,7 @@ void serial2_begin(uint32_t divisor)
UART1_PFIFO = 0;
#endif
#elif defined(HAS_KINETISL_UART1)
if (divisor < 1) divisor = 1;
UART1_BDH = (divisor >> 8) & 0x1F;
UART1_BDL = divisor & 0xFF;
UART1_C1 = 0;
@@ -164,18 +184,20 @@ void serial2_format(uint32_t format)
c = UART1_C3 & ~0x10;
if (format & 0x20) c |= 0x10; // tx invert
UART1_C3 = c;
#ifdef SERIAL_9BIT_SUPPORT
#if defined(SERIAL_9BIT_SUPPORT) && !defined(KINETISL)
c = UART1_C4 & 0x1F;
if (format & 0x08) c |= 0x20; // 9 bit mode with parity (requires 10 bits)
UART1_C4 = c;
use9Bits = format & 0x80;
#endif
// UART1_C1.0 = parity, 0=even, 1=odd
// UART1_C1.1 = parity, 0=disable, 1=enable
// UART1_C1.4 = mode, 1=9bit, 0=8bit
// UART1_C4.5 = mode, 1=10bit, 0=8bit
// UART1_C3.4 = txinv, 0=normal, 1=inverted
// UART1_S2.4 = rxinv, 0=normal, 1=inverted
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(KINETISL)
// For T3.5/T3.6/TLC See about turning on 2 stop bit mode
if ( format & 0x100) {
uint8_t bdl = UART1_BDL;
UART1_BDH |= UART_BDH_SBNS; // Turn on 2 stop bits - was turned off by set baud
UART1_BDL = bdl; // Says BDH not acted on until BDL is written
}
#endif
}

void serial2_end(void)
@@ -184,8 +206,29 @@ void serial2_end(void)
while (transmitting) yield(); // wait for buffered data to send
NVIC_DISABLE_IRQ(IRQ_UART1_STATUS);
UART1_C2 = 0;
CORE_PIN9_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
CORE_PIN10_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
#if defined(KINETISK)
switch (rx_pin_num) {
case 9: CORE_PIN9_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; // PTC3
#if defined(__MK20DX128__) || defined(__MK20DX256__) // T3.0, T3.1, T3.2
case 26: CORE_PIN26_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; // PTE1
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__) // T3.5, T3.6
case 59: CORE_PIN59_CONFIG = 0; break;
#endif
}
switch (tx_pin_num & 127) {
case 10: CORE_PIN10_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; // PTC4
#if defined(__MK20DX128__) || defined(__MK20DX256__) // T3.0, T3.1, T3.2
case 31: CORE_PIN31_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; // PTE0
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__) // T3.5, T3.6
case 58: CORE_PIN58_CONFIG = 0; break;
#endif
}
#elif defined(KINETISL)
CORE_PIN9_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); // PTC3
CORE_PIN10_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); // PTC4
#endif
UART1_S1;
UART1_D; // clear leftover error status
rx_buffer_head = 0;
rx_buffer_tail = 0;
if (rts_pin) rts_deassert();
@@ -209,10 +252,14 @@ void serial2_set_tx(uint8_t pin, uint8_t opendrain)

if (opendrain) pin |= 128;
if (pin == tx_pin_num) return;
if ((SIM_SCGC4 & SIM_SCGC4_UART2)) {
if ((SIM_SCGC4 & SIM_SCGC4_UART1)) {
switch (tx_pin_num & 127) {
case 10: CORE_PIN10_CONFIG = 0; break; // PTC4
#if defined(__MK20DX128__) || defined(__MK20DX256__) // T3.0, T3.1, T3.2
case 31: CORE_PIN31_CONFIG = 0; break; // PTE0
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__) // T3.5, T3.6
case 58: CORE_PIN58_CONFIG = 0; break;
#endif
}
if (opendrain) {
cfg = PORT_PCR_DSE | PORT_PCR_ODE;
@@ -221,7 +268,11 @@ void serial2_set_tx(uint8_t pin, uint8_t opendrain)
}
switch (pin & 127) {
case 10: CORE_PIN10_CONFIG = cfg | PORT_PCR_MUX(3); break;
#if defined(__MK20DX128__) || defined(__MK20DX256__) // T3.0, T3.1, T3.2
case 31: CORE_PIN31_CONFIG = cfg | PORT_PCR_MUX(3); break;
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__) // T3.5, T3.6
case 58: CORE_PIN58_CONFIG = cfg | PORT_PCR_MUX(3); break;
#endif
}
}
tx_pin_num = pin;
@@ -232,14 +283,22 @@ void serial2_set_rx(uint8_t pin)
{
#if defined(KINETISK)
if (pin == rx_pin_num) return;
if ((SIM_SCGC4 & SIM_SCGC4_UART2)) {
if ((SIM_SCGC4 & SIM_SCGC4_UART1)) {
switch (rx_pin_num) {
case 9: CORE_PIN9_CONFIG = 0; break; // PTC3
#if defined(__MK20DX128__) || defined(__MK20DX256__) // T3.0, T3.1, T3.2
case 26: CORE_PIN26_CONFIG = 0; break; // PTE1
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__) // T3.5, T3.6
case 59: CORE_PIN59_CONFIG = 0; break;
#endif
}
switch (pin) {
case 9: CORE_PIN9_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break;
#if defined(__MK20DX128__) || defined(__MK20DX256__) // T3.0, T3.1, T3.2
case 26: CORE_PIN26_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break;
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__) // T3.5, T3.6
case 59: CORE_PIN59_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break;
#endif
}
}
rx_pin_num = pin;
@@ -279,6 +338,10 @@ int serial2_set_cts(uint8_t pin)
if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return 0;
if (pin == 23) {
CORE_PIN23_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_PE; // weak pulldown
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) // on T3.5 or T3.6
} else if (pin == 60) {
CORE_PIN60_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_PE; // weak pulldown
#endif
} else {
UART1_MODEM &= ~UART_MODEM_TXCTSE;
return 0;
@@ -297,13 +360,13 @@ void serial2_putchar(uint32_t c)
if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return;
if (transmit_pin) transmit_assert();
head = tx_buffer_head;
if (++head >= TX_BUFFER_SIZE) head = 0;
if (++head >= SERIAL2_TX_BUFFER_SIZE) head = 0;
while (tx_buffer_tail == head) {
int priority = nvic_execution_priority();
if (priority <= IRQ_PRIORITY) {
if ((UART1_S1 & UART_S1_TDRE)) {
uint32_t tail = tx_buffer_tail;
if (++tail >= TX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL2_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART1_C3 = (UART1_C3 & ~0x40) | ((n & 0x100) >> 2);
UART1_D = n;
@@ -330,7 +393,7 @@ void serial2_write(const void *buf, unsigned int count)
if (transmit_pin) transmit_assert();
while (p < end) {
head = tx_buffer_head;
if (++head >= TX_BUFFER_SIZE) head = 0;
if (++head >= SERIAL2_TX_BUFFER_SIZE) head = 0;
if (tx_buffer_tail == head) {
UART1_C2 = C2_TX_ACTIVE;
do {
@@ -338,7 +401,7 @@ void serial2_write(const void *buf, unsigned int count)
if (priority <= IRQ_PRIORITY) {
if ((UART1_S1 & UART_S1_TDRE)) {
uint32_t tail = tx_buffer_tail;
if (++tail >= TX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL2_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART1_C3 = (UART1_C3 & ~0x40) | ((n & 0x100) >> 2);
UART1_D = n;
@@ -374,7 +437,7 @@ int serial2_write_buffer_free(void)

head = tx_buffer_head;
tail = tx_buffer_tail;
if (head >= tail) return TX_BUFFER_SIZE - 1 - head + tail;
if (head >= tail) return SERIAL2_TX_BUFFER_SIZE - 1 - head + tail;
return tail - head - 1;
}

@@ -385,7 +448,7 @@ int serial2_available(void)
head = rx_buffer_head;
tail = rx_buffer_tail;
if (head >= tail) return head - tail;
return RX_BUFFER_SIZE + head - tail;
return SERIAL2_RX_BUFFER_SIZE + head - tail;
}

int serial2_getchar(void)
@@ -396,13 +459,13 @@ int serial2_getchar(void)
head = rx_buffer_head;
tail = rx_buffer_tail;
if (head == tail) return -1;
if (++tail >= RX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL2_RX_BUFFER_SIZE) tail = 0;
c = rx_buffer[tail];
rx_buffer_tail = tail;
if (rts_pin) {
int avail;
if (head >= tail) avail = head - tail;
else avail = RX_BUFFER_SIZE + head - tail;
else avail = SERIAL2_RX_BUFFER_SIZE + head - tail;
if (avail <= RTS_LOW_WATERMARK) rts_assert();
}
return c;
@@ -415,7 +478,7 @@ int serial2_peek(void)
head = rx_buffer_head;
tail = rx_buffer_tail;
if (head == tail) return -1;
if (++tail >= RX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL2_RX_BUFFER_SIZE) tail = 0;
return rx_buffer[tail];
}

@@ -431,7 +494,7 @@ void serial2_clear(void)
if (rts_pin) rts_assert();
}

// status interrupt combines
// status interrupt combines
// Transmit data below watermark UART_S1_TDRE
// Transmit complete UART_S1_TC
// Idle line UART_S1_IDLE
@@ -480,7 +543,7 @@ void uart1_status_isr(void)
n = UART1_D;
}
newhead = head + 1;
if (newhead >= RX_BUFFER_SIZE) newhead = 0;
if (newhead >= SERIAL2_RX_BUFFER_SIZE) newhead = 0;
if (newhead != tail) {
head = newhead;
rx_buffer[head] = n;
@@ -490,7 +553,7 @@ void uart1_status_isr(void)
if (rts_pin) {
int avail;
if (head >= tail) avail = head - tail;
else avail = RX_BUFFER_SIZE + head - tail;
else avail = SERIAL2_RX_BUFFER_SIZE + head - tail;
if (avail >= RTS_HIGH_WATERMARK) rts_deassert();
}
}
@@ -501,7 +564,7 @@ void uart1_status_isr(void)
tail = tx_buffer_tail;
do {
if (tail == head) break;
if (++tail >= TX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL2_TX_BUFFER_SIZE) tail = 0;
avail = UART1_S1;
n = tx_buffer[tail];
if (use9Bits) UART1_C3 = (UART1_C3 & ~0x40) | ((n & 0x100) >> 2);
@@ -512,13 +575,16 @@ void uart1_status_isr(void)
}
#else
if (UART1_S1 & UART_S1_RDRF) {
n = UART1_D;
if (use9Bits && (UART1_C3 & 0x80)) n |= 0x100;
if (use9Bits && (UART1_C3 & 0x80)) {
n = UART1_D | 0x100;
} else {
n = UART1_D;
}
head = rx_buffer_head + 1;
if (head >= RX_BUFFER_SIZE) head = 0;
if (head >= SERIAL2_RX_BUFFER_SIZE) head = 0;
if (head != rx_buffer_tail) {
rx_buffer[head] = n;
rx_buffer_head = head;
rx_buffer_head = head;
}
}
c = UART1_C2;
@@ -528,7 +594,7 @@ void uart1_status_isr(void)
if (head == tail) {
UART1_C2 = C2_TX_COMPLETING;
} else {
if (++tail >= TX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL2_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART1_C3 = (UART1_C3 & ~0x40) | ((n & 0x100) >> 2);
UART1_D = n;

+ 63
- 27
teensy3/serial3.c View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -10,10 +10,10 @@
* 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
* 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
* 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.
@@ -36,10 +36,14 @@
// Tunable parameters (relatively safe to edit these numbers)
////////////////////////////////////////////////////////////////

#define TX_BUFFER_SIZE 40 // number of outgoing bytes to buffer
#define RX_BUFFER_SIZE 64 // number of incoming bytes to buffer
#define RTS_HIGH_WATERMARK 40 // RTS requests sender to pause
#define RTS_LOW_WATERMARK 26 // RTS allows sender to resume
#ifndef SERIAL3_TX_BUFFER_SIZE
#define SERIAL3_TX_BUFFER_SIZE 40 // number of outgoing bytes to buffer
#endif
#ifndef SERIAL3_RX_BUFFER_SIZE
#define SERIAL3_RX_BUFFER_SIZE 64 // number of incoming bytes to buffer
#endif
#define RTS_HIGH_WATERMARK (SERIAL3_RX_BUFFER_SIZE-24) // RTS requests sender to pause
#define RTS_LOW_WATERMARK (SERIAL3_RX_BUFFER_SIZE-38) // RTS allows sender to resume
#define IRQ_PRIORITY 64 // 0 = highest priority, 255 = lowest


@@ -55,8 +59,8 @@ static uint8_t use9Bits = 0;
#define use9Bits 0
#endif

static volatile BUFTYPE tx_buffer[TX_BUFFER_SIZE];
static volatile BUFTYPE rx_buffer[RX_BUFFER_SIZE];
static volatile BUFTYPE tx_buffer[SERIAL3_TX_BUFFER_SIZE];
static volatile BUFTYPE rx_buffer[SERIAL3_RX_BUFFER_SIZE];
static volatile uint8_t transmitting = 0;
#if defined(KINETISK)
static volatile uint8_t *transmit_pin=NULL;
@@ -75,14 +79,20 @@ static volatile uint8_t transmitting = 0;
#define rts_assert() *(rts_pin+8) = rts_mask;
#define rts_deassert() *(rts_pin+4) = rts_mask;
#endif
#if TX_BUFFER_SIZE > 255
#if SERIAL3_TX_BUFFER_SIZE > 65535
static volatile uint32_t tx_buffer_head = 0;
static volatile uint32_t tx_buffer_tail = 0;
#elif SERIAL3_TX_BUFFER_SIZE > 255
static volatile uint16_t tx_buffer_head = 0;
static volatile uint16_t tx_buffer_tail = 0;
#else
static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0;
#endif
#if RX_BUFFER_SIZE > 255
#if SERIAL3_RX_BUFFER_SIZE > 65535
static volatile uint32_t rx_buffer_head = 0;
static volatile uint32_t rx_buffer_tail = 0;
#elif SERIAL3_RX_BUFFER_SIZE > 255
static volatile uint16_t rx_buffer_head = 0;
static volatile uint16_t rx_buffer_tail = 0;
#else
@@ -91,8 +101,8 @@ static volatile uint8_t rx_buffer_tail = 0;
#endif
#if defined(KINETISL)
static uint8_t rx_pin_num = 7;
static uint8_t tx_pin_num = 8;
#endif
static uint8_t tx_pin_num = 8;

// UART0 and UART1 are clocked by F_CPU, UART2 is clocked by F_BUS
// UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer
@@ -124,12 +134,14 @@ void serial3_begin(uint32_t divisor)
}
#endif
#if defined(HAS_KINETISK_UART2)
if (divisor < 32) divisor = 32;
UART2_BDH = (divisor >> 13) & 0x1F;
UART2_BDL = (divisor >> 5) & 0xFF;
UART2_C4 = divisor & 0x1F;
UART2_C1 = 0;
UART2_PFIFO = 0;
#elif defined(HAS_KINETISL_UART2)
if (divisor < 1) divisor = 1;
UART2_BDH = (divisor >> 8) & 0x1F;
UART2_BDL = divisor & 0xFF;
UART2_C1 = 0;
@@ -154,12 +166,21 @@ void serial3_format(uint32_t format)
c = UART2_C3 & ~0x10;
if (format & 0x20) c |= 0x10; // tx invert
UART2_C3 = c;
#ifdef SERIAL_9BIT_SUPPORT
#if defined(SERIAL_9BIT_SUPPORT) && !defined(KINETISL)
c = UART2_C4 & 0x1F;
if (format & 0x08) c |= 0x20; // 9 bit mode with parity (requires 10 bits)
UART2_C4 = c;
use9Bits = format & 0x80;
#endif
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(KINETISL)
// For T3.5/T3.6/TLC See about turning on 2 stop bit mode
if ( format & 0x100) {
uint8_t bdl = UART2_BDL;
UART2_BDH |= UART_BDH_SBNS; // Turn on 2 stop bits - was turned off by set baud
UART2_BDL = bdl; // Says BDH not acted on until BDL is written
}
#endif

}

void serial3_end(void)
@@ -168,8 +189,21 @@ void serial3_end(void)
while (transmitting) yield(); // wait for buffered data to send
NVIC_DISABLE_IRQ(IRQ_UART2_STATUS);
UART2_C2 = 0;
#if defined(KINETISK)
CORE_PIN7_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
CORE_PIN8_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
#elif defined(KINETISL)
switch (rx_pin_num) {
case 7: CORE_PIN7_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break;
case 6: CORE_PIN6_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break;
}
switch (tx_pin_num & 127) {
case 8: CORE_PIN8_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
UART2_S1;
UART2_D; // clear leftover error status
rx_buffer_head = 0;
rx_buffer_tail = 0;
if (rts_pin) rts_deassert();
@@ -188,7 +222,6 @@ void serial3_set_transmit_pin(uint8_t pin)

void serial3_set_tx(uint8_t pin, uint8_t opendrain)
{
#if defined(KINETISL)
uint32_t cfg;

if (opendrain) pin |= 128;
@@ -196,7 +229,9 @@ void serial3_set_tx(uint8_t pin, uint8_t opendrain)
if ((SIM_SCGC4 & SIM_SCGC4_UART2)) {
switch (tx_pin_num & 127) {
case 8: CORE_PIN8_CONFIG = 0; break; // PTD3
#if defined(KINETISL)
case 20: CORE_PIN20_CONFIG = 0; break; // PTD5
#endif
}
if (opendrain) {
cfg = PORT_PCR_DSE | PORT_PCR_ODE;
@@ -205,11 +240,12 @@ void serial3_set_tx(uint8_t pin, uint8_t opendrain)
}
switch (pin & 127) {
case 8: CORE_PIN8_CONFIG = cfg | PORT_PCR_MUX(3); break;
#if defined(KINETISL)
case 20: CORE_PIN20_CONFIG = cfg | PORT_PCR_MUX(3); break;
#endif
}
}
tx_pin_num = pin;
#endif
}

void serial3_set_rx(uint8_t pin)
@@ -280,13 +316,13 @@ void serial3_putchar(uint32_t c)
if (!(SIM_SCGC4 & SIM_SCGC4_UART2)) return;
if (transmit_pin) transmit_assert();
head = tx_buffer_head;
if (++head >= TX_BUFFER_SIZE) head = 0;
if (++head >= SERIAL3_TX_BUFFER_SIZE) head = 0;
while (tx_buffer_tail == head) {
int priority = nvic_execution_priority();
if (priority <= IRQ_PRIORITY) {
if ((UART2_S1 & UART_S1_TDRE)) {
uint32_t tail = tx_buffer_tail;
if (++tail >= TX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL3_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART2_C3 = (UART2_C3 & ~0x40) | ((n & 0x100) >> 2);
UART2_D = n;
@@ -319,7 +355,7 @@ int serial3_write_buffer_free(void)

head = tx_buffer_head;
tail = tx_buffer_tail;
if (head >= tail) return TX_BUFFER_SIZE - 1 - head + tail;
if (head >= tail) return SERIAL3_TX_BUFFER_SIZE - 1 - head + tail;
return tail - head - 1;
}

@@ -330,7 +366,7 @@ int serial3_available(void)
head = rx_buffer_head;
tail = rx_buffer_tail;
if (head >= tail) return head - tail;
return RX_BUFFER_SIZE + head - tail;
return SERIAL3_RX_BUFFER_SIZE + head - tail;
}

int serial3_getchar(void)
@@ -341,13 +377,13 @@ int serial3_getchar(void)
head = rx_buffer_head;
tail = rx_buffer_tail;
if (head == tail) return -1;
if (++tail >= RX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL3_RX_BUFFER_SIZE) tail = 0;
c = rx_buffer[tail];
rx_buffer_tail = tail;
if (rts_pin) {
int avail;
if (head >= tail) avail = head - tail;
else avail = RX_BUFFER_SIZE + head - tail;
else avail = SERIAL3_RX_BUFFER_SIZE + head - tail;
if (avail <= RTS_LOW_WATERMARK) rts_assert();
}
return c;
@@ -360,7 +396,7 @@ int serial3_peek(void)
head = rx_buffer_head;
tail = rx_buffer_tail;
if (head == tail) return -1;
if (++tail >= RX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL3_RX_BUFFER_SIZE) tail = 0;
return rx_buffer[tail];
}

@@ -370,7 +406,7 @@ void serial3_clear(void)
if (rts_pin) rts_assert();
}

// status interrupt combines
// status interrupt combines
// Transmit data below watermark UART_S1_TDRE
// Transmit complete UART_S1_TC
// Idle line UART_S1_IDLE
@@ -390,16 +426,16 @@ void uart2_status_isr(void)
n = UART2_D;
}
head = rx_buffer_head + 1;
if (head >= RX_BUFFER_SIZE) head = 0;
if (head >= SERIAL3_RX_BUFFER_SIZE) head = 0;
if (head != rx_buffer_tail) {
rx_buffer[head] = n;
rx_buffer_head = head;
rx_buffer_head = head;
}
if (rts_pin) {
int avail;
tail = tx_buffer_tail;
if (head >= tail) avail = head - tail;
else avail = RX_BUFFER_SIZE + head - tail;
else avail = SERIAL3_RX_BUFFER_SIZE + head - tail;
if (avail >= RTS_HIGH_WATERMARK) rts_deassert();
}
}
@@ -410,7 +446,7 @@ void uart2_status_isr(void)
if (head == tail) {
UART2_C2 = C2_TX_COMPLETING;
} else {
if (++tail >= TX_BUFFER_SIZE) tail = 0;
if (++tail >= SERIAL3_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART2_C3 = (UART2_C3 & ~0x40) | ((n & 0x100) >> 2);
UART2_D = n;

+ 403
- 0
teensy3/serial4.c View File

@@ -0,0 +1,403 @@
/* 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 "kinetis.h"
#include "core_pins.h"
#include "HardwareSerial.h"

#ifdef HAS_KINETISK_UART3

////////////////////////////////////////////////////////////////
// Tunable parameters (relatively safe to edit these numbers)
////////////////////////////////////////////////////////////////

#ifndef SERIAL4_TX_BUFFER_SIZE
#define SERIAL4_TX_BUFFER_SIZE 40 // number of outgoing bytes to buffer
#endif
#ifndef SERIAL4_RX_BUFFER_SIZE
#define SERIAL4_RX_BUFFER_SIZE 64 // number of incoming bytes to buffer
#endif
#define RTS_HIGH_WATERMARK (SERIAL4_RX_BUFFER_SIZE-24) // RTS requests sender to pause
#define RTS_LOW_WATERMARK (SERIAL4_RX_BUFFER_SIZE-38) // RTS allows sender to resume
#define IRQ_PRIORITY 64 // 0 = highest priority, 255 = lowest


////////////////////////////////////////////////////////////////
// changes not recommended below this point....
////////////////////////////////////////////////////////////////

#ifdef SERIAL_9BIT_SUPPORT
static uint8_t use9Bits = 0;
#define BUFTYPE uint16_t
#else
#define BUFTYPE uint8_t
#define use9Bits 0
#endif

static volatile BUFTYPE tx_buffer[SERIAL4_TX_BUFFER_SIZE];
static volatile BUFTYPE rx_buffer[SERIAL4_RX_BUFFER_SIZE];
static volatile uint8_t transmitting = 0;
static volatile uint8_t *transmit_pin=NULL;
#define transmit_assert() *transmit_pin = 1
#define transmit_deassert() *transmit_pin = 0
static volatile uint8_t *rts_pin=NULL;
#define rts_assert() *rts_pin = 0
#define rts_deassert() *rts_pin = 1
#if SERIAL4_TX_BUFFER_SIZE > 65535
static volatile uint32_t tx_buffer_head = 0;
static volatile uint32_t tx_buffer_tail = 0;
#elif SERIAL4_TX_BUFFER_SIZE > 255
static volatile uint16_t tx_buffer_head = 0;
static volatile uint16_t tx_buffer_tail = 0;
#else
static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0;
#endif
#if SERIAL4_RX_BUFFER_SIZE > 65535
static volatile uint32_t rx_buffer_head = 0;
static volatile uint32_t rx_buffer_tail = 0;
#elif SERIAL4_RX_BUFFER_SIZE > 255
static volatile uint16_t rx_buffer_head = 0;
static volatile uint16_t rx_buffer_tail = 0;
#else
static volatile uint8_t rx_buffer_head = 0;
static volatile uint8_t rx_buffer_tail = 0;
#endif

static uint8_t rx_pin_num = 31;
static uint8_t tx_pin_num = 32;

// UART0 and UART1 are clocked by F_CPU, UART2 is clocked by F_BUS
// UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer

#define C2_ENABLE UART_C2_TE | UART_C2_RE | UART_C2_RIE
#define C2_TX_ACTIVE C2_ENABLE | UART_C2_TIE
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE
#define C2_TX_INACTIVE C2_ENABLE

void serial4_begin(uint32_t divisor)
{
SIM_SCGC4 |= SIM_SCGC4_UART3; // turn on clock, TODO: use bitband
rx_buffer_head = 0;
rx_buffer_tail = 0;
tx_buffer_head = 0;
tx_buffer_tail = 0;
transmitting = 0;
switch (rx_pin_num) {
case 31: CORE_PIN31_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break;
case 63: CORE_PIN63_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break;
}
switch (tx_pin_num) {
case 32: CORE_PIN32_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); break;
case 62: CORE_PIN62_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); break;
}
if (divisor < 32) divisor = 32;
UART3_BDH = (divisor >> 13) & 0x1F;
UART3_BDL = (divisor >> 5) & 0xFF;
UART3_C4 = divisor & 0x1F;
UART3_C1 = 0;
UART3_PFIFO = 0;
UART3_C2 = C2_TX_INACTIVE;
NVIC_SET_PRIORITY(IRQ_UART3_STATUS, IRQ_PRIORITY);
NVIC_ENABLE_IRQ(IRQ_UART3_STATUS);
}

void serial4_format(uint32_t format)
{
uint8_t c;

c = UART3_C1;
c = (c & ~0x13) | (format & 0x03); // configure parity
if (format & 0x04) c |= 0x10; // 9 bits (might include parity)
UART3_C1 = c;
if ((format & 0x0F) == 0x04) UART3_C3 |= 0x40; // 8N2 is 9 bit with 9th bit always 1
c = UART3_S2 & ~0x10;
if (format & 0x10) c |= 0x10; // rx invert
UART3_S2 = c;
c = UART3_C3 & ~0x10;
if (format & 0x20) c |= 0x10; // tx invert
UART3_C3 = c;
#ifdef SERIAL_9BIT_SUPPORT
c = UART3_C4 & 0x1F;
if (format & 0x08) c |= 0x20; // 9 bit mode with parity (requires 10 bits)
UART3_C4 = c;
use9Bits = format & 0x80;
#endif
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(KINETISL)
// For T3.5/T3.6/TLC See about turning on 2 stop bit mode
if ( format & 0x100) {
uint8_t bdl = UART3_BDL;
UART3_BDH |= UART_BDH_SBNS; // Turn on 2 stop bits - was turned off by set baud
UART3_BDL = bdl; // Says BDH not acted on until BDL is written
}
#endif
}

void serial4_end(void)
{
if (!(SIM_SCGC4 & SIM_SCGC4_UART3)) return;
while (transmitting) yield(); // wait for buffered data to send
NVIC_DISABLE_IRQ(IRQ_UART3_STATUS);
UART3_C2 = 0;
switch (rx_pin_num) {
case 31: CORE_PIN31_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; // PTC3
case 63: CORE_PIN63_CONFIG = 0; break;
}
switch (tx_pin_num & 127) {
case 32: CORE_PIN32_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1); break; // PTC4
case 62: CORE_PIN62_CONFIG = 0; break;
}
UART3_S1;
UART3_D; // clear leftover error status
rx_buffer_head = 0;
rx_buffer_tail = 0;
if (rts_pin) rts_deassert();
}

void serial4_set_transmit_pin(uint8_t pin)
{
while (transmitting) ;
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
transmit_pin = portOutputRegister(pin);
}

void serial4_set_tx(uint8_t pin, uint8_t opendrain)
{
uint32_t cfg;

if (opendrain) pin |= 128;
if (pin == tx_pin_num) return;
if ((SIM_SCGC4 & SIM_SCGC4_UART3)) {
switch (tx_pin_num & 127) {
case 32: CORE_PIN32_CONFIG = 0; break; // PTB11
case 62: CORE_PIN62_CONFIG = 0; break;
}
if (opendrain) {
cfg = PORT_PCR_DSE | PORT_PCR_ODE;
} else {
cfg = PORT_PCR_DSE | PORT_PCR_SRE;
}
switch (pin & 127) {
case 32: CORE_PIN32_CONFIG = cfg | PORT_PCR_MUX(3); break;
case 62: CORE_PIN62_CONFIG = cfg | PORT_PCR_MUX(3); break;
}
}
tx_pin_num = pin;

}

void serial4_set_rx(uint8_t pin)
{
if (pin == rx_pin_num) return;
if ((SIM_SCGC4 & SIM_SCGC4_UART3)) {
switch (rx_pin_num) {
case 31: CORE_PIN31_CONFIG = 0; break; // PTC3
case 63: CORE_PIN63_CONFIG = 0; break;
}
switch (pin) {
case 31: CORE_PIN31_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break;
case 63: CORE_PIN63_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break;
}
}
rx_pin_num = pin;
}

int serial4_set_rts(uint8_t pin)
{
if (!(SIM_SCGC4 & SIM_SCGC4_UART3)) return 0;
if (pin < CORE_NUM_DIGITAL) {
rts_pin = portOutputRegister(pin);
pinMode(pin, OUTPUT);
rts_assert();
} else {
rts_pin = NULL;
return 0;
}
return 1;
}

int serial4_set_cts(uint8_t pin)
{
return 0;
}

void serial4_putchar(uint32_t c)
{
uint32_t head, n;

if (!(SIM_SCGC4 & SIM_SCGC4_UART3)) return;
if (transmit_pin) transmit_assert();
head = tx_buffer_head;
if (++head >= SERIAL4_TX_BUFFER_SIZE) head = 0;
while (tx_buffer_tail == head) {
int priority = nvic_execution_priority();
if (priority <= IRQ_PRIORITY) {
if ((UART3_S1 & UART_S1_TDRE)) {
uint32_t tail = tx_buffer_tail;
if (++tail >= SERIAL4_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART3_C3 = (UART3_C3 & ~0x40) | ((n & 0x100) >> 2);
UART3_D = n;
tx_buffer_tail = tail;
}
} else if (priority >= 256) {
yield(); // wait
}
}
tx_buffer[head] = c;
transmitting = 1;
tx_buffer_head = head;
UART3_C2 = C2_TX_ACTIVE;
}

void serial4_write(const void *buf, unsigned int count)
{
const uint8_t *p = (const uint8_t *)buf;
while (count-- > 0) serial4_putchar(*p++);
}

void serial4_flush(void)
{
while (transmitting) yield(); // wait
}

int serial4_write_buffer_free(void)
{
uint32_t head, tail;

head = tx_buffer_head;
tail = tx_buffer_tail;
if (head >= tail) return SERIAL4_TX_BUFFER_SIZE - 1 - head + tail;
return tail - head - 1;
}

int serial4_available(void)
{
uint32_t head, tail;

head = rx_buffer_head;
tail = rx_buffer_tail;
if (head >= tail) return head - tail;
return SERIAL4_RX_BUFFER_SIZE + head - tail;
}

int serial4_getchar(void)
{
uint32_t head, tail;
int c;

head = rx_buffer_head;
tail = rx_buffer_tail;
if (head == tail) return -1;
if (++tail >= SERIAL4_RX_BUFFER_SIZE) tail = 0;
c = rx_buffer[tail];
rx_buffer_tail = tail;
if (rts_pin) {
int avail;
if (head >= tail) avail = head - tail;
else avail = SERIAL4_RX_BUFFER_SIZE + head - tail;
if (avail <= RTS_LOW_WATERMARK) rts_assert();
}
return c;
}

int serial4_peek(void)
{
uint32_t head, tail;

head = rx_buffer_head;
tail = rx_buffer_tail;
if (head == tail) return -1;
if (++tail >= SERIAL4_RX_BUFFER_SIZE) tail = 0;
return rx_buffer[tail];
}

void serial4_clear(void)
{
rx_buffer_head = rx_buffer_tail;
if (rts_pin) rts_assert();
}

// status interrupt combines
// Transmit data below watermark UART_S1_TDRE
// Transmit complete UART_S1_TC
// Idle line UART_S1_IDLE
// Receive data above watermark UART_S1_RDRF
// LIN break detect UART_S2_LBKDIF
// RxD pin active edge UART_S2_RXEDGIF

void uart3_status_isr(void)
{
uint32_t head, tail, n;
uint8_t c;

if (UART3_S1 & UART_S1_RDRF) {
if (use9Bits && (UART3_C3 & 0x80)) {
n = UART3_D | 0x100;
} else {
n = UART3_D;
}
head = rx_buffer_head + 1;
if (head >= SERIAL4_RX_BUFFER_SIZE) head = 0;
if (head != rx_buffer_tail) {
rx_buffer[head] = n;
rx_buffer_head = head;
}
if (rts_pin) {
int avail;
tail = tx_buffer_tail;
if (head >= tail) avail = head - tail;
else avail = SERIAL4_RX_BUFFER_SIZE + head - tail;
if (avail >= RTS_HIGH_WATERMARK) rts_deassert();
}
}
c = UART3_C2;
if ((c & UART_C2_TIE) && (UART3_S1 & UART_S1_TDRE)) {
head = tx_buffer_head;
tail = tx_buffer_tail;
if (head == tail) {
UART3_C2 = C2_TX_COMPLETING;
} else {
if (++tail >= SERIAL4_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART3_C3 = (UART3_C3 & ~0x40) | ((n & 0x100) >> 2);
UART3_D = n;
tx_buffer_tail = tail;
}
}
if ((c & UART_C2_TCIE) && (UART3_S1 & UART_S1_TC)) {
transmitting = 0;
if (transmit_pin) transmit_deassert();
UART3_C2 = C2_TX_INACTIVE;
}
}

#endif // HAS_KINETISK_UART3

+ 381
- 0
teensy3/serial5.c View File

@@ -0,0 +1,381 @@
/* 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 "kinetis.h"
#include "core_pins.h"
#include "HardwareSerial.h"

#ifdef HAS_KINETISK_UART4

////////////////////////////////////////////////////////////////
// Tunable parameters (relatively safe to edit these numbers)
////////////////////////////////////////////////////////////////

#ifndef SERIAL5_TX_BUFFER_SIZE
#define SERIAL5_TX_BUFFER_SIZE 40 // number of outgoing bytes to buffer
#endif
#ifndef SERIAL5_RX_BUFFER_SIZE
#define SERIAL5_RX_BUFFER_SIZE 64 // number of incoming bytes to buffer
#endif
#define RTS_HIGH_WATERMARK (SERIAL5_RX_BUFFER_SIZE-24) // RTS requests sender to pause
#define RTS_LOW_WATERMARK (SERIAL5_RX_BUFFER_SIZE-38) // RTS allows sender to resume
#define IRQ_PRIORITY 64 // 0 = highest priority, 255 = lowest


////////////////////////////////////////////////////////////////
// changes not recommended below this point....
////////////////////////////////////////////////////////////////

#ifdef SERIAL_9BIT_SUPPORT
static uint8_t use9Bits = 0;
#define BUFTYPE uint16_t
#else
#define BUFTYPE uint8_t
#define use9Bits 0
#endif

static volatile BUFTYPE tx_buffer[SERIAL5_TX_BUFFER_SIZE];
static volatile BUFTYPE rx_buffer[SERIAL5_RX_BUFFER_SIZE];
static volatile uint8_t transmitting = 0;
static volatile uint8_t *transmit_pin=NULL;
#define transmit_assert() *transmit_pin = 1
#define transmit_deassert() *transmit_pin = 0
static volatile uint8_t *rts_pin=NULL;
#define rts_assert() *rts_pin = 0
#define rts_deassert() *rts_pin = 1
#if SERIAL5_TX_BUFFER_SIZE > 65535
static volatile uint32_t tx_buffer_head = 0;
static volatile uint32_t tx_buffer_tail = 0;
#elif SERIAL5_TX_BUFFER_SIZE > 255
static volatile uint16_t tx_buffer_head = 0;
static volatile uint16_t tx_buffer_tail = 0;
#else
static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0;
#endif
#if SERIAL5_RX_BUFFER_SIZE > 65535
static volatile uint32_t rx_buffer_head = 0;
static volatile uint32_t rx_buffer_tail = 0;
#elif SERIAL5_RX_BUFFER_SIZE > 255
static volatile uint16_t rx_buffer_head = 0;
static volatile uint16_t rx_buffer_tail = 0;
#else
static volatile uint8_t rx_buffer_head = 0;
static volatile uint8_t rx_buffer_tail = 0;
#endif

static uint8_t tx_pin_num = 33;

// UART0 and UART1 are clocked by F_CPU, UART2 is clocked by F_BUS
// UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer

#define C2_ENABLE UART_C2_TE | UART_C2_RE | UART_C2_RIE
#define C2_TX_ACTIVE C2_ENABLE | UART_C2_TIE
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE
#define C2_TX_INACTIVE C2_ENABLE

void serial5_begin(uint32_t divisor)
{
SIM_SCGC1 |= SIM_SCGC1_UART4; // turn on clock, TODO: use bitband
rx_buffer_head = 0;
rx_buffer_tail = 0;
tx_buffer_head = 0;
tx_buffer_tail = 0;
transmitting = 0;
CORE_PIN34_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3);
CORE_PIN33_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3);
if (divisor < 32) divisor = 32;
UART4_BDH = (divisor >> 13) & 0x1F;
UART4_BDL = (divisor >> 5) & 0xFF;
UART4_C4 = divisor & 0x1F;
UART4_C1 = 0;
UART4_PFIFO = 0;
UART4_C2 = C2_TX_INACTIVE;
NVIC_SET_PRIORITY(IRQ_UART4_STATUS, IRQ_PRIORITY);
NVIC_ENABLE_IRQ(IRQ_UART4_STATUS);
}

void serial5_format(uint32_t format)
{
uint8_t c;

c = UART4_C1;
c = (c & ~0x13) | (format & 0x03); // configure parity
if (format & 0x04) c |= 0x10; // 9 bits (might include parity)
UART4_C1 = c;
if ((format & 0x0F) == 0x04) UART4_C3 |= 0x40; // 8N2 is 9 bit with 9th bit always 1
c = UART4_S2 & ~0x10;
if (format & 0x10) c |= 0x10; // rx invert
UART4_S2 = c;
c = UART4_C3 & ~0x10;
if (format & 0x20) c |= 0x10; // tx invert
UART4_C3 = c;
#ifdef SERIAL_9BIT_SUPPORT
c = UART4_C4 & 0x1F;
if (format & 0x08) c |= 0x20; // 9 bit mode with parity (requires 10 bits)
UART4_C4 = c;
use9Bits = format & 0x80;
#endif
// For T3.5/T3.6 See about turning on 2 stop bit mode
if ( format & 0x100) {
uint8_t bdl = UART4_BDL;
UART4_BDH |= UART_BDH_SBNS; // Turn on 2 stop bits - was turned off by set baud
UART4_BDL = bdl; // Says BDH not acted on until BDL is written
}
}

void serial5_end(void)
{
if (!(SIM_SCGC1 & SIM_SCGC1_UART4)) return;
while (transmitting) yield(); // wait for buffered data to send
NVIC_DISABLE_IRQ(IRQ_UART4_STATUS);
UART4_C2 = 0;
CORE_PIN34_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
CORE_PIN33_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
UART4_S1;
UART4_D; // clear leftover error status
rx_buffer_head = 0;
rx_buffer_tail = 0;
if (rts_pin) rts_deassert();
}

void serial5_set_transmit_pin(uint8_t pin)
{
while (transmitting) ;
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
transmit_pin = portOutputRegister(pin);
}

void serial5_set_tx(uint8_t pin, uint8_t opendrain)
{
uint32_t cfg;

if (opendrain) pin |= 128;
if (pin == tx_pin_num) return;
if ((SIM_SCGC1 & SIM_SCGC1_UART4)) {
switch (tx_pin_num & 127) {
case 33: CORE_PIN33_CONFIG = 0; break; // PTE24
}
if (opendrain) {
cfg = PORT_PCR_DSE | PORT_PCR_ODE;
} else {
cfg = PORT_PCR_DSE | PORT_PCR_SRE;
}
switch (pin & 127) {
case 33: CORE_PIN33_CONFIG = cfg | PORT_PCR_MUX(3); break;
}
}
tx_pin_num = pin;
}

void serial5_set_rx(uint8_t pin)
{
}

int serial5_set_rts(uint8_t pin)
{
if (!(SIM_SCGC1 & SIM_SCGC1_UART4)) return 0;
if (pin < CORE_NUM_DIGITAL) {
rts_pin = portOutputRegister(pin);
pinMode(pin, OUTPUT);
rts_assert();
} else {
rts_pin = NULL;
return 0;
}
return 1;
}

int serial5_set_cts(uint8_t pin)
{
if (!(SIM_SCGC1 & SIM_SCGC1_UART4)) return 0;
if (pin == 24) {
CORE_PIN24_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_PE; // weak pulldown
} else {
UART4_MODEM &= ~UART_MODEM_TXCTSE;
return 0;
}
UART4_MODEM |= UART_MODEM_TXCTSE;
return 1;
}

void serial5_putchar(uint32_t c)
{
uint32_t head, n;

if (!(SIM_SCGC1 & SIM_SCGC1_UART4)) return;
if (transmit_pin) transmit_assert();
head = tx_buffer_head;
if (++head >= SERIAL5_TX_BUFFER_SIZE) head = 0;
while (tx_buffer_tail == head) {
int priority = nvic_execution_priority();
if (priority <= IRQ_PRIORITY) {
if ((UART4_S1 & UART_S1_TDRE)) {
uint32_t tail = tx_buffer_tail;
if (++tail >= SERIAL5_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART4_C3 = (UART4_C3 & ~0x40) | ((n & 0x100) >> 2);
UART4_D = n;
tx_buffer_tail = tail;
}
} else if (priority >= 256) {
yield(); // wait
}
}
tx_buffer[head] = c;
transmitting = 1;
tx_buffer_head = head;
UART4_C2 = C2_TX_ACTIVE;
}

void serial5_write(const void *buf, unsigned int count)
{
const uint8_t *p = (const uint8_t *)buf;
while (count-- > 0) serial5_putchar(*p++);
}

void serial5_flush(void)
{
while (transmitting) yield(); // wait
}

int serial5_write_buffer_free(void)
{
uint32_t head, tail;

head = tx_buffer_head;
tail = tx_buffer_tail;
if (head >= tail) return SERIAL5_TX_BUFFER_SIZE - 1 - head + tail;
return tail - head - 1;
}

int serial5_available(void)
{
uint32_t head, tail;

head = rx_buffer_head;
tail = rx_buffer_tail;
if (head >= tail) return head - tail;
return SERIAL5_RX_BUFFER_SIZE + head - tail;
}

int serial5_getchar(void)
{
uint32_t head, tail;
int c;

head = rx_buffer_head;
tail = rx_buffer_tail;
if (head == tail) return -1;
if (++tail >= SERIAL5_RX_BUFFER_SIZE) tail = 0;
c = rx_buffer[tail];
rx_buffer_tail = tail;
if (rts_pin) {
int avail;
if (head >= tail) avail = head - tail;
else avail = SERIAL5_RX_BUFFER_SIZE + head - tail;
if (avail <= RTS_LOW_WATERMARK) rts_assert();
}
return c;
}

int serial5_peek(void)
{
uint32_t head, tail;

head = rx_buffer_head;
tail = rx_buffer_tail;
if (head == tail) return -1;
if (++tail >= SERIAL5_RX_BUFFER_SIZE) tail = 0;
return rx_buffer[tail];
}

void serial5_clear(void)
{
rx_buffer_head = rx_buffer_tail;
if (rts_pin) rts_assert();
}

// status interrupt combines
// Transmit data below watermark UART_S1_TDRE
// Transmit complete UART_S1_TC
// Idle line UART_S1_IDLE
// Receive data above watermark UART_S1_RDRF
// LIN break detect UART_S2_LBKDIF
// RxD pin active edge UART_S2_RXEDGIF

void uart4_status_isr(void)
{
uint32_t head, tail, n;
uint8_t c;

if (UART4_S1 & UART_S1_RDRF) {
if (use9Bits && (UART4_C3 & 0x80)) {
n = UART4_D | 0x100;
} else {
n = UART4_D;
}
head = rx_buffer_head + 1;
if (head >= SERIAL5_RX_BUFFER_SIZE) head = 0;
if (head != rx_buffer_tail) {
rx_buffer[head] = n;
rx_buffer_head = head;
}
if (rts_pin) {
int avail;
tail = tx_buffer_tail;
if (head >= tail) avail = head - tail;
else avail = SERIAL5_RX_BUFFER_SIZE + head - tail;
if (avail >= RTS_HIGH_WATERMARK) rts_deassert();
}
}
c = UART4_C2;
if ((c & UART_C2_TIE) && (UART4_S1 & UART_S1_TDRE)) {
head = tx_buffer_head;
tail = tx_buffer_tail;
if (head == tail) {
UART4_C2 = C2_TX_COMPLETING;
} else {
if (++tail >= SERIAL5_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART4_C3 = (UART4_C3 & ~0x40) | ((n & 0x100) >> 2);
UART4_D = n;
tx_buffer_tail = tail;
}
}
if ((c & UART_C2_TCIE) && (UART4_S1 & UART_S1_TC)) {
transmitting = 0;
if (transmit_pin) transmit_deassert();
UART4_C2 = C2_TX_INACTIVE;
}
}

#endif // HAS_KINETISK_UART4

+ 381
- 0
teensy3/serial6.c View File

@@ -0,0 +1,381 @@
/* 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 "kinetis.h"
#include "core_pins.h"
#include "HardwareSerial.h"

#ifdef HAS_KINETISK_UART5

////////////////////////////////////////////////////////////////
// Tunable parameters (relatively safe to edit these numbers)
////////////////////////////////////////////////////////////////

#ifndef SERIAL6_TX_BUFFER_SIZE
#define SERIAL6_TX_BUFFER_SIZE 40 // number of outgoing bytes to buffer
#endif
#ifndef SERIAL6_RX_BUFFER_SIZE
#define SERIAL6_RX_BUFFER_SIZE 64 // number of incoming bytes to buffer
#endif
#define RTS_HIGH_WATERMARK (SERIAL6_RX_BUFFER_SIZE-24) // RTS requests sender to pause
#define RTS_LOW_WATERMARK (SERIAL6_RX_BUFFER_SIZE-38) // RTS allows sender to resume
#define IRQ_PRIORITY 64 // 0 = highest priority, 255 = lowest


////////////////////////////////////////////////////////////////
// changes not recommended below this point....
////////////////////////////////////////////////////////////////

#ifdef SERIAL_9BIT_SUPPORT
static uint8_t use9Bits = 0;
#define BUFTYPE uint16_t
#else
#define BUFTYPE uint8_t
#define use9Bits 0
#endif

static volatile BUFTYPE tx_buffer[SERIAL6_TX_BUFFER_SIZE];
static volatile BUFTYPE rx_buffer[SERIAL6_RX_BUFFER_SIZE];
static volatile uint8_t transmitting = 0;
static volatile uint8_t *transmit_pin=NULL;
#define transmit_assert() *transmit_pin = 1
#define transmit_deassert() *transmit_pin = 0
static volatile uint8_t *rts_pin=NULL;
#define rts_assert() *rts_pin = 0
#define rts_deassert() *rts_pin = 1
#if SERIAL6_TX_BUFFER_SIZE > 65535
static volatile uint32_t tx_buffer_head = 0;
static volatile uint32_t tx_buffer_tail = 0;
#elif SERIAL6_TX_BUFFER_SIZE > 255
static volatile uint16_t tx_buffer_head = 0;
static volatile uint16_t tx_buffer_tail = 0;
#else
static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0;
#endif
#if SERIAL6_RX_BUFFER_SIZE > 65535
static volatile uint32_t rx_buffer_head = 0;
static volatile uint32_t rx_buffer_tail = 0;
#elif SERIAL6_RX_BUFFER_SIZE > 255
static volatile uint16_t rx_buffer_head = 0;
static volatile uint16_t rx_buffer_tail = 0;
#else
static volatile uint8_t rx_buffer_head = 0;
static volatile uint8_t rx_buffer_tail = 0;
#endif

static uint8_t tx_pin_num = 48;

// UART0 and UART1 are clocked by F_CPU, UART2 is clocked by F_BUS
// UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer

#define C2_ENABLE UART_C2_TE | UART_C2_RE | UART_C2_RIE
#define C2_TX_ACTIVE C2_ENABLE | UART_C2_TIE
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE
#define C2_TX_INACTIVE C2_ENABLE

void serial6_begin(uint32_t divisor)
{
SIM_SCGC1 |= SIM_SCGC1_UART5; // turn on clock, TODO: use bitband
rx_buffer_head = 0;
rx_buffer_tail = 0;
tx_buffer_head = 0;
tx_buffer_tail = 0;
transmitting = 0;
CORE_PIN47_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3);
CORE_PIN48_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3);
if (divisor < 32) divisor = 32;
UART5_BDH = (divisor >> 13) & 0x1F;
UART5_BDL = (divisor >> 5) & 0xFF;
UART5_C4 = divisor & 0x1F;
UART5_C1 = 0;
UART5_PFIFO = 0;
UART5_C2 = C2_TX_INACTIVE;
NVIC_SET_PRIORITY(IRQ_UART5_STATUS, IRQ_PRIORITY);
NVIC_ENABLE_IRQ(IRQ_UART5_STATUS);
}

void serial6_format(uint32_t format)
{
uint8_t c;

c = UART5_C1;
c = (c & ~0x13) | (format & 0x03); // configure parity
if (format & 0x04) c |= 0x10; // 9 bits (might include parity)
UART5_C1 = c;
if ((format & 0x0F) == 0x04) UART5_C3 |= 0x40; // 8N2 is 9 bit with 9th bit always 1
c = UART5_S2 & ~0x10;
if (format & 0x10) c |= 0x10; // rx invert
UART5_S2 = c;
c = UART5_C3 & ~0x10;
if (format & 0x20) c |= 0x10; // tx invert
UART5_C3 = c;
#ifdef SERIAL_9BIT_SUPPORT
c = UART5_C4 & 0x1F;
if (format & 0x08) c |= 0x20; // 9 bit mode with parity (requires 10 bits)
UART5_C4 = c;
use9Bits = format & 0x80;
#endif
// For T3.5 See about turning on 2 stop bit mode
if ( format & 0x100) {
uint8_t bdl = UART5_BDL;
UART5_BDH |= UART_BDH_SBNS; // Turn on 2 stop bits - was turned off by set baud
UART5_BDL = bdl; // Says BDH not acted on until BDL is written
}
}

void serial6_end(void)
{
if (!(SIM_SCGC1 & SIM_SCGC1_UART5)) return;
while (transmitting) yield(); // wait for buffered data to send
NVIC_DISABLE_IRQ(IRQ_UART5_STATUS);
UART5_C2 = 0;
CORE_PIN47_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
CORE_PIN48_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
UART5_S1;
UART5_D; // clear leftover error status
rx_buffer_head = 0;
rx_buffer_tail = 0;
if (rts_pin) rts_deassert();
}

void serial6_set_transmit_pin(uint8_t pin)
{
while (transmitting) ;
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
transmit_pin = portOutputRegister(pin);
}

void serial6_set_tx(uint8_t pin, uint8_t opendrain)
{
uint32_t cfg;

if (opendrain) pin |= 128;
if (pin == tx_pin_num) return;
if ((SIM_SCGC1 & SIM_SCGC1_UART5)) {
switch (tx_pin_num & 127) {
case 48: CORE_PIN48_CONFIG = 0; break; // PTE24
}
if (opendrain) {
cfg = PORT_PCR_DSE | PORT_PCR_ODE;
} else {
cfg = PORT_PCR_DSE | PORT_PCR_SRE;
}
switch (pin & 127) {
case 48: CORE_PIN48_CONFIG = cfg | PORT_PCR_MUX(3); break;
}
}
tx_pin_num = pin;
}

void serial6_set_rx(uint8_t pin)
{
}

int serial6_set_rts(uint8_t pin)
{
if (!(SIM_SCGC1 & SIM_SCGC1_UART5)) return 0;
if (pin < CORE_NUM_DIGITAL) {
rts_pin = portOutputRegister(pin);
pinMode(pin, OUTPUT);
rts_assert();
} else {
rts_pin = NULL;
return 0;
}
return 1;
}

int serial6_set_cts(uint8_t pin)
{
if (!(SIM_SCGC1 & SIM_SCGC1_UART5)) return 0;
if (pin == 56) {
CORE_PIN56_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_PE; // weak pulldown
} else {
UART5_MODEM &= ~UART_MODEM_TXCTSE;
return 0;
}
UART5_MODEM |= UART_MODEM_TXCTSE;
return 1;
}

void serial6_putchar(uint32_t c)
{
uint32_t head, n;

if (!(SIM_SCGC1 & SIM_SCGC1_UART5)) return;
if (transmit_pin) transmit_assert();
head = tx_buffer_head;
if (++head >= SERIAL6_TX_BUFFER_SIZE) head = 0;
while (tx_buffer_tail == head) {
int priority = nvic_execution_priority();
if (priority <= IRQ_PRIORITY) {
if ((UART5_S1 & UART_S1_TDRE)) {
uint32_t tail = tx_buffer_tail;
if (++tail >= SERIAL6_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART5_C3 = (UART5_C3 & ~0x40) | ((n & 0x100) >> 2);
UART5_D = n;
tx_buffer_tail = tail;
}
} else if (priority >= 256) {
yield(); // wait
}
}
tx_buffer[head] = c;
transmitting = 1;
tx_buffer_head = head;
UART5_C2 = C2_TX_ACTIVE;
}

void serial6_write(const void *buf, unsigned int count)
{
const uint8_t *p = (const uint8_t *)buf;
while (count-- > 0) serial6_putchar(*p++);
}

void serial6_flush(void)
{
while (transmitting) yield(); // wait
}

int serial6_write_buffer_free(void)
{
uint32_t head, tail;

head = tx_buffer_head;
tail = tx_buffer_tail;
if (head >= tail) return SERIAL6_TX_BUFFER_SIZE - 1 - head + tail;
return tail - head - 1;
}

int serial6_available(void)
{
uint32_t head, tail;

head = rx_buffer_head;
tail = rx_buffer_tail;
if (head >= tail) return head - tail;
return SERIAL6_RX_BUFFER_SIZE + head - tail;
}

int serial6_getchar(void)
{
uint32_t head, tail;
int c;

head = rx_buffer_head;
tail = rx_buffer_tail;
if (head == tail) return -1;
if (++tail >= SERIAL6_RX_BUFFER_SIZE) tail = 0;
c = rx_buffer[tail];
rx_buffer_tail = tail;
if (rts_pin) {
int avail;
if (head >= tail) avail = head - tail;
else avail = SERIAL6_RX_BUFFER_SIZE + head - tail;
if (avail <= RTS_LOW_WATERMARK) rts_assert();
}
return c;
}

int serial6_peek(void)
{
uint32_t head, tail;

head = rx_buffer_head;
tail = rx_buffer_tail;
if (head == tail) return -1;
if (++tail >= SERIAL6_RX_BUFFER_SIZE) tail = 0;
return rx_buffer[tail];
}

void serial6_clear(void)
{
rx_buffer_head = rx_buffer_tail;
if (rts_pin) rts_assert();
}

// status interrupt combines
// Transmit data below watermark UART_S1_TDRE
// Transmit complete UART_S1_TC
// Idle line UART_S1_IDLE
// Receive data above watermark UART_S1_RDRF
// LIN break detect UART_S2_LBKDIF
// RxD pin active edge UART_S2_RXEDGIF

void uart5_status_isr(void)
{
uint32_t head, tail, n;
uint8_t c;

if (UART5_S1 & UART_S1_RDRF) {
if (use9Bits && (UART5_C3 & 0x80)) {
n = UART5_D | 0x100;
} else {
n = UART5_D;
}
head = rx_buffer_head + 1;
if (head >= SERIAL6_RX_BUFFER_SIZE) head = 0;
if (head != rx_buffer_tail) {
rx_buffer[head] = n;
rx_buffer_head = head;
}
if (rts_pin) {
int avail;
tail = tx_buffer_tail;
if (head >= tail) avail = head - tail;
else avail = SERIAL6_RX_BUFFER_SIZE + head - tail;
if (avail >= RTS_HIGH_WATERMARK) rts_deassert();
}
}
c = UART5_C2;
if ((c & UART_C2_TIE) && (UART5_S1 & UART_S1_TDRE)) {
head = tx_buffer_head;
tail = tx_buffer_tail;
if (head == tail) {
UART5_C2 = C2_TX_COMPLETING;
} else {
if (++tail >= SERIAL6_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
if (use9Bits) UART5_C3 = (UART5_C3 & ~0x40) | ((n & 0x100) >> 2);
UART5_D = n;
tx_buffer_tail = tail;
}
}
if ((c & UART_C2_TCIE) && (UART5_S1 & UART_S1_TC)) {
transmitting = 0;
if (transmit_pin) transmit_deassert();
UART5_C2 = C2_TX_INACTIVE;
}
}

#endif // HAS_KINETISK_UART5

+ 463
- 0
teensy3/serial6_lpuart.c View File

@@ -0,0 +1,463 @@
/* 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 "kinetis.h"
#include "core_pins.h"
#include "HardwareSerial.h"

#ifdef HAS_KINETISK_LPUART0

#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000)
#define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit)))
#define BITBAND_SET_BIT(reg, bit) (*GPIO_BITBAND_PTR((reg), (bit)) = 1)
#define BITBAND_CLR_BIT(reg, bit) (*GPIO_BITBAND_PTR((reg), (bit)) = 0)
#define TCIE_BIT 22
#define TIE_BIT 23


////////////////////////////////////////////////////////////////
// Tunable parameters (relatively safe to edit these numbers)
////////////////////////////////////////////////////////////////

#ifndef SERIAL6_TX_BUFFER_SIZE
#define SERIAL6_TX_BUFFER_SIZE 40 // number of outgoing bytes to buffer
#endif
#ifndef SERIAL6_RX_BUFFER_SIZE
#define SERIAL6_RX_BUFFER_SIZE 64 // number of incoming bytes to buffer
#endif
#define RTS_HIGH_WATERMARK (SERIAL6_RX_BUFFER_SIZE-24) // RTS requests sender to pause
#define RTS_LOW_WATERMARK (SERIAL6_RX_BUFFER_SIZE-38) // RTS allows sender to resume
#define IRQ_PRIORITY 64 // 0 = highest priority, 255 = lowest


////////////////////////////////////////////////////////////////
// changes not recommended below this point....
////////////////////////////////////////////////////////////////

#ifdef SERIAL_9BIT_SUPPORT
static uint8_t use9Bits = 0;
#define BUFTYPE uint16_t
#else
#define BUFTYPE uint8_t
#define use9Bits 0
#endif

static volatile BUFTYPE tx_buffer[SERIAL6_TX_BUFFER_SIZE];
static volatile BUFTYPE rx_buffer[SERIAL6_RX_BUFFER_SIZE];
static volatile uint8_t transmitting = 0;
static volatile uint8_t *transmit_pin=NULL;
#define transmit_assert() *transmit_pin = 1
#define transmit_deassert() *transmit_pin = 0
static volatile uint8_t *rts_pin=NULL;
#define rts_assert() *rts_pin = 0
#define rts_deassert() *rts_pin = 1
#if SERIAL6_TX_BUFFER_SIZE > 255
static volatile uint16_t tx_buffer_head = 0;
static volatile uint16_t tx_buffer_tail = 0;
#else
static volatile uint8_t tx_buffer_head = 0;
static volatile uint8_t tx_buffer_tail = 0;
#endif
#if SERIAL6_RX_BUFFER_SIZE > 255
static volatile uint16_t rx_buffer_head = 0;
static volatile uint16_t rx_buffer_tail = 0;
#else
static volatile uint8_t rx_buffer_head = 0;
static volatile uint8_t rx_buffer_tail = 0;
#endif

static uint8_t tx_pin_num = 48;

// UART0 and UART1 are clocked by F_CPU, UART2 is clocked by F_BUS
// UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer


void serial6_begin(uint32_t desiredBaudRate)
{
#define F_LPUART_CLOCK_SPEED 48000000 //F_BUS
// Make sure the clock for this uart is enabled, else the registers are not
// vailable.
SIM_SCGC2 |= SIM_SCGC2_LPUART0; // Turn on the clock

// Convert the baud rate to best divisor and OSR, based off of code I found in posting
// try to find an OSR > 4 with the minimum difference from the actual disired baud rate.
uint16_t sbr, sbrTemp, osrCheck;
uint32_t osr, baudDiffCheck, calculatedBaud, baudDiff;
uint32_t clockSpeed;

// First lets figure out what the LPUART Clock speed is.
uint32_t PLLFLLSEL = SIM_SOPT2 & SIM_SOPT2_IRC48SEL; // Note: Bot bits on here

if (PLLFLLSEL == SIM_SOPT2_IRC48SEL)
clockSpeed = 48000000; // Fixed to 48mhz
else if (PLLFLLSEL == SIM_SOPT2_PLLFLLSEL)
clockSpeed = F_PLL; // Using PLL clock
else
clockSpeed = F_CPU/4; // FLL clock, guessing
osr = 4;
sbr = (clockSpeed/(desiredBaudRate * osr));
/*set sbr to 1 if the clockSpeed can not satisfy the desired baud rate*/
if(sbr == 0) {
// Maybe print something.
return; // can not initialize
}

// With integer math the divide*muliply implies the calculated baud will be >= desired baud
calculatedBaud = (clockSpeed / (osr * sbr));
baudDiff = calculatedBaud - desiredBaudRate;

// Check if better off with sbr+1
if (baudDiff != 0) {
calculatedBaud = (clockSpeed / (osr * (sbr + 1)));
baudDiffCheck = desiredBaudRate - calculatedBaud ;
if (baudDiffCheck < baudDiff) {
sbr++; // use the higher sbr
baudDiff = baudDiffCheck;
}
}

// loop to find the best osr value possible, one that generates minimum baudDiff
for (osrCheck = 5; osrCheck <= 32; osrCheck++) {
sbrTemp = (clockSpeed/(desiredBaudRate * osrCheck));

if(sbrTemp == 0)
break; // higher divisor returns 0 so can not use...

// Remember integer math so (X/Y)*Y will always be <=X
calculatedBaud = (clockSpeed / (osrCheck * sbrTemp));
baudDiffCheck = calculatedBaud - desiredBaudRate;
if (baudDiffCheck <= baudDiff) {
baudDiff = baudDiffCheck;
osr = osrCheck;
sbr = sbrTemp;
}
// Lets try the rounded up one as well
if (baudDiffCheck) {
calculatedBaud = (clockSpeed / (osrCheck * ++sbrTemp));
baudDiffCheck = desiredBaudRate - calculatedBaud;
if (baudDiffCheck <= baudDiff) {
baudDiff = baudDiffCheck;
osr = osrCheck;
sbr = sbrTemp;
}
}
}
// for lower OSR <= 7x turn on both edge sampling
uint32_t lpb = LPUART_BAUD_OSR(osr-1) | LPUART_BAUD_SBR(sbr);
if (osr < 8) {
lpb |= LPUART_BAUD_BOTHEDGE;
}
LPUART0_BAUD = lpb;

SIM_SOPT2 |= SIM_SOPT2_LPUARTSRC(1); // Lets use PLL?

rx_buffer_head = 0;
rx_buffer_tail = 0;
tx_buffer_head = 0;
tx_buffer_tail = 0;
transmitting = 0;
CORE_PIN47_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(5);
CORE_PIN48_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(5);
LPUART0_CTRL = 0;
LPUART0_MATCH = 0;
LPUART0_STAT = 0;

// Enable the transmitter, receiver and enable receiver interrupt
LPUART0_CTRL |= LPUART_CTRL_RIE | LPUART_CTRL_TE | LPUART_CTRL_RE;
NVIC_SET_PRIORITY(IRQ_LPUART0, IRQ_PRIORITY);
NVIC_ENABLE_IRQ(IRQ_LPUART0);
}

void serial6_format(uint32_t format)
{
uint32_t c;

// Bits 0-2 - Parity plus 9 bit.
c = LPUART0_CTRL;
//c = (c & ~(LPUART_CTRL_M | LPUART_CTRL_PE | LPUART_CTRL_PT)) | (format & (LPUART_CTRL_PE | LPUART_CTRL_PT)); // configure parity
//if (format & 0x04) c |= LPUART_CTRL_M; // 9 bits (might include parity)
c = (c & ~0x13) | (format & 0x03); // configure parity
if (format & 0x04) c |= 0x10; // 9 bits (might include parity)
LPUART0_CTRL = c;
if ((format & 0x0F) == 0x04) LPUART0_CTRL |= LPUART_CTRL_T8; // 8N2 is 9 bit with 9th bit always 1

// Bit 3 10 bit - Will assume that begin already cleared it.
if (format & 0x08)
LPUART0_BAUD |= LPUART_BAUD_M10;
// Bit 4 RXINVERT
c = LPUART0_STAT & ~LPUART_STAT_RXINV;
if (format & 0x10) c |= LPUART_STAT_RXINV; // rx invert
LPUART0_STAT = c;

// Bit 5 TXINVERT
c = LPUART0_CTRL & ~LPUART_CTRL_TXINV;
if (format & 0x20) c |= LPUART_CTRL_TXINV; // tx invert
LPUART0_CTRL = c;

// For T3.6 See about turning on 2 stop bit mode
if ( format & 0x100) LPUART0_BAUD |= LPUART_BAUD_SBNS;
}

void serial6_end(void)
{
if (!(SIM_SCGC2 & SIM_SCGC2_LPUART0)) return;
while (transmitting) yield(); // wait for buffered data to send
NVIC_DISABLE_IRQ(IRQ_LPUART0);
LPUART0_CTRL = 0;
CORE_PIN47_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
CORE_PIN48_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_MUX(1);
rx_buffer_head = 0;
rx_buffer_tail = 0;
if (rts_pin) rts_deassert();
}

void serial6_set_transmit_pin(uint8_t pin)
{
while (transmitting) ;
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
transmit_pin = portOutputRegister(pin);
}

void serial6_set_tx(uint8_t pin, uint8_t opendrain)
{
uint32_t cfg;

if (opendrain) pin |= 128;
if (pin == tx_pin_num) return;
if ((SIM_SCGC2 & SIM_SCGC2_LPUART0)) {
switch (tx_pin_num & 127) {
case 48: CORE_PIN48_CONFIG = 0; break; // PTE24
}
if (opendrain) {
cfg = PORT_PCR_DSE | PORT_PCR_ODE;
} else {
cfg = PORT_PCR_DSE | PORT_PCR_SRE;
}
switch (pin & 127) {
case 48: CORE_PIN48_CONFIG = cfg | PORT_PCR_MUX(5); break;
}
}
tx_pin_num = pin;
}

void serial6_set_rx(uint8_t pin)
{
}

int serial6_set_rts(uint8_t pin)
{
if (!(SIM_SCGC2 & SIM_SCGC2_LPUART0)) return 0;
if (pin < CORE_NUM_DIGITAL) {
rts_pin = portOutputRegister(pin);
pinMode(pin, OUTPUT);
rts_assert();
} else {
rts_pin = NULL;
return 0;
}
return 1;
}

int serial6_set_cts(uint8_t pin)
{
if (!(SIM_SCGC2 & SIM_SCGC2_LPUART0)) return 0;
if (pin == 56) {
CORE_PIN56_CONFIG = PORT_PCR_MUX(5) | PORT_PCR_PE; // weak pulldown
} else {
UART5_MODEM &= ~UART_MODEM_TXCTSE;
return 0;
}
UART5_MODEM |= UART_MODEM_TXCTSE;
return 1;
}

void serial6_putchar(uint32_t c)
{
uint32_t head, n;

if (!(SIM_SCGC2 & SIM_SCGC2_LPUART0)) return;
if (transmit_pin) transmit_assert();
head = tx_buffer_head;
if (++head >= SERIAL6_TX_BUFFER_SIZE) head = 0;
while (tx_buffer_tail == head) {
int priority = nvic_execution_priority();
if (priority <= IRQ_PRIORITY) {
if ((LPUART0_STAT & LPUART_STAT_TDRE)) {
uint32_t tail = tx_buffer_tail;
if (++tail >= SERIAL6_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
//if (use9Bits) UART5_C3 = (UART5_C3 & ~0x40) | ((n & 0x100) >> 2);
LPUART0_DATA = n;
tx_buffer_tail = tail;
}
} else if (priority >= 256) {
yield(); // wait
}
}
tx_buffer[head] = c;
transmitting = 1;
tx_buffer_head = head;

//LPUART0_CTRL |= LPUART_CTRL_TIE; // enable the transmit interrupt
BITBAND_SET_BIT(LPUART0_CTRL, TIE_BIT);

}

void serial6_write(const void *buf, unsigned int count)
{
const uint8_t *p = (const uint8_t *)buf;
while (count-- > 0) serial6_putchar(*p++);
}

void serial6_flush(void)
{
while (transmitting) yield(); // wait
}

int serial6_write_buffer_free(void)
{
uint32_t head, tail;

head = tx_buffer_head;
tail = tx_buffer_tail;
if (head >= tail) return SERIAL6_TX_BUFFER_SIZE - 1 - head + tail;
return tail - head - 1;
}

int serial6_available(void)
{
uint32_t head, tail;

head = rx_buffer_head;
tail = rx_buffer_tail;
if (head >= tail) return head - tail;
return SERIAL6_RX_BUFFER_SIZE + head - tail;
}

int serial6_getchar(void)
{
uint32_t head, tail;
int c;

head = rx_buffer_head;
tail = rx_buffer_tail;
if (head == tail) return -1;
if (++tail >= SERIAL6_RX_BUFFER_SIZE) tail = 0;
c = rx_buffer[tail];
rx_buffer_tail = tail;
if (rts_pin) {
int avail;
if (head >= tail) avail = head - tail;
else avail = SERIAL6_RX_BUFFER_SIZE + head - tail;
if (avail <= RTS_LOW_WATERMARK) rts_assert();
}
return c;
}

int serial6_peek(void)
{
uint32_t head, tail;

head = rx_buffer_head;
tail = rx_buffer_tail;
if (head == tail) return -1;
if (++tail >= SERIAL6_RX_BUFFER_SIZE) tail = 0;
return rx_buffer[tail];
}

void serial6_clear(void)
{
rx_buffer_head = rx_buffer_tail;
if (rts_pin) rts_assert();
}

// status interrupt combines
// Transmit data below watermark LPUART_STAT_TDRE
// Transmit complete LPUART_STAT_TC
// Idle line LPUART_STAT_IDLE
// Receive data above watermark LPUART_STAT_RDRF
// LIN break detect UART_S2_LBKDIF
// RxD pin active edge UART_S2_RXEDGIF

void lpuart0_status_isr(void)
{
uint32_t head, tail, n;
uint32_t c;

if (LPUART0_STAT & LPUART_STAT_RDRF) {
// if (use9Bits && (UART5_C3 & 0x80)) {
// n = UART5_D | 0x100;
// } else {
// n = UART5_D;
// }
n = LPUART0_DATA & 0x3ff; // use only the 10 data bits
head = rx_buffer_head + 1;
if (head >= SERIAL6_RX_BUFFER_SIZE) head = 0;
if (head != rx_buffer_tail) {
rx_buffer[head] = n;
rx_buffer_head = head;
}
if (rts_pin) {
int avail;
tail = tx_buffer_tail;
if (head >= tail) avail = head - tail;
else avail = SERIAL6_RX_BUFFER_SIZE + head - tail;
if (avail >= RTS_HIGH_WATERMARK) rts_deassert();
}
}
c = LPUART0_CTRL;
if ((c & LPUART_CTRL_TIE) && (LPUART0_STAT & LPUART_STAT_TDRE)) {
head = tx_buffer_head;
tail = tx_buffer_tail;
if (head == tail) {
BITBAND_CLR_BIT(LPUART0_CTRL, TIE_BIT);
BITBAND_SET_BIT(LPUART0_CTRL, TCIE_BIT);
//LPUART0_CTRL &= ~LPUART_CTRL_TIE;
//LPUART0_CTRL |= LPUART_CTRL_TCIE; // Actually wondering if we can just leave this one on...
} else {
if (++tail >= SERIAL6_TX_BUFFER_SIZE) tail = 0;
n = tx_buffer[tail];
//if (use9Bits) UART5_C3 = (UART5_C3 & ~0x40) | ((n & 0x100) >> 2);
LPUART0_DATA = n;
tx_buffer_tail = tail;
}
}
if ((c & LPUART_CTRL_TCIE) && (LPUART0_STAT & LPUART_STAT_TC)) {
transmitting = 0;
if (transmit_pin) transmit_deassert();
BITBAND_CLR_BIT(LPUART0_CTRL, TCIE_BIT);
// LPUART0_CTRL &= ~LPUART_CTRL_TCIE; // Actually wondering if we can just leave this one on...
}
}

#endif // HAS_KINETISK_LPUART0

+ 14
- 10
teensy3/touch.c View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* 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
@@ -10,10 +10,10 @@
* 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
* 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
* 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.
@@ -31,6 +31,8 @@
#include "core_pins.h"
//#include "HardwareSerial.h"

#if defined(HAS_KINETIS_TSI) || defined(HAS_KINETIS_TSI_LITE)

#if defined(__MK20DX128__) || defined(__MK20DX256__)
// These settings give approx 0.02 pF sensitivity and 1200 pF range
// Lower current, higher number of scans, and higher prescaler
@@ -48,7 +50,6 @@ static const uint8_t pin2tsi[] = {
};

#elif defined(__MK66FX1M0__)
#define CURRENT 2
#define NSCAN 9
#define PRESCALE 2
static const uint8_t pin2tsi[] = {
@@ -78,9 +79,6 @@ static const uint8_t pin2tsi[] = {

int touchRead(uint8_t pin)
{
#if defined(__MK64FX512__)
return 0; // no Touch sensing :(
#else
uint32_t ch;

if (pin >= NUM_DIGITAL_PINS) return 0;
@@ -89,7 +87,7 @@ int touchRead(uint8_t pin)

*portConfigRegister(pin) = PORT_PCR_MUX(0);
SIM_SCGC5 |= SIM_SCGC5_TSI;
#if defined(KINETISK)
#if defined(HAS_KINETIS_TSI)
TSI0_GENCS = 0;
TSI0_PEN = (1 << ch);
TSI0_SCANC = TSI_SCANC_REFCHRG(3) | TSI_SCANC_EXTCHRG(CURRENT);
@@ -98,7 +96,7 @@ int touchRead(uint8_t pin)
while (TSI0_GENCS & TSI_GENCS_SCNIP) ; // wait
delayMicroseconds(1);
return *((volatile uint16_t *)(&TSI0_CNTR1) + ch);
#elif defined(KINETISL)
#elif defined(HAS_KINETIS_TSI_LITE)
TSI0_GENCS = TSI_GENCS_REFCHRG(4) | TSI_GENCS_EXTCHRG(3) | TSI_GENCS_PS(PRESCALE)
| TSI_GENCS_NSCN(NSCAN) | TSI_GENCS_TSIEN | TSI_GENCS_EOSF;
TSI0_DATA = TSI_DATA_TSICH(ch) | TSI_DATA_SWTS;
@@ -107,9 +105,15 @@ int touchRead(uint8_t pin)
delayMicroseconds(1);
return TSI0_DATA & 0xFFFF;
#endif
#endif
}

#else

int touchRead(uint8_t pin)
{
return 0; // no Touch sensing :(
}

#endif



+ 61
- 21
teensy3/usb_audio.cpp View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2016 PJRC.COM, LLC.
* 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
@@ -28,14 +28,17 @@
* SOFTWARE.
*/

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

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

// Uncomment this to work around a limitation in Macintosh adaptive rates
// This is not a perfect solution. Details here:
// https://forum.pjrc.com/threads/34855-Distorted-audio-when-using-USB-input-on-Teensy-3-1
//#define MACOSX_ADAPTIVE_LIMIT

bool AudioInputUSB::update_responsibility;
audio_block_t * AudioInputUSB::incoming_left;
audio_block_t * AudioInputUSB::incoming_right;
@@ -44,7 +47,7 @@ audio_block_t * AudioInputUSB::ready_right;
uint16_t AudioInputUSB::incoming_count;
uint8_t AudioInputUSB::receive_flag;

struct usb_audio_features_struct AudioInputUSB::features = {0,0,FEATURE_MAX_VOLUME};
struct usb_audio_features_struct AudioInputUSB::features = {0,0,FEATURE_MAX_VOLUME/2};

#define DMABUFATTR __attribute__ ((section(".dmabuffers"), aligned (4)))
uint16_t usb_audio_receive_buffer[AUDIO_RX_SIZE/2] DMABUFATTR;
@@ -67,9 +70,7 @@ void AudioInputUSB::begin(void)
// but also because the PC may stop transmitting data, which
// means we no longer get receive callbacks from usb_dev.
update_responsibility = false;
//usb_audio_sync_feedback = 722824;
//usb_audio_sync_feedback = 723700; // too fast?
usb_audio_sync_feedback = 722534; // too slow
usb_audio_sync_feedback = feedback_accumulator >> 8;
}

static void copy_to_buffers(const uint32_t *src, int16_t *left, int16_t *right, unsigned int len)
@@ -84,7 +85,7 @@ static void copy_to_buffers(const uint32_t *src, int16_t *left, int16_t *right,
while ((src < target - 2)) {
uint32_t n1 = *src++;
uint32_t n = *src++;
*(uint32_t *)left = n1 & 0xFFFF | ((n & 0xFFFF) << 16);
*(uint32_t *)left = (n1 & 0xFFFF) | ((n & 0xFFFF) << 16);
left+=2;
*(uint32_t *)right = (n1 >> 16) | ((n & 0xFFFF0000)) ;
right+=2;
@@ -187,9 +188,12 @@ void AudioInputUSB::update(void)
__enable_irq();
if (f) {
int diff = AUDIO_BLOCK_SAMPLES/2 - (int)c;
feedback_accumulator += diff;
// TODO: min/max sanity check for feedback_accumulator??
usb_audio_sync_feedback = (feedback_accumulator >> 8) + diff * 3;
feedback_accumulator += diff / 3;
uint32_t feedback = (feedback_accumulator >> 8) + diff * 100;
#ifdef MACOSX_ADAPTIVE_LIMIT
if (feedback > 722698) feedback = 722698;
#endif
usb_audio_sync_feedback = feedback;
//if (diff > 0) {
//serial_print(".");
//} else if (diff < 0) {
@@ -200,7 +204,7 @@ void AudioInputUSB::update(void)
//serial_print(".");
if (!left || !right) {
//serial_print("#"); // buffer underrun - PC sending too slow
if (f) feedback_accumulator += 10 << 8;
//if (f) feedback_accumulator += 10 << 8;
}
if (left) {
transmit(left, 0);
@@ -249,8 +253,11 @@ void AudioOutputUSB::update(void)
{
audio_block_t *left, *right;

left = receiveReadOnly(0); // input 0 = left channel
right = receiveReadOnly(1); // input 1 = right channel
// TODO: we shouldn't be writing to these......
//left = receiveReadOnly(0); // input 0 = left channel
//right = receiveReadOnly(1); // input 1 = right channel
left = receiveWritable(0); // input 0 = left channel
right = receiveWritable(1); // input 1 = right channel
if (usb_audio_transmit_setting == 0) {
if (left) release(left);
if (right) release(right);
@@ -262,12 +269,20 @@ void AudioOutputUSB::update(void)
return;
}
if (left == NULL) {
if (right == NULL) return;
right->ref_count++;
left = right;
} else if (right == NULL) {
left->ref_count++;
right = left;
left = allocate();
if (left == NULL) {
if (right) release(right);
return;
}
memset(left->data, 0, sizeof(left->data));
}
if (right == NULL) {
right = allocate();
if (right == NULL) {
release(left);
return;
}
memset(right->data, 0, sizeof(right->data));
}
__disable_irq();
if (left_1st == NULL) {
@@ -344,6 +359,31 @@ unsigned int usb_audio_transmit_callback(void)
return target * 4;
}


struct setup_struct {
union {
struct {
uint8_t bmRequestType;
uint8_t bRequest;
union {
struct {
uint8_t bChannel; // 0=main, 1=left, 2=right
uint8_t bCS; // Control Selector
};
uint16_t wValue;
};
union {
struct {
uint8_t bIfEp; // type of entity
uint8_t bEntityId; // UnitID, TerminalID, etc.
};
uint16_t wIndex;
};
uint16_t wLength;
};
};
};

int usb_audio_get_feature(void *stp, uint8_t *data, uint32_t *datalen)
{
struct setup_struct setup = *((struct setup_struct *)stp);

+ 34
- 28
teensy3/usb_audio.h View File

@@ -1,3 +1,33 @@
/* 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 USBaudio_h_
#define USBaudio_h_

@@ -22,32 +52,6 @@ extern uint8_t usb_audio_transmit_setting;
#ifdef __cplusplus
}

// setup struct definition could be moved from usb_dev.c to usb_dev.h so we can reuse
// it instead of redefining it here
struct setup_struct {
union {
struct {
uint8_t bmRequestType;
uint8_t bRequest;
union {
struct {
uint8_t bChannel; // 0=main, 1=left, 2=right
uint8_t bCS; // Control Selector
};
uint16_t wValue;
};
union {
struct {
uint8_t bIfEp; // type of entity
uint8_t bEntityId; // UnitID, TerminalID, etc.
};
uint16_t wIndex;
};
uint16_t wLength;
};
};
};

// audio features supported
struct usb_audio_features_struct {
int change; // set to 1 when any value is changed
@@ -66,9 +70,11 @@ public:
friend void usb_audio_receive_callback(unsigned int len);
friend int usb_audio_set_feature(void *stp, uint8_t *buf);
friend int usb_audio_get_feature(void *stp, uint8_t *data, uint32_t *datalen);

static struct usb_audio_features_struct features;

float volume(void) {
if (features.mute) return 0.0;
return (float)(features.volume) * (1.0 / (float)FEATURE_MAX_VOLUME);
}
private:
static bool update_responsibility;
static audio_block_t *incoming_left;

+ 0
- 0
teensy3/usb_desc.c View File


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

Loading…
Cancel
Save