瀏覽代碼

Merge pull request #1 from PaulStoffregen/master

sync with upstream
teensy4-core
Andrew Kroll 6 年之前
父節點
當前提交
c284975191
No account linked to committer's email address
共有 100 個文件被更改,包括 15322 次插入2695 次删除
  1. +27
    -0
      .github/ISSUE_TEMPLATE.md
  2. +1
    -11
      README.md
  3. +513
    -0
      keywords.txt
  4. +30
    -2
      teensy/HardwareSerial.cpp
  5. +1
    -0
      teensy/HardwareSerial.h
  6. +48
    -17
      teensy/IPAddress.cpp
  7. +15
    -7
      teensy/IPAddress.h
  8. +1
    -0
      teensy/Keyboard.h
  9. +53
    -0
      teensy/MIDIUSB.h
  10. +1
    -0
      teensy/Mouse.h
  11. +9
    -127
      teensy/Print.cpp
  12. +10
    -63
      teensy/Print.h
  13. +4
    -4
      teensy/Stream.cpp
  14. +8
    -8
      teensy/Stream.h
  15. +1
    -0
      teensy/Udp.h
  16. +3
    -1
      teensy/WString.cpp
  17. +219
    -1
      teensy/core_pins.h
  18. +1
    -1
      teensy/keylayouts.c
  19. +575
    -207
      teensy/keylayouts.h
  20. +2
    -0
      teensy/pgmspace.h
  21. +13
    -0
      teensy/pins_arduino.h
  22. +1
    -1
      teensy/wiring.h
  23. +7
    -0
      teensy3/Arduino.h
  24. +127
    -27
      teensy3/AudioStream.cpp
  25. +54
    -12
      teensy3/AudioStream.h
  26. +19
    -0
      teensy3/Client.h
  27. +133
    -6
      teensy3/DMAChannel.cpp
  28. +562
    -270
      teensy3/DMAChannel.h
  29. +344
    -0
      teensy3/EventResponder.cpp
  30. +274
    -0
      teensy3/EventResponder.h
  31. +72
    -0
      teensy3/FS.h
  32. +255
    -8
      teensy3/HardwareSerial.h
  33. +31
    -0
      teensy3/HardwareSerial1.cpp
  34. +31
    -0
      teensy3/HardwareSerial2.cpp
  35. +31
    -0
      teensy3/HardwareSerial3.cpp
  36. +41
    -0
      teensy3/HardwareSerial4.cpp
  37. +41
    -0
      teensy3/HardwareSerial5.cpp
  38. +41
    -0
      teensy3/HardwareSerial6.cpp
  39. +53
    -45
      teensy3/IPAddress.cpp
  40. +79
    -36
      teensy3/IPAddress.h
  41. +124
    -165
      teensy3/IntervalTimer.cpp
  42. +128
    -73
      teensy3/IntervalTimer.h
  43. +3
    -0
      teensy3/Keyboard.h
  44. +56
    -0
      teensy3/MIDIUSB.h
  45. +78
    -22
      teensy3/Makefile
  46. +3
    -0
      teensy3/Mouse.h
  47. +186
    -30
      teensy3/Print.cpp
  48. +26
    -3
      teensy3/Print.h
  49. +137
    -23
      teensy3/SPIFIFO.h
  50. +21
    -0
      teensy3/Server.h
  51. +10
    -35
      teensy3/Stream.cpp
  52. +18
    -11
      teensy3/Stream.h
  53. +60
    -122
      teensy3/Tone.cpp
  54. +1
    -0
      teensy3/Udp.h
  55. +3
    -3
      teensy3/WCharacter.h
  56. +2
    -0
      teensy3/WConstants.h
  57. +23
    -7
      teensy3/WMath.cpp
  58. +51
    -5
      teensy3/WProgram.h
  59. +17
    -6
      teensy3/WString.cpp
  60. +13
    -2
      teensy3/WString.h
  61. +192
    -76
      teensy3/analog.c
  62. +36
    -1
      teensy3/avr/eeprom.h
  63. +1
    -0
      teensy3/avr/interrupt.h
  64. +22
    -0
      teensy3/avr/io.h
  65. +67
    -5
      teensy3/avr/pgmspace.h
  66. +26
    -0
      teensy3/avr/power.h
  67. +24
    -2
      teensy3/avr/sleep.h
  68. +21
    -0
      teensy3/avr/wdt.h
  69. +15
    -7
      teensy3/avr_emulation.cpp
  70. +1300
    -147
      teensy3/avr_emulation.h
  71. +5
    -1
      teensy3/avr_functions.h
  72. +2
    -0
      teensy3/binary.h
  73. +2
    -0
      teensy3/core_id.h
  74. +1278
    -14
      teensy3/core_pins.h
  75. +316
    -27
      teensy3/eeprom.c
  76. +1
    -1
      teensy3/elapsedMillis.h
  77. +2
    -2
      teensy3/keylayouts.c
  78. +506
    -135
      teensy3/keylayouts.h
  79. +3602
    -430
      teensy3/kinetis.h
  80. +32
    -2
      teensy3/main.cpp
  81. +63
    -71
      teensy3/math_helper.c
  82. +336
    -0
      teensy3/memcpy-armv7m.S
  83. +93
    -0
      teensy3/memset.S
  84. +766
    -61
      teensy3/mk20dx128.c
  85. +2
    -0
      teensy3/mk20dx128.h
  86. +6
    -3
      teensy3/mk20dx128.ld
  87. +7
    -39
      teensy3/mk20dx256.ld
  88. +115
    -0
      teensy3/mk64fx512.ld
  89. +115
    -0
      teensy3/mk66fx1m0.ld
  90. +113
    -0
      teensy3/mkl26z64.ld
  91. +35
    -0
      teensy3/new.cpp
  92. +28
    -1
      teensy3/new.h
  93. +151
    -17
      teensy3/nonstd.c
  94. +2
    -0
      teensy3/pgmspace.h
  95. +179
    -32
      teensy3/pins_arduino.h
  96. +720
    -198
      teensy3/pins_teensy.c
  97. +79
    -0
      teensy3/ser_print.c
  98. +40
    -0
      teensy3/ser_print.h
  99. +331
    -62
      teensy3/serial1.c
  100. +0
    -0
      teensy3/serial1_doughboy.txt

+ 27
- 0
.github/ISSUE_TEMPLATE.md 查看文件

@@ -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
- 11
README.md 查看文件

@@ -1,15 +1,5 @@
Teensy 2.0 and 3.0 core libraries for Arduino.
Teensy 2.0, 3.x, LC core libraries for Arduino.

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

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

This version implements overclock to 120MHz, 144MHz and 168MHz.

Howto:
1. Overwrite Arduino\hardware\teensy\boards.txt with this version
2. Overwrite all in core/teensy3 with this version





+ 513
- 0
keywords.txt 查看文件

@@ -0,0 +1,513 @@

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

# teensy specific functions
elapsedMillis LITERAL1
elapsedMicros LITERAL1
readString KEYWORD2
readStringUntil KEYWORD2
analogReadRes KEYWORD2
analogReadResolution KEYWORD2
analogReadAveraging KEYWORD2
analogWriteRes KEYWORD2
analogWriteResolution KEYWORD2
analogWriteFrequency KEYWORD2
touchRead KEYWORD2
Teensy3Clock KEYWORD2
IntervalTimer KEYWORD2
printf KEYWORD2
digitalWriteFast KEYWORD2
digitalReadFast KEYWORD2
transmitterEnable KEYWORD2
attachRts KEYWORD2
attachCts KEYWORD2
PROGMEM LITERAL1
DMAMEM LITERAL1
FASTRUN LITERAL1
Serial4 KEYWORD1
Serial5 KEYWORD1
Serial6 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, now also removed from Teensyduino
#BYTE LITERAL1

# Arduino constants
A0 LITERAL1
A1 LITERAL1
A2 LITERAL1
A3 LITERAL1
A4 LITERAL1
A5 LITERAL1
A6 LITERAL1
A7 LITERAL1
A8 LITERAL1
A9 LITERAL1
A10 LITERAL1
A11 LITERAL1
A12 LITERAL1
A13 LITERAL1
A14 LITERAL1
A15 LITERAL1
A16 LITERAL1
A17 LITERAL1
A18 LITERAL1
A19 LITERAL1
A20 LITERAL1
A21 LITERAL1
A22 LITERAL1
A23 LITERAL1
A24 LITERAL1
A25 LITERAL1
A26 LITERAL1
SS LITERAL1
MOSI LITERAL1
MISO LITERAL1
SCK LITERAL1
SDA LITERAL1
SCL LITERAL1
NUM_DIGITAL_PINS LITERAL1
NUM_ANALOG_INPUTS LITERAL1
analogInputToDigitalPin KEYWORD2
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_DISABLE LITERAL1

# String functions
copy KEYWORD2
append KEYWORD2

# Teensy 2.0 pin names
PIN_A0 LITERAL1
PIN_A1 LITERAL1
PIN_A2 LITERAL1
PIN_A3 LITERAL1
PIN_A4 LITERAL1
PIN_A5 LITERAL1
PIN_A6 LITERAL1
PIN_A7 LITERAL1
PIN_B0 LITERAL1
PIN_B1 LITERAL1
PIN_B2 LITERAL1
PIN_B3 LITERAL1
PIN_B4 LITERAL1
PIN_B5 LITERAL1
PIN_B6 LITERAL1
PIN_B7 LITERAL1
PIN_C0 LITERAL1
PIN_C1 LITERAL1
PIN_C2 LITERAL1
PIN_C3 LITERAL1
PIN_C4 LITERAL1
PIN_C5 LITERAL1
PIN_C6 LITERAL1
PIN_C7 LITERAL1
PIN_D0 LITERAL1
PIN_D1 LITERAL1
PIN_D2 LITERAL1
PIN_D3 LITERAL1
PIN_D4 LITERAL1
PIN_D5 LITERAL1
PIN_D6 LITERAL1
PIN_D7 LITERAL1
PIN_E0 LITERAL1
PIN_E1 LITERAL1
PIN_E2 LITERAL1
PIN_E3 LITERAL1
PIN_E4 LITERAL1
PIN_E5 LITERAL1
PIN_E6 LITERAL1
PIN_E7 LITERAL1
PIN_F0 LITERAL1
PIN_F1 LITERAL1
PIN_F2 LITERAL1
PIN_F3 LITERAL1
PIN_F4 LITERAL1
PIN_F5 LITERAL1
PIN_F6 LITERAL1
PIN_F7 LITERAL1
PIN_SS LITERAL1
PIN_SCLK LITERAL1
PIN_MOSI LITERAL1
PIN_MISO LITERAL1
PIN_LED LITERAL1
ANALOG_0 LITERAL1 AnalogRead
ANALOG_1 LITERAL1 AnalogRead
ANALOG_2 LITERAL1 AnalogRead
ANALOG_3 LITERAL1 AnalogRead
ANALOG_4 LITERAL1 AnalogRead
ANALOG_5 LITERAL1 AnalogRead
ANALOG_6 LITERAL1 AnalogRead
ANALOG_7 LITERAL1 AnalogRead
ANALOG_1_TO_0_X10 LITERAL1 AnalogRead
ANALOG_1_TO_0_X200 LITERAL1 AnalogRead
ANALOG_3_TO_2_X10 LITERAL1 AnalogRead
ANALOG_3_TO_2_X200 LITERAL1 AnalogRead
ANALOG_0_TO_1 LITERAL1 AnalogRead
ANALOG_2_TO_1 LITERAL1 AnalogRead
ANALOG_3_TO_1 LITERAL1 AnalogRead
ANALOG_4_TO_1 LITERAL1 AnalogRead
ANALOG_5_TO_1 LITERAL1 AnalogRead
ANALOG_6_TO_1 LITERAL1 AnalogRead
ANALOG_7_TO_1 LITERAL1 AnalogRead
ANALOG_0_TO_2 LITERAL1 AnalogRead
ANALOG_1_TO_2 LITERAL1 AnalogRead
ANALOG_3_TO_2 LITERAL1 AnalogRead
ANALOG_4_TO_2 LITERAL1 AnalogRead
ANALOG_5_TO_2 LITERAL1 AnalogRead
ANALOG_1_1V LITERAL1 AnalogRead
ANALOG_0V LITERAL1 AnalogRead

# USB Serial
send_now KEYWORD2
baud KEYWORD2
stopbits KEYWORD2
paritytype KEYWORD2
numbits KEYWORD2
dtr KEYWORD2
rts KEYWORD2

# USB Keyboard
write_unicode KEYWORD2
set_modifier KEYWORD2
set_key1 KEYWORD2
set_key2 KEYWORD2
set_key3 KEYWORD2
set_key4 KEYWORD2
set_key5 KEYWORD2
set_key6 KEYWORD2
set_media KEYWORD2
MODIFIERKEY_CTRL LITERAL1
MODIFIERKEY_SHIFT LITERAL1
MODIFIERKEY_ALT LITERAL1
MODIFIERKEY_GUI LITERAL1
MODIFIERKEY_LEFT_CTRL LITERAL1
MODIFIERKEY_LEFT_SHIFT LITERAL1
MODIFIERKEY_LEFT_ALT LITERAL1
MODIFIERKEY_LEFT_GUI LITERAL1
MODIFIERKEY_RIGHT_CTRL LITERAL1
MODIFIERKEY_RIGHT_SHIFT LITERAL1
MODIFIERKEY_RIGHT_ALT LITERAL1
MODIFIERKEY_RIGHT_GUI LITERAL1
KEY_MEDIA_VOLUME_INC LITERAL1
KEY_MEDIA_VOLUME_DEC LITERAL1
KEY_MEDIA_MUTE LITERAL1
KEY_MEDIA_PLAY_PAUSE LITERAL1
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
KEY_D LITERAL1
KEY_E LITERAL1
KEY_F LITERAL1
KEY_G LITERAL1
KEY_H LITERAL1
KEY_I LITERAL1
KEY_J LITERAL1
KEY_K LITERAL1
KEY_L LITERAL1
KEY_M LITERAL1
KEY_N LITERAL1
KEY_O LITERAL1
KEY_P LITERAL1
KEY_Q LITERAL1
KEY_R LITERAL1
KEY_S LITERAL1
KEY_T LITERAL1
KEY_U LITERAL1
KEY_V LITERAL1
KEY_W LITERAL1
KEY_X LITERAL1
KEY_Y LITERAL1
KEY_Z LITERAL1
KEY_1 LITERAL1
KEY_2 LITERAL1
KEY_3 LITERAL1
KEY_4 LITERAL1
KEY_5 LITERAL1
KEY_6 LITERAL1
KEY_7 LITERAL1
KEY_8 LITERAL1
KEY_9 LITERAL1
KEY_0 LITERAL1
KEY_ENTER LITERAL1
KEY_ESC LITERAL1
KEY_BACKSPACE LITERAL1
KEY_TAB LITERAL1
KEY_SPACE LITERAL1
KEY_MINUS LITERAL1
KEY_EQUAL LITERAL1
KEY_LEFT_BRACE LITERAL1
KEY_RIGHT_BRACE LITERAL1
KEY_BACKSLASH LITERAL1
KEY_NON_US_NUM LITERAL1
KEY_SEMICOLON LITERAL1
KEY_QUOTE LITERAL1
KEY_TILDE LITERAL1
KEY_COMMA LITERAL1
KEY_PERIOD LITERAL1
KEY_SLASH LITERAL1
KEY_CAPS_LOCK LITERAL1
KEY_F1 LITERAL1
KEY_F2 LITERAL1
KEY_F3 LITERAL1
KEY_F4 LITERAL1
KEY_F5 LITERAL1
KEY_F6 LITERAL1
KEY_F7 LITERAL1
KEY_F8 LITERAL1
KEY_F9 LITERAL1
KEY_F10 LITERAL1
KEY_F11 LITERAL1
KEY_F12 LITERAL1
KEY_PRINTSCREEN LITERAL1
KEY_SCROLL_LOCK LITERAL1
KEY_PAUSE LITERAL1
KEY_INSERT LITERAL1
KEY_HOME LITERAL1
KEY_PAGE_UP LITERAL1
KEY_DELETE LITERAL1
KEY_END LITERAL1
KEY_PAGE_DOWN LITERAL1
KEY_RIGHT LITERAL1
KEY_LEFT LITERAL1
KEY_DOWN LITERAL1
KEY_UP LITERAL1
KEY_NUM_LOCK LITERAL1
KEYPAD_SLASH LITERAL1
KEYPAD_ASTERIX LITERAL1
KEYPAD_MINUS LITERAL1
KEYPAD_PLUS LITERAL1
KEYPAD_ENTER LITERAL1
KEYPAD_1 LITERAL1
KEYPAD_2 LITERAL1
KEYPAD_3 LITERAL1
KEYPAD_4 LITERAL1
KEYPAD_5 LITERAL1
KEYPAD_6 LITERAL1
KEYPAD_7 LITERAL1
KEYPAD_8 LITERAL1
KEYPAD_9 LITERAL1
KEYPAD_0 LITERAL1
KEYPAD_PERIOD LITERAL1
KEY_UP_ARROW LITERAL1
KEY_DOWN_ARROW LITERAL1
KEY_LEFT_ARROW LITERAL1
KEY_RIGHT_ARROW LITERAL1
KEY_RETURN LITERAL1
KEY_LEFT_CTRL LITERAL1
KEY_LEFT_SHIFT LITERAL1
KEY_LEFT_ALT LITERAL1
KEY_LEFT_GUI LITERAL1
KEY_RIGHT_CTRL LITERAL1
KEY_RIGHT_SHIFT LITERAL1
KEY_RIGHT_ALT LITERAL1
KEY_RIGHT_GUI LITERAL1

# USB Mouse
moveTo KEYWORD2
screenSize KEYWORD2
scroll KEYWORD2
set_buttons KEYWORD2
isPressed KEYWORD2
MOUSE_LEFT LITERAL1
MOUSE_MIDDLE LITERAL1
MOUSE_RIGHT LITERAL1
MOUSE_ALL LITERAL1
MOUSE_BACK LITERAL1
MOUSE_FORWARD LITERAL1

# USB Joystick
Joystick KEYWORD1
button KEYWORD2
X KEYWORD2
Y KEYWORD2
position KEYWORD2
Z KEYWORD2
Xrotate KEYWORD2
Yrotate KEYWORD2
Zrotate KEYWORD2
sliderLeft KEYWORD2
sliderRight KEYWORD2
slider KEYWORD2
hat KEYWORD2
useManualSend KEYWORD2

# USB Disk
Disk KEYWORD1
claim KEYWORD2
readSector KEYWORD2
writeSector KEYWORD2
releaseReadOnly KEYWORD2

# USB MIDI
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
getSysExArray KEYWORD2
setHandleNoteOff KEYWORD2
setHandleNoteOn KEYWORD2
setHandleVelocityChange KEYWORD2
setHandleControlChange KEYWORD2
setHandleProgramChange KEYWORD2
setHandleAfterTouch KEYWORD2
setHandlePitchChange KEYWORD2
NoteOff LITERAL1
NoteOn LITERAL1
AfterTouchPoly LITERAL1
ControlChange LITERAL1
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
recv KEYWORD2
send KEYWORD2

# USB Flight Sim Controls
FlightSim KEYWORD1
FlightSimCommand KEYWORD2
FlightSimInteger KEYWORD2
FlightSimFloat KEYWORD2
FlightSimElapsedFrames KEYWORD2
onChange KEYWORD2
update KEYWORD2
isEnabled KEYWORD2
getFrameCount KEYWORD2
XPlaneRef KEYWORD2

# USB Touchscreen
TouchscreenUSB KEYWORD1

+ 30
- 2
teensy/HardwareSerial.cpp 查看文件

@@ -25,6 +25,7 @@
#include <avr/interrupt.h>
#include "core_pins.h"
#include "HardwareSerial.h"
#include "wiring_private.h"

#define RX_BUFFER_SIZE 64
static volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
@@ -91,6 +92,16 @@ int HardwareSerial::available(void)
return RX_BUFFER_SIZE + head - tail;
}

int HardwareSerial::availableForWrite(void)
{
uint8_t head, tail;

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

int HardwareSerial::peek(void)
{
uint8_t head, tail;
@@ -135,6 +146,7 @@ void HardwareSerial::write(uint8_t c)
#endif
{
uint8_t i;
uint8_t status;

if (!(UCSR1B & (1<<TXEN1))) {
#if ARDUINO >= 100
@@ -147,13 +159,28 @@ void HardwareSerial::write(uint8_t c)
if (tx_enable_pin < 255 && !transmitting) {
digitalWrite(tx_enable_pin, HIGH);
}
// If the buffer and the data register is empty, just write the byte
// to the data register and be done. This shortcut helps
// significantly improve the effective datarate at high (>
// 500kbit/s) bitrates, where interrupt overhead becomes a slowdown.
if ((tx_buffer_head == tx_buffer_tail) && (UCSR1A & (1<<UDRE1))) {
status = SREG;
cli();
UDR1 = c;
transmitting = 1;
SREG = status;
return 1;
}

i = tx_buffer_head + 1;
if (i >= TX_BUFFER_SIZE) i = 0;
while (tx_buffer_tail == i) ; // wait until space in buffer
tx_buffer[i] = c;
transmitting = 1;
tx_buffer_head = i;
UCSR1B = (1<<RXEN1) | (1<<TXCIE1) | (1<<TXEN1) | (1<<RXCIE1) | (1<<UDRIE1);
//UCSR1B = (1<<RXEN1) | (1<<TXCIE1) | (1<<TXEN1) | (1<<RXCIE1) | (1<<UDRIE1);
sbi(UCSR1B, UDRIE1);

#if ARDUINO >= 100
return 1;
#endif
@@ -178,7 +205,8 @@ ISR(USART1_UDRE_vect)

if (tx_buffer_head == tx_buffer_tail) {
// buffer is empty, disable transmit interrupt
UCSR1B = (1<<RXEN1) | (1<<TXCIE1) | (1<<TXEN1) | (1<<RXCIE1);
//UCSR1B = (1<<RXEN1) | (1<<TXCIE1) | (1<<TXEN1) | (1<<RXCIE1);
cbi(UCSR1B, UDRIE1);
} else {
i = tx_buffer_tail + 1;
if (i >= TX_BUFFER_SIZE) i = 0;

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

@@ -17,6 +17,7 @@ public:
virtual int peek(void);
virtual int read(void);
virtual void flush(void);
int availableForWrite(void);
void clear(void);
#if ARDUINO >= 100
virtual size_t write(uint8_t);

+ 48
- 17
teensy/IPAddress.cpp 查看文件

@@ -4,54 +4,85 @@

IPAddress::IPAddress()
{
memset(_address, 0, sizeof(_address));
_address.dword = 0;
}

IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
{
_address[0] = first_octet;
_address[1] = second_octet;
_address[2] = third_octet;
_address[3] = fourth_octet;
_address.bytes[0] = first_octet;
_address.bytes[1] = second_octet;
_address.bytes[2] = third_octet;
_address.bytes[3] = fourth_octet;
}

IPAddress::IPAddress(uint32_t address)
{
memcpy(_address, &address, sizeof(_address));
_address.dword = address;
}

IPAddress::IPAddress(const uint8_t *address)
{
memcpy(_address, address, sizeof(_address));
memcpy(_address.bytes, address, sizeof(_address));
}

IPAddress& IPAddress::operator=(const uint8_t *address)
{
memcpy(_address, address, sizeof(_address));
memcpy(_address.bytes, address, sizeof(_address.bytes));
return *this;
}

IPAddress& IPAddress::operator=(uint32_t address)
{
memcpy(_address, (const uint8_t *)&address, sizeof(_address));
_address.dword = address;
return *this;
}

bool IPAddress::operator==(const uint8_t* addr)
{
return memcmp(addr, _address, sizeof(_address)) == 0;
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
}

size_t IPAddress::printTo(Print& p) const
{
size_t n = 0;
for (int i =0; i < 3; i++)
{
n += p.print(_address[i], DEC);
n += p.print('.');
for (int i= 0; i < 3; i++) {
p.print(_address.bytes[i], DEC);
p.print('.');
}
n += p.print(_address[3], DEC);
return n;
p.print(_address.bytes[3], DEC);
return 4;
}

bool IPAddress::fromString(const char *address)
{
uint16_t acc = 0; // Accumulator
uint8_t dots = 0;

while (*address) {
char c = *address++;
if (c >= '0' && c <= '9') {
acc = acc * 10 + (c - '0');
if (acc > 255) {
// Value out of [0..255] range
return false;
}
} else if (c == '.') {
if (dots == 3) {
// Too much dots (there must be 3 dots)
return false;
}
_address.bytes[dots++] = acc;
acc = 0;
} else {
// Invalid char
return false;
}
}
if (dots != 3) {
// Too few dots (there must be 3 dots)
return false;
}
_address.bytes[3] = acc;
return true;
}

#endif

+ 15
- 7
teensy/IPAddress.h 查看文件

@@ -32,13 +32,16 @@
// A class to make it easier to handle and pass around IP addresses

class IPAddress : public Printable {
private:
uint8_t _address[4]; // IPv4 address
private:
union {
uint8_t bytes[4]; // IPv4 address
uint32_t dword;
} _address;
// Access the raw byte array containing the address. Because this returns a pointer
// to the internal structure rather than a copy of the address this function should only
// be used when you know that the usage of the returned uint8_t* will be transient and not
// stored.
uint8_t* raw_address() { return _address; };
uint8_t* raw_address() { return _address.bytes; };

public:
// Constructors
@@ -47,15 +50,20 @@ public:
IPAddress(uint32_t address);
IPAddress(const uint8_t *address);

bool fromString(const char *address);
bool fromString(const String &address) {
return fromString(address.c_str());
}

// Overloaded cast operator to allow IPAddress objects to be used where a pointer
// to a four-byte uint8_t array is expected
operator uint32_t() { return *((uint32_t*)_address); };
bool operator==(const IPAddress& addr) { return (*((uint32_t*)_address)) == (*((uint32_t*)addr._address)); };
operator uint32_t() { return _address.dword; };
bool operator==(const IPAddress& addr) { return _address.dword == addr._address.dword; };
bool operator==(const uint8_t* addr);

// Overloaded index operator to allow getting and setting individual octets of the address
uint8_t operator[](int index) const { return _address[index]; };
uint8_t& operator[](int index) { return _address[index]; };
uint8_t operator[](int index) const { return _address.bytes[index]; };
uint8_t& operator[](int index) { return _address.bytes[index]; };

// Overloaded copy operators to allow initialisation of IPAddress objects from other types
IPAddress& operator=(const uint8_t *address);

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

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

+ 53
- 0
teensy/MIDIUSB.h 查看文件

@@ -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 查看文件

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

+ 9
- 127
teensy/Print.cpp 查看文件

@@ -30,31 +30,13 @@
#include "Print.h"


#if ARDUINO >= 100
#else
void Print::write(const char *str)
{
write((const uint8_t *)str, strlen(str));
}
#endif


#if ARDUINO >= 100
size_t Print::write(const uint8_t *buffer, size_t size)
{
size_t count = 0;
while (size--) count += write(*buffer++);
return count;
}
#else
void Print::write(const uint8_t *buffer, size_t size)
{
while (size--) write(*buffer++);
}
#endif


#if ARDUINO >= 100
size_t Print::print(const String &s)
{
uint8_t buffer[33];
@@ -71,23 +53,12 @@ size_t Print::print(const String &s)
}
return count;
}
#else
void Print::print(const String &s)
{
unsigned int len = s.length();
for (unsigned int i=0; i < len; i++) {
write(s[i]);
}
}
#endif


#if ARDUINO >= 100
size_t Print::print(const __FlashStringHelper *ifsh)
{
uint8_t buffer[32];
size_t count = 0;
const char PROGMEM *p = (const char PROGMEM *)ifsh;
const char *p = (const char *)ifsh;
unsigned int len = strlen_P(p);
while (len > 0) {
unsigned int nbytes = len;
@@ -99,20 +70,7 @@ size_t Print::print(const __FlashStringHelper *ifsh)
}
return count;
}
#else
void Print::print(const __FlashStringHelper *ifsh)
{
const char PROGMEM *p = (const char PROGMEM *)ifsh;
while (1) {
unsigned char c = pgm_read_byte(p++);
if (c == 0) return;
write(c);
}
}
#endif


#if ARDUINO >= 100
size_t Print::print(long n)
{
uint8_t sign=0;
@@ -123,36 +81,13 @@ size_t Print::print(long n)
}
return printNumber(n, sign, 10);
}
#else
void Print::print(long n)
{
uint8_t sign=0;

if (n < 0) {
sign = 1;
n = -n;
}
printNumber(n, sign, 10);
}
#endif


#if ARDUINO >= 100
size_t Print::println(void)
{
uint8_t buf[2]={'\r', '\n'};
return write(buf, 2);
}
#else
void Print::println(void)
{
uint8_t buf[2]={'\r', '\n'};
write(buf, 2);
}
#endif


#if ARDUINO >= 100
static int printf_putchar(char c, FILE *fp)
{
((class Print *)(fdev_get_udata(fp)))->write((uint8_t)c);
@@ -180,7 +115,6 @@ int Print::printf(const __FlashStringHelper *format, ...)
va_start(ap, format);
return vfprintf_P(&f, (const char *)format, ap);
}
#endif


//#define USE_HACKER_DELIGHT_OPTIMIZATION
@@ -344,11 +278,7 @@ uint32_t usec_print = 0;
#endif


#if ARDUINO >= 100
size_t Print::printNumberDec(unsigned long n, uint8_t sign)
#else
void Print::printNumberDec(unsigned long n, uint8_t sign)
#endif
{
uint8_t digit, buf[11], *p;
#if defined(USE_HACKER_DELIGHT_OPTIMIZATION)
@@ -360,7 +290,7 @@ void Print::printNumberDec(unsigned long n, uint8_t sign)
#ifdef USE_BENCHMARK_CODE
uint32_t usec = micros();
#endif
p = buf + (sizeof(buf)-1);
p = buf + (sizeof(buf));
do {
#if defined(USE_HACKER_DELIGHT_OPTIMIZATION)
divmod10_asm(n, tmp32, digit);
@@ -377,66 +307,42 @@ void Print::printNumberDec(unsigned long n, uint8_t sign)
#ifdef USE_BENCHMARK_CODE
usec_print += micros() - usec;
#endif
#if ARDUINO >= 100
return write(p, sizeof(buf)-1 - (p - buf));
#else
write(p, sizeof(buf)-1 - (p - buf));
#endif
return write(p, sizeof(buf) - (p - buf));
}

#if ARDUINO >= 100
size_t Print::printNumberHex(unsigned long n)
#else
void Print::printNumberHex(unsigned long n)
#endif
{
uint8_t digit, buf[8], *p;

p = buf + (sizeof(buf)-1);
p = buf + (sizeof(buf));
do {
digit = n & 15;
*--p = (digit < 10) ? '0' + digit : 'A' + digit - 10;
n >>= 4;
} while (n);
#if ARDUINO >= 100
return write(p, sizeof(buf)-1 - (p - buf));
#else
write(p, sizeof(buf)-1 - (p - buf));
#endif
return write(p, sizeof(buf) - (p - buf));
}

#if ARDUINO >= 100
size_t Print::printNumberBin(unsigned long n)
#else
void Print::printNumberBin(unsigned long n)
#endif
{
uint8_t buf[32], *p;

p = buf + (sizeof(buf)-1);
p = buf + (sizeof(buf));
do {
*--p = '0' + ((uint8_t)n & 1);
n >>= 1;
} while (n);
#if ARDUINO >= 100
return write(p, sizeof(buf)-1 - (p - buf));
#else
write(p, sizeof(buf)-1 - (p - buf));
#endif
return write(p, sizeof(buf) - (p - buf));
}

#if ARDUINO >= 100
size_t Print::printNumberAny(unsigned long n, uint8_t base)
#else
void Print::printNumberAny(unsigned long n, uint8_t base)
#endif
{
uint8_t digit, buf[21], *p;
uint32_t tmp;
//uint32_t usec;

//usec = micros();
p = buf + (sizeof(buf)-1);
p = buf + sizeof(buf);
do {
tmp = n;
n = n / base;
@@ -444,26 +350,13 @@ void Print::printNumberAny(unsigned long n, uint8_t base)
*--p = (digit < 10) ? '0' + digit : 'A' + digit - 10;
} while (n);
//usec_print += micros() - usec;
#if ARDUINO >= 100
return write(p, sizeof(buf)-1 - (p - buf));
#else
write(p, sizeof(buf)-1 - (p - buf));
#endif
return write(p, sizeof(buf) - (p - buf));
}




#if ARDUINO >= 100
size_t Print::printFloat(double number, uint8_t digits)
#else
void Print::printFloat(double number, uint8_t digits)
#endif
{
uint8_t sign=0;
#if ARDUINO >= 100
size_t count=0;
#endif

// Handle negative numbers
if (number < 0.0) {
@@ -481,11 +374,7 @@ void Print::printFloat(double number, uint8_t digits)
// Extract the integer part of the number and print it
unsigned long int_part = (unsigned long)number;
double remainder = number - (double)int_part;
#if ARDUINO >= 100
count += printNumber(int_part, sign, 10);
#else
printNumber(int_part, sign, 10);
#endif

// Print the decimal point, but only if there are digits beyond
if (digits > 0) {
@@ -501,15 +390,8 @@ void Print::printFloat(double number, uint8_t digits)
buf[count++] = '0' + n;
remainder -= n;
}
#if ARDUINO >= 100
count += write(buf, count);
#else
write(buf, count);
#endif
}
#if ARDUINO >= 100
return count;
#endif
}



+ 10
- 63
teensy/Print.h 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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
- 1
teensy/WString.cpp 查看文件

@@ -66,7 +66,9 @@ String::String(char c)
String::String(unsigned char c)
{
init();
*this = (char)c;
char buf[4];
utoa(c, buf, 10);
*this = buf;
}

String::String(const int value, unsigned char base)

+ 219
- 1
teensy/core_pins.h 查看文件

@@ -1136,6 +1136,217 @@ static inline void digitalWrite(uint8_t pin, uint8_t val)
}
}

static inline void digitalWriteFast(uint8_t, uint8_t) __attribute__((always_inline, unused));
static inline void digitalWriteFast(uint8_t pin, uint8_t val)
{
if (__builtin_constant_p(pin)) {
if (val) {
if (pin == 0) {
CORE_PIN0_PORTREG |= CORE_PIN0_BITMASK;
} else if (pin == 1) {
CORE_PIN1_PORTREG |= CORE_PIN1_BITMASK;
} else if (pin == 2) {
CORE_PIN2_PORTREG |= CORE_PIN2_BITMASK;
} else if (pin == 3) {
CORE_PIN3_PORTREG |= CORE_PIN3_BITMASK;
} else if (pin == 4) {
CORE_PIN4_PORTREG |= CORE_PIN4_BITMASK;
} else if (pin == 5) {
CORE_PIN5_PORTREG |= CORE_PIN5_BITMASK;
} else if (pin == 6) {
CORE_PIN6_PORTREG |= CORE_PIN6_BITMASK;
} else if (pin == 7) {
CORE_PIN7_PORTREG |= CORE_PIN7_BITMASK;
} else if (pin == 8) {
CORE_PIN8_PORTREG |= CORE_PIN8_BITMASK;
} else if (pin == 9) {
CORE_PIN9_PORTREG |= CORE_PIN9_BITMASK;
} else if (pin == 10) {
CORE_PIN10_PORTREG |= CORE_PIN10_BITMASK;
} else if (pin == 11) {
CORE_PIN11_PORTREG |= CORE_PIN11_BITMASK;
} else if (pin == 12) {
CORE_PIN12_PORTREG |= CORE_PIN12_BITMASK;
} else if (pin == 13) {
CORE_PIN13_PORTREG |= CORE_PIN13_BITMASK;
} else if (pin == 14) {
CORE_PIN14_PORTREG |= CORE_PIN14_BITMASK;
} else if (pin == 15) {
CORE_PIN15_PORTREG |= CORE_PIN15_BITMASK;
} else if (pin == 16) {
CORE_PIN16_PORTREG |= CORE_PIN16_BITMASK;
} else if (pin == 17) {
CORE_PIN17_PORTREG |= CORE_PIN17_BITMASK;
} else if (pin == 18) {
CORE_PIN18_PORTREG |= CORE_PIN18_BITMASK;
} else if (pin == 19) {
CORE_PIN19_PORTREG |= CORE_PIN19_BITMASK;
} else if (pin == 20) {
CORE_PIN20_PORTREG |= CORE_PIN20_BITMASK;
}
#if CORE_NUM_TOTAL_PINS > 21
else if (pin == 21) {
CORE_PIN21_PORTREG |= CORE_PIN21_BITMASK;
} else if (pin == 22) {
CORE_PIN22_PORTREG |= CORE_PIN22_BITMASK;
} else if (pin == 23) {
CORE_PIN23_PORTREG |= CORE_PIN23_BITMASK;
} else if (pin == 24) {
CORE_PIN24_PORTREG |= CORE_PIN24_BITMASK;
}
#endif
#if CORE_NUM_TOTAL_PINS > 25
else if (pin == 25) {
CORE_PIN25_PORTREG |= CORE_PIN25_BITMASK;
} else if (pin == 26) {
CORE_PIN26_PORTREG |= CORE_PIN26_BITMASK;
} else if (pin == 27) {
CORE_PIN27_PORTREG |= CORE_PIN27_BITMASK;
} else if (pin == 28) {
CORE_PIN28_PORTREG |= CORE_PIN28_BITMASK;
} else if (pin == 29) {
CORE_PIN29_PORTREG |= CORE_PIN29_BITMASK;
} else if (pin == 30) {
CORE_PIN30_PORTREG |= CORE_PIN30_BITMASK;
} else if (pin == 31) {
CORE_PIN31_PORTREG |= CORE_PIN31_BITMASK;
} else if (pin == 32) {
CORE_PIN32_PORTREG |= CORE_PIN32_BITMASK;
} else if (pin == 33) {
CORE_PIN33_PORTREG |= CORE_PIN33_BITMASK;
} else if (pin == 34) {
CORE_PIN34_PORTREG |= CORE_PIN34_BITMASK;
} else if (pin == 35) {
CORE_PIN35_PORTREG |= CORE_PIN35_BITMASK;
} else if (pin == 36) {
CORE_PIN36_PORTREG |= CORE_PIN36_BITMASK;
} else if (pin == 37) {
CORE_PIN37_PORTREG |= CORE_PIN37_BITMASK;
} else if (pin == 38) {
CORE_PIN38_PORTREG |= CORE_PIN38_BITMASK;
} else if (pin == 39) {
CORE_PIN39_PORTREG |= CORE_PIN39_BITMASK;
} else if (pin == 40) {
CORE_PIN40_PORTREG |= CORE_PIN40_BITMASK;
} else if (pin == 41) {
CORE_PIN41_PORTREG |= CORE_PIN41_BITMASK;
} else if (pin == 42) {
CORE_PIN42_PORTREG |= CORE_PIN42_BITMASK;
} else if (pin == 43) {
CORE_PIN43_PORTREG |= CORE_PIN43_BITMASK;
} else if (pin == 44) {
CORE_PIN44_PORTREG |= CORE_PIN44_BITMASK;
} else if (pin == 45) {
CORE_PIN45_PORTREG |= CORE_PIN45_BITMASK;
}
#endif
} else {
if (pin == 0) {
CORE_PIN0_PORTREG &= ~CORE_PIN0_BITMASK;
} else if (pin == 1) {
CORE_PIN1_PORTREG &= ~CORE_PIN1_BITMASK;
} else if (pin == 2) {
CORE_PIN2_PORTREG &= ~CORE_PIN2_BITMASK;
} else if (pin == 3) {
CORE_PIN3_PORTREG &= ~CORE_PIN3_BITMASK;
} else if (pin == 4) {
CORE_PIN4_PORTREG &= ~CORE_PIN4_BITMASK;
} else if (pin == 5) {
CORE_PIN5_PORTREG &= ~CORE_PIN5_BITMASK;
} else if (pin == 6) {
CORE_PIN6_PORTREG &= ~CORE_PIN6_BITMASK;
} else if (pin == 7) {
CORE_PIN7_PORTREG &= ~CORE_PIN7_BITMASK;
} else if (pin == 8) {
CORE_PIN8_PORTREG &= ~CORE_PIN8_BITMASK;
} else if (pin == 9) {
CORE_PIN9_PORTREG &= ~CORE_PIN9_BITMASK;
} else if (pin == 10) {
CORE_PIN10_PORTREG &= ~CORE_PIN10_BITMASK;
} else if (pin == 11) {
CORE_PIN11_PORTREG &= ~CORE_PIN11_BITMASK;
} else if (pin == 12) {
CORE_PIN12_PORTREG &= ~CORE_PIN12_BITMASK;
} else if (pin == 13) {
CORE_PIN13_PORTREG &= ~CORE_PIN13_BITMASK;
} else if (pin == 14) {
CORE_PIN14_PORTREG &= ~CORE_PIN14_BITMASK;
} else if (pin == 15) {
CORE_PIN15_PORTREG &= ~CORE_PIN15_BITMASK;
} else if (pin == 16) {
CORE_PIN16_PORTREG &= ~CORE_PIN16_BITMASK;
} else if (pin == 17) {
CORE_PIN17_PORTREG &= ~CORE_PIN17_BITMASK;
} else if (pin == 18) {
CORE_PIN18_PORTREG &= ~CORE_PIN18_BITMASK;
} else if (pin == 19) {
CORE_PIN19_PORTREG &= ~CORE_PIN19_BITMASK;
} else if (pin == 20) {
CORE_PIN20_PORTREG &= ~CORE_PIN20_BITMASK;
}
#if CORE_NUM_TOTAL_PINS > 21
else if (pin == 21) {
CORE_PIN21_PORTREG &= ~CORE_PIN21_BITMASK;
} else if (pin == 22) {
CORE_PIN22_PORTREG &= ~CORE_PIN22_BITMASK;
} else if (pin == 23) {
CORE_PIN23_PORTREG &= ~CORE_PIN23_BITMASK;
} else if (pin == 24) {
CORE_PIN24_PORTREG &= ~CORE_PIN24_BITMASK;
}
#endif
#if CORE_NUM_TOTAL_PINS > 25
else if (pin == 25) {
CORE_PIN25_PORTREG &= ~CORE_PIN25_BITMASK;
} else if (pin == 26) {
CORE_PIN26_PORTREG &= ~CORE_PIN26_BITMASK;
} else if (pin == 27) {
CORE_PIN27_PORTREG &= ~CORE_PIN27_BITMASK;
} else if (pin == 28) {
CORE_PIN28_PORTREG &= ~CORE_PIN28_BITMASK;
} else if (pin == 29) {
CORE_PIN29_PORTREG &= ~CORE_PIN29_BITMASK;
} else if (pin == 30) {
CORE_PIN30_PORTREG &= ~CORE_PIN30_BITMASK;
} else if (pin == 31) {
CORE_PIN31_PORTREG &= ~CORE_PIN31_BITMASK;
} else if (pin == 32) {
CORE_PIN32_PORTREG &= ~CORE_PIN32_BITMASK;
} else if (pin == 33) {
CORE_PIN33_PORTREG &= ~CORE_PIN33_BITMASK;
} else if (pin == 34) {
CORE_PIN34_PORTREG &= ~CORE_PIN34_BITMASK;
} else if (pin == 35) {
CORE_PIN35_PORTREG &= ~CORE_PIN35_BITMASK;
} else if (pin == 36) {
CORE_PIN36_PORTREG &= ~CORE_PIN36_BITMASK;
} else if (pin == 37) {
CORE_PIN37_PORTREG &= ~CORE_PIN37_BITMASK;
} else if (pin == 38) {
CORE_PIN38_PORTREG &= ~CORE_PIN38_BITMASK;
} else if (pin == 39) {
CORE_PIN39_PORTREG &= ~CORE_PIN39_BITMASK;
} else if (pin == 40) {
CORE_PIN40_PORTREG &= ~CORE_PIN40_BITMASK;
} else if (pin == 41) {
CORE_PIN41_PORTREG &= ~CORE_PIN41_BITMASK;
} else if (pin == 42) {
CORE_PIN42_PORTREG &= ~CORE_PIN42_BITMASK;
} else if (pin == 43) {
CORE_PIN43_PORTREG &= ~CORE_PIN43_BITMASK;
} else if (pin == 44) {
CORE_PIN44_PORTREG &= ~CORE_PIN44_BITMASK;
} else if (pin == 45) {
CORE_PIN45_PORTREG &= ~CORE_PIN45_BITMASK;
}
#endif
}
} else {
digitalWrite(pin, val);
}
}


extern void _digitalRead(void) __attribute__((noinline));

static inline uint8_t digitalRead(uint8_t) __attribute__((always_inline, unused));
@@ -1254,6 +1465,12 @@ static inline uint8_t digitalRead(uint8_t pin)
}
}

static inline uint8_t digitalReadFast(uint8_t) __attribute__((always_inline, unused));
static inline uint8_t digitalReadFast(uint8_t pin)
{
return digitalRead(pin);
}

extern void _pinMode(uint8_t pin, uint8_t mode) __attribute__((noinline));
extern void _pinMode_output(uint8_t pin) __attribute__((noinline));
extern void _pinMode_input(uint8_t pin) __attribute__((noinline));
@@ -1919,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)

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

@@ -6,7 +6,7 @@
#ifdef M
#undef M
#endif
#define M(n) ((n) & 0x3FFF)
#define M(n) ((n) & KEYCODE_MASK)

const KEYCODE_TYPE PROGMEM keycodes_ascii[] = {
M(ASCII_20), M(ASCII_21), M(ASCII_22), M(ASCII_23),

+ 575
- 207
teensy/keylayouts.h
文件差異過大導致無法顯示
查看文件


+ 2
- 0
teensy/pgmspace.h 查看文件

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

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

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

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

// This allows CapSense to work. Do any libraries
// depend on these to be zero?
@@ -148,4 +154,11 @@ static inline uint8_t digitalPinToTimer(uint8_t pin)
}
}

#define SERIAL_PORT_MONITOR Serial
#define SERIAL_PORT_USBVIRTUAL Serial
#define SERIAL_PORT_HARDWARE Serial1
#define SERIAL_PORT_HARDWARE_OPEN Serial1

#define SerialUSB Serial

#endif

+ 1
- 1
teensy/wiring.h 查看文件

@@ -87,7 +87,7 @@ 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;


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

@@ -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

+ 127
- 27
teensy3/AudioStream.cpp 查看文件

@@ -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,16 +29,32 @@
*/


#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;




@@ -47,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++) {
@@ -71,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();
@@ -107,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--;
@@ -118,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();
@@ -126,8 +151,10 @@ void AudioStream::release(audio_block_t *block)
// Transmit an audio data block
// to all streams that connect to an output. The block
// becomes owned by all the recepients, but also is still
// owned by this object. Normally, a block is released
// after it's transmitted.
// owned by this object. Normally, a block must be released
// by the caller after it's transmitted. This allows the
// caller to transmit to same block to more than 1 output,
// and then release it once after all transmit calls.
void AudioStream::transmit(audio_block_t *block, unsigned char index)
{
for (AudioConnection *c = destination_list; c != NULL; c = c->next_dest) {
@@ -176,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()
@@ -202,7 +302,7 @@ bool AudioStream::update_scheduled = false;
bool AudioStream::update_setup(void)
{
if (update_scheduled) return false;
NVIC_SET_PRIORITY(IRQ_SOFTWARE, 0xFF); // 0xFF = lowest priority
NVIC_SET_PRIORITY(IRQ_SOFTWARE, 208); // 255 = lowest priority
NVIC_ENABLE_IRQ(IRQ_SOFTWARE);
update_scheduled = true;
return true;

+ 54
- 12
teensy3/AudioStream.h 查看文件

@@ -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,19 +31,49 @@
#ifndef AudioStream_h
#define AudioStream_h

#include "Arduino.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.

#ifndef AUDIO_BLOCK_SAMPLES
#if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
#define AUDIO_BLOCK_SAMPLES 128
#define AUDIO_SAMPLE_RATE 44117.64706
#elif defined(__MKL26Z64__)
#define AUDIO_BLOCK_SAMPLES 64
#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;
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;


@@ -53,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;
};


@@ -107,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;
@@ -131,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;
@@ -139,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 查看文件

@@ -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

+ 133
- 6
teensy3/DMAChannel.cpp 查看文件

@@ -1,15 +1,59 @@
/* 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
#define DMA_MAX_CHANNELS DMA_NUM_CHANNELS
#else
#define DMA_MAX_CHANNELS 16
#endif


// The channel allocation bitmask is accessible from "C" namespace,
// so C-only code can reserve DMA channels
uint16_t dma_channel_allocated_mask = 0;



/****************************************************************/
/** Teensy 3.0 & 3.1 **/
/****************************************************************/
#if defined(KINETISK)

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
@@ -22,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
}
@@ -33,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;
@@ -52,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 = 16;
channel = DMA_MAX_CHANNELS;
TCD = (TCD_t *)0;
}

@@ -82,6 +130,85 @@ static void swap(DMAChannel &c1, DMAChannel &c2)
c2.TCD = t;
}

/****************************************************************/
/** Teensy-LC **/
/****************************************************************/
#elif defined(KINETISL)


void DMAChannel::begin(bool force_initialization)
{
uint32_t ch = 0;

__disable_irq();
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
__enable_irq();
return;
}
while (1) {
if (!(dma_channel_allocated_mask & (1 << ch))) {
dma_channel_allocated_mask |= (1 << ch);
__enable_irq();
break;
}
if (++ch >= DMA_MAX_CHANNELS) {
__enable_irq();
CFG = (CFG_t *)0;
channel = DMA_MAX_CHANNELS;
return; // no more channels available
// attempts to use this object will hardfault
}
}
channel = ch;
SIM_SCGC7 |= SIM_SCGC7_DMA;
SIM_SCGC6 |= SIM_SCGC6_DMAMUX;
CFG = (CFG_t *)(0x40008100 + ch * 16);
CFG->DSR_BCR = DMA_DSR_BCR_DONE;
CFG->DCR = DMA_DCR_CS;
CFG->SAR = NULL;
CFG->DAR = NULL;
}

void DMAChannel::release(void)
{
if (channel >= DMA_MAX_CHANNELS) return;
CFG->DSR_BCR = DMA_DSR_BCR_DONE;
__disable_irq();
dma_channel_allocated_mask &= ~(1 << channel);
__enable_irq();
channel = 16;
CFG = (CFG_t *)0;
}

static uint32_t priority(const DMAChannel &c)
{
return 3 - c.channel;
}

static void swap(DMAChannel &c1, DMAChannel &c2)
{
uint8_t c;
DMABaseClass::CFG_t *t;

c = c1.channel;
c1.channel = c2.channel;
c2.channel = c;
t = c1.CFG;
c1.CFG = c2.CFG;
c2.CFG = t;
}




#endif




void DMAPriorityOrder(DMAChannel &ch1, DMAChannel &ch2)
{
if (priority(ch1) < priority(ch2)) swap(ch1, ch2);

+ 562
- 270
teensy3/DMAChannel.h 查看文件

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

#ifndef DMAChannel_h_
#define DMAChannel_h_

#include "kinetis.h"

// This code is a work-in-progress. It's incomplete and not usable yet...
//
// Discussion about DMAChannel is here:
// http://forum.pjrc.com/threads/25778-Could-there-be-something-like-an-ISR-template-function/page3

#define DMACHANNEL_HAS_BEGIN
#define DMACHANNEL_HAS_BOOLEAN_CTOR


// The channel allocation bitmask is accessible from "C" namespace,
// so C-only code can reserve DMA channels
#ifdef __cplusplus
extern "C" {
#endif
extern uint16_t dma_channel_allocated_mask;
#ifdef __cplusplus
}
#endif


#ifdef __cplusplus

// known libraries with DMA usage (in need of porting to this new scheme):
//
@@ -17,14 +62,16 @@
// https://github.com/pixelmatix/SmartMatrix
// https://github.com/crteensy/DmaSpi <-- DmaSpi has adopted this scheme

#ifdef __cplusplus

#define DMACHANNEL_HAS_BEGIN
#define DMACHANNEL_HAS_BOOLEAN_CTOR
/****************************************************************/
/** Teensy 3.0 & 3.1 **/
/****************************************************************/
#if defined(KINETISK)


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;
@@ -269,7 +316,12 @@ public:

// Set the data size used for each triggered transfer
void transferSize(unsigned int len) {
if (len == 4) {
if (len == 16) {
TCD->NBYTES = 16;
if (TCD->SOFF != 0) TCD->SOFF = 16;
if (TCD->DOFF != 0) TCD->DOFF = 16;
TCD->ATTR = (TCD->ATTR & 0xF8F8) | 0x0404;
} else if (len == 4) {
TCD->NBYTES = 4;
if (TCD->SOFF != 0) TCD->SOFF = 4;
if (TCD->DOFF != 0) TCD->DOFF = 4;
@@ -289,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;
}
@@ -536,263 +589,504 @@ public:
// code, but direct control of all parameters is possible.
uint8_t channel;
// TCD is accessible due to inheritance from DMABaseClass
};

// arrange the relative priority of 2 or more DMA channels
void DMAPriorityOrder(DMAChannel &ch1, DMAChannel &ch2);
void DMAPriorityOrder(DMAChannel &ch1, DMAChannel &ch2, DMAChannel &ch3);
void DMAPriorityOrder(DMAChannel &ch1, DMAChannel &ch2, DMAChannel &ch3, DMAChannel &ch4);

















/****************************************************************/
/** Teensy-LC **/
/****************************************************************/
#elif defined(KINETISL)


class DMABaseClass {
public:
typedef struct __attribute__((packed, aligned(4))) {
volatile const void * volatile SAR;
volatile void * volatile DAR;
volatile uint32_t DSR_BCR;
volatile uint32_t DCR;
} CFG_t;
CFG_t *CFG;

/***************************************/
/** Data Transfer **/
/***************************************/

// Use a single variable as the data source. Typically a register
// for receiving data from one of the hardware peripherals is used.
void source(volatile const signed char &p) { source(*(volatile const uint8_t *)&p); }
void source(volatile const unsigned char &p) {
CFG->SAR = &p;
CFG->DCR = (CFG->DCR & 0xF08E0FFF) | DMA_DCR_SSIZE(1);
}
void source(volatile const signed short &p) { source(*(volatile const uint16_t *)&p); }
void source(volatile const unsigned short &p) {
CFG->SAR = &p;
CFG->DCR = (CFG->DCR & 0xF08E0FFF) | DMA_DCR_SSIZE(2);
}
void source(volatile const signed int &p) { source(*(volatile const uint32_t *)&p); }
void source(volatile const unsigned int &p) { source(*(volatile const uint32_t *)&p); }
void source(volatile const signed long &p) { source(*(volatile const uint32_t *)&p); }
void source(volatile const unsigned long &p) {
CFG->SAR = &p;
CFG->DCR = (CFG->DCR & 0xF08E0FFF) | DMA_DCR_SSIZE(0);
}

// Use a buffer (array of data) as the data source. Typically a
// buffer for transmitting data is used.
void sourceBuffer(volatile const signed char p[], unsigned int len) {
sourceBuffer((volatile const uint8_t *)p, len); }
void sourceBuffer(volatile const unsigned char p[], unsigned int len) {
if (len > 0xFFFFF) return;
CFG->SAR = p;
CFG->DCR = (CFG->DCR & 0xF08E0FFF) | DMA_DCR_SSIZE(1) | DMA_DCR_SINC;
CFG->DSR_BCR = len;
}
void sourceBuffer(volatile const signed short p[], unsigned int len) {
sourceBuffer((volatile const uint16_t *)p, len); }
void sourceBuffer(volatile const unsigned short p[], unsigned int len) {
if (len > 0xFFFFF) return;
CFG->SAR = p;
CFG->DCR = (CFG->DCR & 0xF08E0FFF) | DMA_DCR_SSIZE(2) | DMA_DCR_SINC;
CFG->DSR_BCR = len;
}
void sourceBuffer(volatile const signed int p[], unsigned int len) {
sourceBuffer((volatile const uint32_t *)p, len); }
void sourceBuffer(volatile const unsigned int p[], unsigned int len) {
sourceBuffer((volatile const uint32_t *)p, len); }
void sourceBuffer(volatile const signed long p[], unsigned int len) {
sourceBuffer((volatile const uint32_t *)p, len); }
void sourceBuffer(volatile const unsigned long p[], unsigned int len) {
if (len > 0xFFFFF) return;
CFG->SAR = p;
CFG->DCR = (CFG->DCR & 0xF08E0FFF) | DMA_DCR_SSIZE(0) | DMA_DCR_SINC;
CFG->DSR_BCR = len;
}

// Use a circular buffer as the data source
void sourceCircular(volatile const signed char p[], unsigned int len) {
sourceCircular((volatile const uint8_t *)p, len); }
void sourceCircular(volatile const unsigned char p[], unsigned int len) {
uint32_t mod = len2mod(len);
if (mod == 0) return;
CFG->SAR = p;
CFG->DCR = (CFG->DCR & 0xF08E0FFF) | DMA_DCR_SSIZE(1) | DMA_DCR_SINC
| DMA_DCR_SMOD(mod);
CFG->DSR_BCR = len;
}
void sourceCircular(volatile const signed short p[], unsigned int len) {
sourceCircular((volatile const uint16_t *)p, len); }
void sourceCircular(volatile const unsigned short p[], unsigned int len) {
uint32_t mod = len2mod(len);
if (mod == 0) return;
CFG->SAR = p;
CFG->DCR = (CFG->DCR & 0xF08E0FFF) | DMA_DCR_SSIZE(2) | DMA_DCR_SINC
| DMA_DCR_SMOD(mod);
CFG->DSR_BCR = len;
}
void sourceCircular(volatile const signed int p[], unsigned int len) {
sourceCircular((volatile const uint32_t *)p, len); }
void sourceCircular(volatile const unsigned int p[], unsigned int len) {
sourceCircular((volatile const uint32_t *)p, len); }
void sourceCircular(volatile const signed long p[], unsigned int len) {
sourceCircular((volatile const uint32_t *)p, len); }
void sourceCircular(volatile const unsigned long p[], unsigned int len) {
uint32_t mod = len2mod(len);
if (mod == 0) return;
CFG->SAR = p;
CFG->DCR = (CFG->DCR & 0xF08E0FFF) | DMA_DCR_SSIZE(0) | DMA_DCR_SINC
| DMA_DCR_SMOD(mod);
CFG->DSR_BCR = len;
}

// Use a single variable as the data destination. Typically a register
// for transmitting data to one of the hardware peripherals is used.
void destination(volatile signed char &p) { destination(*(volatile uint8_t *)&p); }
void destination(volatile unsigned char &p) {
CFG->DAR = &p;
CFG->DCR = (CFG->DCR & 0xF0F0F0FF) | DMA_DCR_DSIZE(1);
}
void destination(volatile signed short &p) { destination(*(volatile uint16_t *)&p); }
void destination(volatile unsigned short &p) {
CFG->DAR = &p;
CFG->DCR = (CFG->DCR & 0xF0F0F0FF) | DMA_DCR_DSIZE(2);
}
void destination(volatile signed int &p) { destination(*(volatile uint32_t *)&p); }
void destination(volatile unsigned int &p) { destination(*(volatile uint32_t *)&p); }
void destination(volatile signed long &p) { destination(*(volatile uint32_t *)&p); }
void destination(volatile unsigned long &p) {
CFG->DAR = &p;
CFG->DCR = (CFG->DCR & 0xF0F0F0FF) | DMA_DCR_DSIZE(0);
}

// Use a buffer (array of data) as the data destination. Typically a
// buffer for receiving data is used.
void destinationBuffer(volatile signed char p[], unsigned int len) {
destinationBuffer((volatile uint8_t *)p, len); }
void destinationBuffer(volatile unsigned char p[], unsigned int len) {
CFG->DAR = p;
CFG->DCR = (CFG->DCR & 0xF0F0F0FF) | DMA_DCR_DSIZE(1) | DMA_DCR_DINC;
CFG->DSR_BCR = len;
}
void destinationBuffer(volatile signed short p[], unsigned int len) {
destinationBuffer((volatile uint16_t *)p, len); }
void destinationBuffer(volatile unsigned short p[], unsigned int len) {
CFG->DAR = p;
CFG->DCR = (CFG->DCR & 0xF0F0F0FF) | DMA_DCR_DSIZE(2) | DMA_DCR_DINC;
CFG->DSR_BCR = len;
}
void destinationBuffer(volatile signed int p[], unsigned int len) {
destinationBuffer((volatile uint32_t *)p, len); }
void destinationBuffer(volatile unsigned int p[], unsigned int len) {
destinationBuffer((volatile uint32_t *)p, len); }
void destinationBuffer(volatile signed long p[], unsigned int len) {
destinationBuffer((volatile uint32_t *)p, len); }
void destinationBuffer(volatile unsigned long p[], unsigned int len) {
CFG->DAR = p;
CFG->DCR = (CFG->DCR & 0xF0F0F0FF) | DMA_DCR_DSIZE(0) | DMA_DCR_DINC;
CFG->DSR_BCR = len;
}

// Use a circular buffer as the data destination
void destinationCircular(volatile signed char p[], unsigned int len) {
destinationCircular((volatile uint8_t *)p, len); }
void destinationCircular(volatile unsigned char p[], unsigned int len) {
uint32_t mod = len2mod(len);
if (mod == 0) return;
CFG->DAR = p;
CFG->DCR = (CFG->DCR & 0xF0F0F0FF) | DMA_DCR_DSIZE(1) | DMA_DCR_DINC
| DMA_DCR_DMOD(mod);
CFG->DSR_BCR = len;
}
void destinationCircular(volatile signed short p[], unsigned int len) {
destinationCircular((volatile uint16_t *)p, len); }
void destinationCircular(volatile unsigned short p[], unsigned int len) {
uint32_t mod = len2mod(len);
if (mod == 0) return;
CFG->DAR = p;
CFG->DCR = (CFG->DCR & 0xF0F0F0FF) | DMA_DCR_DSIZE(2) | DMA_DCR_DINC
| DMA_DCR_DMOD(mod);
CFG->DSR_BCR = len;
}
void destinationCircular(volatile signed int p[], unsigned int len) {
destinationCircular((volatile uint32_t *)p, len); }
void destinationCircular(volatile unsigned int p[], unsigned int len) {
destinationCircular((volatile uint32_t *)p, len); }
void destinationCircular(volatile signed long p[], unsigned int len) {
destinationCircular((volatile uint32_t *)p, len); }
void destinationCircular(volatile unsigned long p[], unsigned int len) {
uint32_t mod = len2mod(len);
if (mod == 0) return;
CFG->DAR = p;
CFG->DCR = (CFG->DCR & 0xF0F0F0FF) | DMA_DCR_DSIZE(0) | DMA_DCR_DINC
| DMA_DCR_DMOD(mod);
CFG->DSR_BCR = len;
}

/* usage cases:

************************
OctoWS2811:
************************

// enable clocks to the DMA controller and DMAMUX
SIM_SCGC7 |= SIM_SCGC7_DMA;
SIM_SCGC6 |= SIM_SCGC6_DMAMUX;
DMA_CR = 0;
DMA_CERQ = 1;
DMA_CERQ = 2;
DMA_CERQ = 3;

// DMA channel #1 sets WS2811 high at the beginning of each cycle
DMA_TCD1_SADDR = &ones;
DMA_TCD1_SOFF = 0;
DMA_TCD1_ATTR = DMA_TCD_ATTR_SSIZE(0) | DMA_TCD_ATTR_DSIZE(0);
DMA_TCD1_NBYTES_MLNO = 1;
DMA_TCD1_SLAST = 0;
DMA_TCD1_DADDR = &GPIOD_PSOR;
DMA_TCD1_DOFF = 0;
DMA_TCD1_CITER_ELINKNO = bufsize;
DMA_TCD1_DLASTSGA = 0;
DMA_TCD1_CSR = DMA_TCD_CSR_DREQ;
DMA_TCD1_BITER_ELINKNO = bufsize;
dma1.source(ones);
dma1.destination(GPIOD_PSOR);
dma1.size(1);
dma1.count(bufsize);
dma1.disableOnCompletion();

// DMA channel #2 writes the pixel data at 20% of the cycle
DMA_TCD2_SADDR = frameBuffer;
DMA_TCD2_SOFF = 1;
DMA_TCD2_ATTR = DMA_TCD_ATTR_SSIZE(0) | DMA_TCD_ATTR_DSIZE(0);
DMA_TCD2_NBYTES_MLNO = 1;
DMA_TCD2_SLAST = -bufsize;
DMA_TCD2_DADDR = &GPIOD_PDOR;
DMA_TCD2_DOFF = 0;
DMA_TCD2_CITER_ELINKNO = bufsize;
DMA_TCD2_DLASTSGA = 0;
DMA_TCD2_CSR = DMA_TCD_CSR_DREQ;
DMA_TCD2_BITER_ELINKNO = bufsize;
dma2.source(frameBuffer, sizeof(frameBuffer));
dma2.destination(GPIOD_PDOR);
dma2.size(1);
dma2.count(bufsize);
dma2.disableOnCompletion();

// DMA channel #3 clear all the pins low at 48% of the cycle
DMA_TCD3_SADDR = &ones;
DMA_TCD3_SOFF = 0;
DMA_TCD3_ATTR = DMA_TCD_ATTR_SSIZE(0) | DMA_TCD_ATTR_DSIZE(0);
DMA_TCD3_NBYTES_MLNO = 1;
DMA_TCD3_SLAST = 0;
DMA_TCD3_DADDR = &GPIOD_PCOR;
DMA_TCD3_DOFF = 0;
DMA_TCD3_CITER_ELINKNO = bufsize;
DMA_TCD3_DLASTSGA = 0;
DMA_TCD3_CSR = DMA_TCD_CSR_DREQ | DMA_TCD_CSR_INTMAJOR;
DMA_TCD3_BITER_ELINKNO = bufsize;
dma3.source(ones);
dma3.destination(GPIOD_PCOR);
dma3.size(1);
dma3.count(bufsize);
dma3.disableOnCompletion();

************************
Audio, DAC
************************

DMA_CR = 0;
DMA_TCD4_SADDR = dac_buffer;
DMA_TCD4_SOFF = 2;
DMA_TCD4_ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
DMA_TCD4_NBYTES_MLNO = 2;
DMA_TCD4_SLAST = -sizeof(dac_buffer);
DMA_TCD4_DADDR = &DAC0_DAT0L;
DMA_TCD4_DOFF = 0;
DMA_TCD4_CITER_ELINKNO = sizeof(dac_buffer) / 2;
DMA_TCD4_DLASTSGA = 0;
DMA_TCD4_BITER_ELINKNO = sizeof(dac_buffer) / 2;
DMA_TCD4_CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
DMAMUX0_CHCFG4 = DMAMUX_DISABLE;
DMAMUX0_CHCFG4 = DMAMUX_SOURCE_PDB | DMAMUX_ENABLE;

************************
Audio, I2S
************************

DMA_CR = 0;
DMA_TCD0_SADDR = i2s_tx_buffer;
DMA_TCD0_SOFF = 2;
DMA_TCD0_ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
DMA_TCD0_NBYTES_MLNO = 2;
DMA_TCD0_SLAST = -sizeof(i2s_tx_buffer);
DMA_TCD0_DADDR = &I2S0_TDR0;
DMA_TCD0_DOFF = 0;
DMA_TCD0_CITER_ELINKNO = sizeof(i2s_tx_buffer) / 2;
DMA_TCD0_DLASTSGA = 0;
DMA_TCD0_BITER_ELINKNO = sizeof(i2s_tx_buffer) / 2;
DMA_TCD0_CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;

DMAMUX0_CHCFG0 = DMAMUX_DISABLE;
DMAMUX0_CHCFG0 = DMAMUX_SOURCE_I2S0_TX | DMAMUX_ENABLE;

************************
ADC lib, Pedro Villanueva
************************

DMA_CR = 0; // normal mode of operation

*DMAMUX0_CHCFG = DMAMUX_DISABLE; // disable before changing

*DMA_TCD_ATTR = DMA_TCD_ATTR_SSIZE(DMA_TCD_ATTR_SIZE_16BIT) |
DMA_TCD_ATTR_DSIZE(DMA_TCD_ATTR_SIZE_16BIT) |
DMA_TCD_ATTR_DMOD(4); // src and dst data is 16 bit (2 bytes), buffer size 2^^4 bytes = 8 values
*DMA_TCD_NBYTES_MLNO = 2; // Minor Byte Transfer Count 2 bytes = 16 bits (we transfer 2 bytes each minor loop)

*DMA_TCD_SADDR = ADC_RA; // source address
*DMA_TCD_SOFF = 0; // don't change the address when minor loop finishes
*DMA_TCD_SLAST = 0; // don't change src address after major loop completes

*DMA_TCD_DADDR = elems; // destination address
*DMA_TCD_DOFF = 2; // increment 2 bytes each minor loop
*DMA_TCD_DLASTSGA = 0; // modulus feature takes care of going back to first element

*DMA_TCD_CITER_ELINKNO = 1; // Current Major Iteration Count with channel linking disabled
*DMA_TCD_BITER_ELINKNO = 1; // Starting Major Iteration Count with channel linking disabled

*DMA_TCD_CSR = DMA_TCD_CSR_INTMAJOR; // Control and status: interrupt when major counter is complete

DMA_CERQ = DMA_CERQ_CERQ(DMA_channel); // clear all past request
DMA_CINT = DMA_channel; // clear interrupts

uint8_t DMAMUX_SOURCE_ADC = DMAMUX_SOURCE_ADC0;
if(ADC_number==1){
DMAMUX_SOURCE_ADC = DMAMUX_SOURCE_ADC1;
}
*DMAMUX0_CHCFG = DMAMUX_SOURCE_ADC | DMAMUX_ENABLE; // enable mux and set channel DMA_channel to ADC0

DMA_SERQ = DMA_SERQ_SERQ(DMA_channel); // enable DMA request
NVIC_ENABLE_IRQ(IRQ_DMA_CH); // enable interrupts

************************
SmartMatrix
************************

// enable minor loop mapping so addresses can get reset after minor loops
DMA_CR = 1 << 7;

// DMA channel #0 - on latch rising edge, read address from fixed address temporary buffer, and output address on GPIO
// using combo of writes to set+clear registers, to only modify the address pins and not other GPIO pins
// address temporary buffer is refreshed before each DMA trigger (by DMA channel #2)
// only use single major loop, never disable channel
#define ADDRESS_ARRAY_REGISTERS_TO_UPDATE 2
DMA_TCD0_SADDR = &gpiosync.gpio_pcor;
DMA_TCD0_SOFF = (int)&gpiosync.gpio_psor - (int)&gpiosync.gpio_pcor;
DMA_TCD0_SLAST = (ADDRESS_ARRAY_REGISTERS_TO_UPDATE * ((int)&ADDX_GPIO_CLEAR_REGISTER - (int)&ADDX_GPIO_SET_REGISTER));
DMA_TCD0_ATTR = DMA_TCD_ATTR_SSIZE(2) | DMA_TCD_ATTR_DSIZE(2);
// Destination Minor Loop Offset Enabled - transfer appropriate number of bytes per minor loop, and put DADDR back to original value when minor loop is complete
// Source Minor Loop Offset Enabled - source buffer is same size and offset as destination so values reset after each minor loop
DMA_TCD0_NBYTES_MLOFFYES = DMA_TCD_NBYTES_SMLOE | DMA_TCD_NBYTES_DMLOE |
((ADDRESS_ARRAY_REGISTERS_TO_UPDATE * ((int)&ADDX_GPIO_CLEAR_REGISTER - (int)&ADDX_GPIO_SET_REGISTER)) << 10) |
(ADDRESS_ARRAY_REGISTERS_TO_UPDATE * sizeof(gpiosync.gpio_psor));
// start on higher value of two registers, and make offset decrement to avoid negative number in NBYTES_MLOFFYES (TODO: can switch order by masking negative offset)
DMA_TCD0_DADDR = &ADDX_GPIO_CLEAR_REGISTER;
// update destination address so the second update per minor loop is ADDX_GPIO_SET_REGISTER
DMA_TCD0_DOFF = (int)&ADDX_GPIO_SET_REGISTER - (int)&ADDX_GPIO_CLEAR_REGISTER;
DMA_TCD0_DLASTSGA = (ADDRESS_ARRAY_REGISTERS_TO_UPDATE * ((int)&ADDX_GPIO_CLEAR_REGISTER - (int)&ADDX_GPIO_SET_REGISTER));
// single major loop
DMA_TCD0_CITER_ELINKNO = 1;
DMA_TCD0_BITER_ELINKNO = 1;
// link channel 1, enable major channel-to-channel linking, don't clear enable on major loop complete
DMA_TCD0_CSR = (1 << 8) | (1 << 5);
DMAMUX0_CHCFG0 = DMAMUX_SOURCE_LATCH_RISING_EDGE | DMAMUX_ENABLE;

// DMA channel #1 - copy address values from current position in array to buffer to temporarily hold row values for the next timer cycle
// only use single major loop, never disable channel
DMA_TCD1_SADDR = &matrixUpdateBlocks[0][0].addressValues;
DMA_TCD1_SOFF = sizeof(uint16_t);
DMA_TCD1_SLAST = sizeof(matrixUpdateBlock) - (ADDRESS_ARRAY_REGISTERS_TO_UPDATE * sizeof(uint16_t));
DMA_TCD1_ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
// 16-bit = 2 bytes transferred
// transfer two 16-bit values, reset destination address back after each minor loop
DMA_TCD1_NBYTES_MLOFFNO = (ADDRESS_ARRAY_REGISTERS_TO_UPDATE * sizeof(uint16_t));
// start with the register that's the highest location in memory and make offset decrement to avoid negative number in NBYTES_MLOFFYES register (TODO: can switch order by masking negative offset)
DMA_TCD1_DADDR = &gpiosync.gpio_pcor;
DMA_TCD1_DOFF = (int)&gpiosync.gpio_psor - (int)&gpiosync.gpio_pcor;
DMA_TCD1_DLASTSGA = (ADDRESS_ARRAY_REGISTERS_TO_UPDATE * ((int)&gpiosync.gpio_pcor - (int)&gpiosync.gpio_psor));
// no minor loop linking, single major loop, single minor loop, don't clear enable after major loop complete
DMA_TCD1_CITER_ELINKNO = 1;
DMA_TCD1_BITER_ELINKNO = 1;
DMA_TCD1_CSR = 0;

// DMA channel #2 - on latch falling edge, load FTM1_CV1 and FTM1_MOD with with next values from current block
// only use single major loop, never disable channel
// link to channel 3 when complete
#define TIMER_REGISTERS_TO_UPDATE 2
DMA_TCD2_SADDR = &matrixUpdateBlocks[0][0].timerValues.timer_oe;
DMA_TCD2_SOFF = sizeof(uint16_t);
DMA_TCD2_SLAST = sizeof(matrixUpdateBlock) - (TIMER_REGISTERS_TO_UPDATE * sizeof(uint16_t));
DMA_TCD2_ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1);
// 16-bit = 2 bytes transferred
DMA_TCD2_NBYTES_MLOFFNO = TIMER_REGISTERS_TO_UPDATE * sizeof(uint16_t);
DMA_TCD2_DADDR = &FTM1_C1V;
DMA_TCD2_DOFF = (int)&FTM1_MOD - (int)&FTM1_C1V;
DMA_TCD2_DLASTSGA = TIMER_REGISTERS_TO_UPDATE * ((int)&FTM1_C1V - (int)&FTM1_MOD);
// no minor loop linking, single major loop
DMA_TCD2_CITER_ELINKNO = 1;
DMA_TCD2_BITER_ELINKNO = 1;
// link channel 3, enable major channel-to-channel linking, don't clear enable after major loop complete
DMA_TCD2_CSR = (3 << 8) | (1 << 5);
DMAMUX0_CHCFG2 = DMAMUX_SOURCE_LATCH_FALLING_EDGE | DMAMUX_ENABLE;

#define DMA_TCD_MLOFF_MASK (0x3FFFFC00)

// DMA channel #3 - repeatedly load gpio_array into GPIOD_PDOR, stop and int on major loop complete
DMA_TCD3_SADDR = matrixUpdateData[0][0];
DMA_TCD3_SOFF = sizeof(matrixUpdateData[0][0]) / 2;
// SADDR will get updated by ISR, no need to set SLAST
DMA_TCD3_SLAST = 0;
DMA_TCD3_ATTR = DMA_TCD_ATTR_SSIZE(0) | DMA_TCD_ATTR_DSIZE(0);
// after each minor loop, set source to point back to the beginning of this set of data,
// but advance by 1 byte to get the next significant bits data
DMA_TCD3_NBYTES_MLOFFYES = DMA_TCD_NBYTES_SMLOE |
(((1 - sizeof(matrixUpdateData[0])) << 10) & DMA_TCD_MLOFF_MASK) |
(MATRIX_WIDTH * DMA_UPDATES_PER_CLOCK);
DMA_TCD3_DADDR = &GPIOD_PDOR;
DMA_TCD3_DOFF = 0;
DMA_TCD3_DLASTSGA = 0;
DMA_TCD3_CITER_ELINKNO = LATCHES_PER_ROW;
DMA_TCD3_BITER_ELINKNO = LATCHES_PER_ROW;
// int after major loop is complete
DMA_TCD3_CSR = DMA_TCD_CSR_INTMAJOR;
// for debugging - enable bandwidth control (space out GPIO updates so they can be seen easier on a low-bandwidth logic analyzer)
//DMA_TCD3_CSR |= (0x02 << 14);

// enable a done interrupt when all DMA operations are complete
NVIC_ENABLE_IRQ(IRQ_DMA_CH3);

// enable additional dma interrupt used as software interrupt
NVIC_SET_PRIORITY(IRQ_DMA_CH1, 0xFF); // 0xFF = lowest priority
NVIC_ENABLE_IRQ(IRQ_DMA_CH1);

// enable channels 0, 1, 2, 3
DMA_ERQ = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);

// at the end after everything is set up: enable timer from system clock, with appropriate prescale
FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(LATCH_TIMER_PRESCALE);


*/
/*************************************************/
/** Quantity of Data to Transfer **/
/*************************************************/

// Set the data size used for each triggered transfer
void transferSize(unsigned int len) {
uint32_t dcr = CFG->DCR & 0xF0C8FFFF;
if (len == 4) {
CFG->DCR = dcr | DMA_DCR_SSIZE(0) | DMA_DCR_DSIZE(0);
} else if (len == 2) {
CFG->DCR = dcr | DMA_DCR_SSIZE(2) | DMA_DCR_DSIZE(2);
} else {
CFG->DCR = dcr | DMA_DCR_SSIZE(1) | DMA_DCR_DSIZE(1);
}
}

// Set the number of transfers (number of triggers until complete)
void transferCount(unsigned int len) {
uint32_t s, d, n = 0; // 0 = 8 bit, 1 = 16 bit, 2 = 32 bit
uint32_t dcr = CFG->DCR;
s = (dcr >> 20) & 3;
d = (dcr >> 17) & 3;
if (s == 0 || d == 0) n = 2;
else if (s == 2 || d == 2) n = 1;
CFG->DSR_BCR = len << n;
}

/*************************************************/
/** Special Options / Features **/
/*************************************************/

void interruptAtCompletion(void) {
CFG->DCR |= DMA_DCR_EINT;
}

void disableOnCompletion(void) {
CFG->DCR |= DMA_DCR_D_REQ;
}

// Kinetis-L DMA does not have these features :-(
//
// void interruptAtHalf(void) {}
// void replaceSettingsOnCompletion(const DMABaseClass &settings) {};
// TODO: can a 2nd linked channel be used to emulate this?

protected:
// users should not be able to create instances of DMABaseClass, which
// require the inheriting class to initialize the TCD pointer.
DMABaseClass() {}

static inline void copy_cfg(CFG_t *dst, const CFG_t *src) {
dst->SAR = src->SAR;
dst->DAR = src->DAR;
dst->DSR_BCR = src->DSR_BCR;
dst->DCR = src->DCR;
}
private:
static inline uint32_t len2mod(uint32_t len) {
if (len < 16) return 0;
if (len < 32) return 1;
if (len < 64) return 2;
if (len < 128) return 3;
if (len < 256) return 4;
if (len < 512) return 5;
if (len < 1024) return 6;
if (len < 2048) return 7;
if (len < 4096) return 8;
if (len < 8192) return 9;
if (len < 16384) return 10;
if (len < 32768) return 11;
if (len < 65536) return 12;
if (len < 131072) return 13;
if (len < 262144) return 14;
return 15;
}
};


// DMASetting represents settings stored only in memory, which can be
// applied to any DMA channel.

class DMASetting : public DMABaseClass {
public:
DMASetting() {
cfgdata.SAR = NULL;
cfgdata.DAR = NULL;
cfgdata.DSR_BCR = 0;
cfgdata.DCR = DMA_DCR_CS;
CFG = &cfgdata;
}
DMASetting(const DMASetting &c) {
CFG = &cfgdata;
*this = c;
}
DMASetting(const DMABaseClass &c) {
CFG = &cfgdata;
*this = c;
}
DMASetting & operator = (const DMABaseClass &rhs) {
copy_cfg(CFG, rhs.CFG);
return *this;
}
private:
CFG_t cfgdata __attribute__((aligned(4)));
};


// DMAChannel reprents an actual DMA channel and its current settings

class DMAChannel : public DMABaseClass {
public:
/*************************************************/
/** Channel Allocation **/
/*************************************************/

DMAChannel() {
begin();
}
DMAChannel(const DMAChannel &c) {
CFG = c.CFG;
channel = c.channel;
}
DMAChannel(const DMASetting &c) {
begin();
copy_cfg(CFG, c.CFG);
}
DMAChannel(bool allocate) {
if (allocate) begin();
}
DMAChannel & operator = (const DMAChannel &rhs) {
if (channel != rhs.channel) {
release();
CFG = rhs.CFG;
channel = rhs.channel;
}
return *this;
}
DMAChannel & operator = (const DMASetting &rhs) {
copy_cfg(CFG, rhs.CFG);
return *this;
}
~DMAChannel() {
release();
}
void begin(bool force_initialization = false);
private:
void release(void);

public:
/***************************************/
/** Triggering **/
/***************************************/

// Triggers cause the DMA channel to actually move data. Each
// trigger moves a single data unit, which is typically 8, 16 or
// 32 bits. If a channel is configured for 200 transfers

// Use a hardware trigger to make the DMA channel run
void triggerAtHardwareEvent(uint8_t source) {
volatile uint8_t *mux;
CFG->DCR |= DMA_DCR_CS;
mux = (volatile uint8_t *)&(DMAMUX0_CHCFG0) + channel;
*mux = 0;
*mux = (source & 63) | DMAMUX_ENABLE;
}

// Use another DMA channel as the trigger, causing this
// channel to trigger after each transfer is makes, including
// the its last transfer. This effectively makes the 2
// channels run in parallel. Note, on Teensy 3.0 & 3.1,
// this feature triggers on every transfer except the last.
// On Teensy-LC, it triggers on every one, including the last.
void triggerAtTransfersOf(DMABaseClass &ch) {
uint32_t dcr = ch.CFG->DCR;
uint32_t linkcc = (dcr >> 4) & 3;
if (linkcc == 0 || linkcc == 2) {
ch.CFG->DCR = (dcr & ~DMA_DCR_LCH1(3)) |
DMA_DCR_LINKCC(2) | DMA_DCR_LCH1(channel);
} else if (linkcc == 1) {
ch.CFG->DCR = (dcr & ~DMA_DCR_LCH1(3)) |
DMA_DCR_LCH1(channel);
} else {
uint32_t lch1 = (dcr >> 2) & 3;
ch.CFG->DCR = (dcr
& ~(DMA_DCR_LINKCC(3) | DMA_DCR_LCH2(3) | DMA_DCR_LCH1(3)))
| DMA_DCR_LINKCC(1) | DMA_DCR_LCH2(lch1) | DMA_DCR_LCH1(channel);
}
}

// Use another DMA channel as the trigger, causing this
// channel to trigger when the other channel completes.
void triggerAtCompletionOf(DMABaseClass &ch) {
uint32_t dcr = ch.CFG->DCR;
uint32_t linkcc = (dcr >> 4) & 3;
if (linkcc == 0 || linkcc == 3) {
ch.CFG->DCR = (dcr & ~DMA_DCR_LCH1(3)) |
DMA_DCR_LINKCC(3) | DMA_DCR_LCH1(channel);
} else {
ch.CFG->DCR = (dcr
& ~(DMA_DCR_LINKCC(3) | DMA_DCR_LCH2(3)))
| DMA_DCR_LINKCC(1) | DMA_DCR_LCH2(channel);
}
}

// Cause this DMA channel to be continuously triggered, so
// it will move data as rapidly as possible, without waiting.
// Normally this would be used with disableOnCompletion().
void triggerContinuously(void) {
uint32_t dcr = CFG->DCR;
dcr &= ~(DMA_DCR_ERQ | DMA_DCR_CS);
CFG->DCR = dcr;
CFG->DCR = dcr | DMA_DCR_START;
}

// Manually trigger the DMA channel.
void triggerManual(void) {
CFG->DCR = (CFG->DCR & ~DMA_DCR_ERQ) | (DMA_DCR_CS | DMA_DCR_START);
}


/***************************************/
/** Interrupts **/
/***************************************/

// An interrupt routine can be run when the DMA channel completes
// the entire transfer, and also optionally when half of the
// transfer is completed.
void attachInterrupt(void (*isr)(void)) {
_VectorsRam[channel + IRQ_DMA_CH0 + 16] = isr;
NVIC_ENABLE_IRQ(IRQ_DMA_CH0 + channel);
}

void detachInterrupt(void) {
NVIC_DISABLE_IRQ(IRQ_DMA_CH0 + channel);
}

void clearInterrupt(void) {
CFG->DSR_BCR = DMA_DSR_BCR_DONE;
}


/***************************************/
/** Enable / Disable **/
/***************************************/

void enable(void) {
CFG->DCR |= DMA_DCR_ERQ;
}
void disable(void) {
CFG->DCR &= ~DMA_DCR_ERQ;
}

/***************************************/
/** Status **/
/***************************************/

bool complete(void) {
if (CFG->DSR_BCR & DMA_DSR_BCR_DONE) return true;
return false;
}
void clearComplete(void) {
CFG->DSR_BCR |= DMA_DSR_BCR_DONE;
}
bool error(void) {
if (CFG->DSR_BCR &
(DMA_DSR_BCR_CE | DMA_DSR_BCR_BES | DMA_DSR_BCR_BED)) return true;
return false;
}
void clearError(void) {
CFG->DSR_BCR |= DMA_DSR_BCR_DONE;
}
void * sourceAddress(void) {
return (void *)(CFG->SAR);
}
void * destinationAddress(void) {
return (void *)(CFG->DAR);
}

/***************************************/
/** Direct Hardware Access **/
/***************************************/

uint8_t channel;
// CFG is accessible due to inheritance from DMABaseClass
};

// arrange the relative priority of 2 or more DMA channels
@@ -802,13 +1096,11 @@ void DMAPriorityOrder(DMAChannel &ch1, DMAChannel &ch2, DMAChannel &ch3, DMAChan



extern "C" {
#endif
extern uint16_t dma_channel_allocated_mask;
#ifdef __cplusplus
}
#endif
#endif // KINETISL



#endif
#endif // __cplusplus


#endif // DMAChannel_h_

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

@@ -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 查看文件

@@ -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 查看文件

@@ -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

+ 255
- 8
teensy3/HardwareSerial.h 查看文件

@@ -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
@@ -85,8 +111,24 @@
// bit7: actual data goes into 9th bit


#if defined(KINETISK)
#define BAUD2DIV(baud) (((F_CPU * 2) + ((baud) >> 1)) / (baud))
#define BAUD2DIV2(baud) (((F_CPU * 2) + ((baud) >> 1)) / (baud))
#define BAUD2DIV3(baud) (((F_BUS * 2) + ((baud) >> 1)) / (baud))
#elif defined(KINETISL)

#if F_CPU <= 2000000
#define BAUD2DIV(baud) (((F_PLL / 16 ) + ((baud) >> 1)) / (baud))
#elif F_CPU <= 16000000
#define BAUD2DIV(baud) (((F_PLL / (F_PLL / 1000000)) + ((baud) >> 1)) / (baud))
#else
#define BAUD2DIV(baud) (((F_PLL / 2 / 16) + ((baud) >> 1)) / (baud))
#endif

#define BAUD2DIV2(baud) (((F_BUS / 16) + ((baud) >> 1)) / (baud))
#define BAUD2DIV3(baud) (((F_BUS / 16) + ((baud) >> 1)) / (baud))
#endif


// C language implementation
//
@@ -97,6 +139,10 @@ void serial_begin(uint32_t divisor);
void serial_format(uint32_t format);
void serial_end(void);
void serial_set_transmit_pin(uint8_t pin);
void serial_set_rx(uint8_t pin);
void serial_set_tx(uint8_t pin, uint8_t opendrain);
int serial_set_rts(uint8_t pin);
int serial_set_cts(uint8_t pin);
void serial_putchar(uint32_t c);
void serial_write(const void *buf, unsigned int count);
void serial_flush(void);
@@ -114,6 +160,10 @@ void serial2_begin(uint32_t divisor);
void serial2_format(uint32_t format);
void serial2_end(void);
void serial2_set_transmit_pin(uint8_t pin);
void serial2_set_rx(uint8_t pin);
void serial2_set_tx(uint8_t pin, uint8_t opendrain);
int serial2_set_rts(uint8_t pin);
int serial2_set_cts(uint8_t pin);
void serial2_putchar(uint32_t c);
void serial2_write(const void *buf, unsigned int count);
void serial2_flush(void);
@@ -127,6 +177,10 @@ void serial3_begin(uint32_t divisor);
void serial3_format(uint32_t format);
void serial3_end(void);
void serial3_set_transmit_pin(uint8_t pin);
void serial3_set_rx(uint8_t pin);
void serial3_set_tx(uint8_t pin, uint8_t opendrain);
int serial3_set_rts(uint8_t pin);
int serial3_set_cts(uint8_t pin);
void serial3_putchar(uint32_t c);
void serial3_write(const void *buf, unsigned int count);
void serial3_flush(void);
@@ -136,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
@@ -148,18 +253,24 @@ 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));
serial_format(format); }
virtual void end(void) { serial_end(); }
virtual void transmitterEnable(uint8_t pin) { serial_set_transmit_pin(pin); }
virtual void setRX(uint8_t pin) { serial_set_rx(pin); }
virtual void setTX(uint8_t pin, bool opendrain=false) { serial_set_tx(pin, opendrain); }
virtual bool attachRts(uint8_t pin) { return serial_set_rts(pin); }
virtual bool attachCts(uint8_t pin) { return serial_set_cts(pin); }
virtual int available(void) { return serial_available(); }
virtual int peek(void) { return serial_peek(); }
virtual int read(void) { return serial_getchar(); }
virtual void flush(void) { serial_flush(); }
virtual void clear(void) { serial_clear(); }
virtual int availableForWrite(void) { return serial_write_buffer_free(); }
using Print::write;
virtual size_t write(uint8_t c) { serial_putchar(c); return 1; }
virtual size_t write(unsigned long n) { return write((uint8_t)n); }
virtual size_t write(long n) { return write((uint8_t)n); }
@@ -171,6 +282,7 @@ public:
serial_write((const uint8_t *)str, len);
return len; }
virtual size_t write9bit(uint32_t c) { serial_putchar(c); return 1; }
operator bool() { return true; }
};
extern HardwareSerial Serial1;
extern void serialEvent1(void);
@@ -178,18 +290,24 @@ extern void serialEvent1(void);
class HardwareSerial2 : public HardwareSerial
{
public:
virtual void begin(uint32_t baud) { serial2_begin(BAUD2DIV(baud)); }
constexpr HardwareSerial2() {}
virtual void begin(uint32_t baud) { serial2_begin(BAUD2DIV2(baud)); }
virtual void begin(uint32_t baud, uint32_t format) {
serial2_begin(BAUD2DIV(baud));
serial2_begin(BAUD2DIV2(baud));
serial2_format(format); }
virtual void end(void) { serial2_end(); }
virtual void transmitterEnable(uint8_t pin) { serial2_set_transmit_pin(pin); }
virtual void setRX(uint8_t pin) { serial2_set_rx(pin); }
virtual void setTX(uint8_t pin, bool opendrain=false) { serial2_set_tx(pin, opendrain); }
virtual bool attachRts(uint8_t pin) { return serial2_set_rts(pin); }
virtual bool attachCts(uint8_t pin) { return serial2_set_cts(pin); }
virtual int available(void) { return serial2_available(); }
virtual int peek(void) { return serial2_peek(); }
virtual int read(void) { return serial2_getchar(); }
virtual void flush(void) { serial2_flush(); }
virtual void clear(void) { serial2_clear(); }
virtual int availableForWrite(void) { return serial2_write_buffer_free(); }
using Print::write;
virtual size_t write(uint8_t c) { serial2_putchar(c); return 1; }
virtual size_t write(unsigned long n) { return write((uint8_t)n); }
virtual size_t write(long n) { return write((uint8_t)n); }
@@ -201,6 +319,7 @@ public:
serial2_write((const uint8_t *)str, len);
return len; }
virtual size_t write9bit(uint32_t c) { serial2_putchar(c); return 1; }
operator bool() { return true; }
};
extern HardwareSerial2 Serial2;
extern void serialEvent2(void);
@@ -208,18 +327,24 @@ 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));
serial3_format(format); }
virtual void end(void) { serial3_end(); }
virtual void transmitterEnable(uint8_t pin) { serial3_set_transmit_pin(pin); }
virtual void setRX(uint8_t pin) { serial3_set_rx(pin); }
virtual void setTX(uint8_t pin, bool opendrain=false) { serial3_set_tx(pin, opendrain); }
virtual bool attachRts(uint8_t pin) { return serial3_set_rts(pin); }
virtual bool attachCts(uint8_t pin) { return serial3_set_cts(pin); }
virtual int available(void) { return serial3_available(); }
virtual int peek(void) { return serial3_peek(); }
virtual int read(void) { return serial3_getchar(); }
virtual void flush(void) { serial3_flush(); }
virtual void clear(void) { serial3_clear(); }
virtual int availableForWrite(void) { return serial3_write_buffer_free(); }
using Print::write;
virtual size_t write(uint8_t c) { serial3_putchar(c); return 1; }
virtual size_t write(unsigned long n) { return write((uint8_t)n); }
virtual size_t write(long n) { return write((uint8_t)n); }
@@ -231,9 +356,131 @@ public:
serial3_write((const uint8_t *)str, len);
return len; }
virtual size_t write9bit(uint32_t c) { serial3_putchar(c); return 1; }
operator bool() { return true; }
};
extern HardwareSerial3 Serial3;
extern void serialEvent3(void);

class HardwareSerial4 : public HardwareSerial
{
public:
constexpr HardwareSerial4() {}
virtual void begin(uint32_t baud) { serial4_begin(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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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

+ 53
- 45
teensy3/IPAddress.cpp 查看文件

@@ -1,57 +1,65 @@
#if ARDUINO >= 100
#include "Arduino.h"
#include "IPAddress.h"
/*
IPAddress.cpp - Base class that provides IPAddress
Copyright (c) 2011 Adrian McEwen. All right reserved.

IPAddress::IPAddress()
{
memset(_address, 0, sizeof(_address));
}
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.

IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
{
_address[0] = first_octet;
_address[1] = second_octet;
_address[2] = third_octet;
_address[3] = fourth_octet;
}
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.

IPAddress::IPAddress(uint32_t address)
{
memcpy(_address, &address, sizeof(_address));
}
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
*/

IPAddress::IPAddress(const uint8_t *address)
{
memcpy(_address, address, sizeof(_address));
}

IPAddress& IPAddress::operator=(const uint8_t *address)
{
memcpy(_address, address, sizeof(_address));
return *this;
}
#include <Arduino.h>
#include "IPAddress.h"

IPAddress& IPAddress::operator=(uint32_t address)
size_t IPAddress::printTo(Print& p) const
{
memcpy(_address, (const uint8_t *)&address, sizeof(_address));
return *this;
int i=0;
while (1) {
p.print(_address.bytes[i], DEC);
if (++i >= 4) return 4;
p.write('.');
}
}

bool IPAddress::operator==(const uint8_t* addr)
bool IPAddress::fromString(const char *address)
{
return memcmp(addr, _address, sizeof(_address)) == 0;
}
unsigned int acc = 0; // Accumulator
unsigned int dots = 0;

size_t IPAddress::printTo(Print& p) const
{
size_t n = 0;
for (int i =0; i < 3; i++)
{
n += p.print(_address[i], DEC);
n += p.print('.');
}
n += p.print(_address[3], DEC);
return n;
while (*address) {
char c = *address++;
if (c >= '0' && c <= '9') {
acc = acc * 10 + (c - '0');
if (acc > 255) {
// Value out of [0..255] range
return false;
}
} else if (c == '.') {
if (dots == 3) {
// Too much dots (there must be 3 dots)
return false;
}
_address.bytes[dots++] = acc;
acc = 0;
} else {
// Invalid char
return false;
}
}
if (dots != 3) {
// Too few dots (there must be 3 dots)
return false;
}
_address.bytes[3] = acc;
return true;
}

#endif

+ 79
- 36
teensy3/IPAddress.h 查看文件

@@ -23,60 +23,103 @@
* adrianm@mcqn.com 1/1/2011
*/

#if ARDUINO >= 100
#ifndef IPAddress_h
#define IPAddress_h

#include <Printable.h>
#include <WString.h>

// A class to make it easier to handle and pass around IP addresses

class IPAddress : public Printable {
private:
uint8_t _address[4]; // IPv4 address
// Access the raw byte array containing the address. Because this returns a pointer
// to the internal structure rather than a copy of the address this function should only
// be used when you know that the usage of the returned uint8_t* will be transient and not
// stored.
uint8_t* raw_address() { return _address; };
union {
uint8_t bytes[4]; // IPv4 address
uint32_t dword;
} _address;

// Access the raw byte array containing the address. Because this returns a pointer
// to the internal structure rather than a copy of the address this function should only
// be used when you know that the usage of the returned uint8_t* will be transient and not
// stored.
uint8_t * raw_address() { return _address.bytes; };

public:
// Constructors
IPAddress();
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
IPAddress(uint32_t address);
IPAddress(const uint8_t *address);
// Constructors
IPAddress() {
_address.dword = 0;
}
IPAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) {
_address.bytes[0] = b1;
_address.bytes[1] = b2;
_address.bytes[2] = b3;
_address.bytes[3] = b4;
}
IPAddress(uint32_t address) {
_address.dword = address;
}
IPAddress(const uint8_t *address) {
// TODO: use unaligned read on Cortex-M4
_address.bytes[0] = *address++;
_address.bytes[1] = *address++;
_address.bytes[2] = *address++;
_address.bytes[3] = *address++;
}

bool fromString(const char *address);
bool fromString(const String &address) {
return fromString(address.c_str());
}

// Overloaded cast operator to allow IPAddress objects to be used where a pointer
// to a four-byte uint8_t array is expected
operator uint32_t () { return _address[0] | (_address[1] << 8)
| (_address[2] << 16) | (_address[3] << 24); }
bool operator==(const IPAddress& addr) { return _address[0] == addr._address[0]
&& _address[1] == addr._address[1]
&& _address[2] == addr._address[2]
&& _address[3] == addr._address[3]; }
bool operator==(const uint8_t* addr);
// Overloaded cast operator to allow IPAddress objects to be used where a pointer
// to a four-byte uint8_t array is expected
operator uint32_t () {
return _address.dword;
}
bool operator==(const IPAddress& addr) {
return _address.dword == addr._address.dword;
}
bool operator==(const uint8_t* addr) {
// TODO: use unaligned read on Cortex-M4
return (_address.bytes[0] == addr[0]
&& _address.bytes[1] == addr[1]
&& _address.bytes[2] == addr[2]
&& _address.bytes[3] == addr[3]);
}

// Overloaded index operator to allow getting and setting individual octets of the address
uint8_t operator[](int index) const { return _address[index]; };
uint8_t& operator[](int index) { return _address[index]; };
// Overloaded index operator to allow getting and setting individual octets of the address
uint8_t operator[](int index) const {
return _address.bytes[index];
};
uint8_t& operator[](int index) {
return _address.bytes[index];
};

// Overloaded copy operators to allow initialisation of IPAddress objects from other types
IPAddress& operator=(const uint8_t *address);
IPAddress& operator=(uint32_t address);
// Overloaded copy operators to allow initialisation of IPAddress objects from other types
IPAddress& operator=(const uint8_t *address) {
// TODO: use unaligned read on Cortex-M4
_address.bytes[0] = *address++;
_address.bytes[1] = *address++;
_address.bytes[2] = *address++;
_address.bytes[3] = *address++;
return *this;
}
IPAddress& operator=(uint32_t address) {
_address.dword = address;
return *this;
}

virtual size_t printTo(Print& p) const;
virtual size_t printTo(Print& p) const;

friend class EthernetClass;
friend class UDP;
friend class Client;
friend class Server;
friend class DhcpClass;
friend class DNSClient;
friend class EthernetClass;
friend class UDP;
friend class Client;
friend class Server;
friend class DhcpClass;
friend class DNSClient;
};

const IPAddress INADDR_NONE(0,0,0,0);
const IPAddress INADDR_NONE((uint32_t)0);


#endif
#endif

+ 124
- 165
teensy3/IntervalTimer.cpp 查看文件

@@ -1,186 +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 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
// ------------------------------------------------------------
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](); }



// ------------------------------------------------------------
// 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;
static void dummy_funct(void);

#if defined(KINETISK)
#define NUM_CHANNELS 4
static void (*funct_table[4])(void) = {dummy_funct, dummy_funct, dummy_funct, dummy_funct};

#elif defined(KINETISL)
#define NUM_CHANNELS 2
static void (*funct_table[2])(void) = {dummy_funct, dummy_funct};
uint8_t IntervalTimer::nvic_priorites[2] = {255, 255};
#endif


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;
IRQ_PIT_CH = IRQ_PIT_CH0 + PIT_id;
// 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;
NVIC_SET_PRIORITY(IRQ_PIT_CH, nvic_priority);
NVIC_ENABLE_IRQ(IRQ_PIT_CH);

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
NVIC_DISABLE_IRQ(IRQ_PIT_CH);
*PIT_TCTRL = 0;
// 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();
#elif defined(KINETISL)
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
- 73
teensy3/IntervalTimer.h 查看文件

@@ -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,60 +38,105 @@ extern "C" {
#endif

class IntervalTimer {
private:
typedef void (*ISR)();
typedef volatile uint32_t* reg;
enum {TIMER_OFF, TIMER_PIT};
static const uint8_t NUM_PIT = 4;
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];
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);
}
static ISR PIT_ISR[NUM_PIT];
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 查看文件

@@ -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 查看文件

@@ -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

+ 78
- 22
teensy3/Makefile 查看文件

@@ -1,15 +1,64 @@
# 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)))))))))))))))))))))))))))
MCU_LD = $(LOWER_MCU).ld

# The name of your project (used to name the compiled .hex file)
TARGET = main

# Those that specify a NO_ARDUINO environment variable will
# be able to use this Makefile with no Arduino dependency.
# Please note that if ARDUINOPATH was set, it will override
# the NO_ARDUINO behaviour.
ifndef NO_ARDUINO
# Path to your arduino installation
ARDUINOPATH ?= ../../../..
ARDUINOPATH ?= ../../../../..
endif

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

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

# options needed by many Arduino libraries to configure for Teensy 3.0
OPTIONS += -D__MK20DX128__ -DARDUIO=105 -DTEENSYDUINO=118
# 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:
@@ -25,41 +74,49 @@ OPTIONS += -D__MK20DX128__ -DARDUIO=105 -DTEENSYDUINO=118
# locations and edit the pathnames. The rest of Arduino is not needed.
#************************************************************************

# path location for Teensy Loader, teensy_post_compile and teensy_reboot
TOOLSPATH = $(ARDUINOPATH)/hardware/tools # on Linux
#TOOLSPATH = $(ARDUINOPATH)/hardware/tools/tools/avr/bin # on Mac or Windows
ifdef ARDUINOPATH

# 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 = $(ARDUINOPATH)/libraries
LIBRARYPATH = $(abspath $(ARDUINOPATH)/libraries)

# path location for the arm-none-eabi compiler
COMPILERPATH = $(ARDUINOPATH)/hardware/tools/arm-none-eabi/bin
COMPILERPATH = $(abspath $(ARDUINOPATH)/hardware/tools/arm/bin)

else
# Default to the normal GNU/Linux compiler path if NO_ARDUINO
# and ARDUINOPATH was not set.
COMPILERPATH ?= /usr/bin

endif

#************************************************************************
# Settings below this point usually do not need to be edited
#************************************************************************

# CPPFLAGS = compiler options for C and C++
CPPFLAGS = -Wall -g -Os -mcpu=cortex-m4 -mthumb -nostdlib -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 -mcpu=cortex-m4 -mthumb -Tmk20dx128.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


# names for the compiler programs
CC = $(abspath $(COMPILERPATH))/arm-none-eabi-gcc
CXX = $(abspath $(COMPILERPATH))/arm-none-eabi-g++
OBJCOPY = $(abspath $(COMPILERPATH))/arm-none-eabi-objcopy
SIZE = $(abspath $(COMPILERPATH))/arm-none-eabi-size
CC = $(COMPILERPATH)/arm-none-eabi-gcc
CXX = $(COMPILERPATH)/arm-none-eabi-g++
OBJCOPY = $(COMPILERPATH)/arm-none-eabi-objcopy
SIZE = $(COMPILERPATH)/arm-none-eabi-size

# automatically create lists of the sources and objects
# TODO: this does not handle Arduino libraries yet...
@@ -72,20 +129,19 @@ OBJS := $(C_FILES:.c=.o) $(CPP_FILES:.cpp=.o)

all: $(TARGET).hex

$(TARGET).elf: $(OBJS) mk20dx128.ld
$(TARGET).elf: $(OBJS) $(MCU_LD)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)

%.hex: %.elf
$(SIZE) $<
$(OBJCOPY) -O ihex -R .eeprom $< $@
$(abspath $(TOOLSPATH))/teensy_post_compile -file=$(basename $@) -path=$(shell pwd) -tools=$(abspath $(TOOLSPATH))
-$(abspath $(TOOLSPATH))/teensy_reboot

ifneq (,$(wildcard $(TOOLSPATH)))
$(TOOLSPATH)/teensy_post_compile -file=$(basename $@) -path=$(shell pwd) -tools=$(TOOLSPATH)
-$(TOOLSPATH)/teensy_reboot
endif

# compiler generated dependency info
-include $(OBJS:.o=.d)

clean:
rm -f *.o *.d $(TARGET).elf $(TARGET).hex



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

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

// This header file is in the public domain.

+ 186
- 30
teensy3/Print.cpp 查看文件

@@ -1,34 +1,40 @@
/*
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)
@@ -80,7 +86,7 @@ __attribute__((weak))
int _write(int file, char *ptr, int len)
{
((class Print *)file)->write((uint8_t *)ptr, len);
return 0;
return len;
}
}

@@ -88,16 +94,160 @@ int Print::printf(const char *format, ...)
{
va_list ap;
va_start(ap, format);
#ifdef __STRICT_ANSI__
return 0; // TODO: make this work with -std=c++0x
#else
return vdprintf((int)this, format, ap);
#endif
}

int Print::printf(const __FlashStringHelper *format, ...)
{
va_list ap;
va_start(ap, format);
#ifdef __STRICT_ANSI__
return 0;
#else
return vdprintf((int)this, (const char *)format, ap);
#endif
}

#ifdef __MKL26Z64__

// optimized code inspired by Stimmer's optimization
// obviously a dit different, adapted to 32 bit Cortex-M0+
// http://forum.arduino.cc/index.php?topic=167414.msg1293679#msg1293679
// http://forum.arduino.cc/index.php?topic=167414.msg1309482#msg1309482
// equivelant code:
// mod = div % 10;
// div = div / 10;
// tmp1 = {random};
// tmp2 = 10;
#if 1
// https://forum.pjrc.com/threads/28932-LC-is-10-9-times-slower-than-T3-1?p=76072&viewfull=1#post76072
void inline divmod10_v2(uint32_t n,uint32_t *div,uint32_t *mod) {
uint32_t p,q;
/* Using 32.16 fixed point representation p.q */
/* p.q = (n+1)/512 */
q = (n&0xFFFF) + 1;
p = (n>>16);
/* p.q = 51*(n+1)/512 */
q = 13107*q;
p = 13107*p;
/* p.q = (1+1/2^8+1/2^16+1/2^24)*51*(n+1)/512 */
q = q + (q>>16) + (p&0xFFFF);
p = p + (p>>16) + (q>>16);
/* divide by 2 */
p = p>>1;
*div = p;
*mod = n-10*p;
}
#define divmod10_asm(div, mod, tmp1, tmp2, const3333) \
divmod10_v2(div, &div, &mod);
/*
#define divmod10_asm(div, mod, tmp1, tmp2, const3333) \
asm ( \
" lsr %2, %0, #16" "\n\t" \
" mul %2, %4" "\n\t" \
" uxth %1, %0" "\n\t" \
" mul %1, %4" "\n\t" \
" add %1, #1" "\n\t" \
" lsr %0, %2, #16" "\n\t" \
" lsl %2, %2, #16" "\n\t" \
" add %1, %2" "\n\t" \
" mov %3, #0" "\n\t" \
" adc %0, %3" "\n\t" \
" lsl %0, %0, #15" "\n\t" \
" lsr %2, %1, #17" "\n\t" \
" orr %0, %2" "\n\t" \
" lsl %1, %1, #15" "\n\t" \
" lsr %2, %1, #16" "\n\t" \
" lsl %3, %0, #16" "\n\t" \
" orr %2, %3" "\n\t" \
" lsr %3, %0, #16" "\n\t" \
" add %1, %0" "\n\t" \
" adc %0, %1" "\n\t" \
" sub %0, %1" "\n\t" \
" add %1, %2" "\n\t" \
" adc %0, %3" "\n\t" \
" lsr %1, %1, #4" "\n\t" \
" mov %3, #10" "\n\t" \
" mul %1, %3" "\n\t" \
" lsr %1, %1, #28" "\n\t" \
: "+l" (div), \
"=&l" (mod), \
"=&l" (tmp1), \
"=&l" (tmp2) \
: "l" (const3333) \
: \
)
*/
#else
#define divmod10_asm(_div, _mod, _tmp1, _tmp2, _const3333) \
({ _tmp1 = _div; _div = _div / 10; _mod = _tmp1 - _div * 10; })
// ({_mod = _div % 10, _div = _div / 10; })
#endif


size_t Print::printNumberDec(unsigned long n, uint8_t sign)
{
uint8_t buf[11], *p;
uint32_t digit;
//uint32_t t1, t2, c3333=0x3333;

p = buf + (sizeof(buf));
do {
uint32_t div;
divmod10_v2(n, &div, &digit);
n = div;
//divmod10_asm(n, digit, t1, t2, c3333);
*--p = digit + '0';
} while (n);
if (sign) *--p = '-';
return write(p, sizeof(buf) - (p - buf));
}

size_t Print::printNumberHex(unsigned long n)
{
uint8_t digit, buf[8], *p;

p = buf + (sizeof(buf));
do {
digit = n & 15;
*--p = (digit < 10) ? '0' + digit : 'A' + digit - 10;
n >>= 4;
} while (n);
return write(p, sizeof(buf) - (p - buf));
}

size_t Print::printNumberBin(unsigned long n)
{
uint8_t buf[32], *p;

p = buf + (sizeof(buf));
do {
*--p = '0' + ((uint8_t)n & 1);
n >>= 1;
} while (n);
return write(p, sizeof(buf) - (p - buf));
}

size_t Print::printNumberAny(unsigned long n, uint8_t base)
{
uint8_t digit, buf[21], *p;
uint32_t tmp;

p = buf + sizeof(buf);
do {
tmp = n;
n = n / base;
digit = tmp - n * base;
*--p = (digit < 10) ? '0' + digit : 'A' + digit - 10;
} while (n);
return write(p, sizeof(buf) - (p - buf));
}

#else

size_t Print::printNumber(unsigned long n, uint8_t base, uint8_t sign)
{
@@ -134,12 +284,18 @@ size_t Print::printNumber(unsigned long n, uint8_t base, uint8_t sign)
return write(buf + i, sizeof(buf) - i);
}

#endif

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;
@@ -160,7 +316,7 @@ size_t Print::printFloat(double number, uint8_t digits)

// Print the decimal point, but only if there are digits beyond
if (digits > 0) {
uint8_t n, buf[8], count=1;
uint8_t n, buf[16], count=1;
buf[0] = '.';

// Extract digits from the remainder one at a time

+ 26
- 3
teensy3/Print.h 查看文件

@@ -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); }
@@ -102,7 +109,23 @@ class Print
private:
char write_error;
size_t printFloat(double n, uint8_t digits);
#ifdef __MKL26Z64__
size_t printNumberDec(unsigned long n, uint8_t sign);
size_t printNumberHex(unsigned long n);
size_t printNumberBin(unsigned long n);
size_t printNumberAny(unsigned long n, uint8_t base);
inline size_t printNumber(unsigned long n, uint8_t base, uint8_t sign) __attribute__((always_inline)) {
// when "base" is a constant (pretty much always), the
// compiler optimizes this to a single function call.
if (base == 0) return write((uint8_t)n);
if (base == 10 || base < 2) return printNumberDec(n, sign);
if (base == 16) return printNumberHex(n);
if (base == 2) return printNumberBin(n);
return printNumberAny(n, base);
}
#else
size_t printNumber(unsigned long n, uint8_t base, uint8_t sign);
#endif
};



+ 137
- 23
teensy3/SPIFIFO.h 查看文件

@@ -1,9 +1,115 @@
/* 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_

#include "avr_emulation.h"

#if F_BUS == 60000000
#ifdef KINETISK

// 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
@@ -93,7 +199,9 @@
#define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz
#define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz

#endif
#endif // F_BUS

#endif // KINETISK

/*
#! /usr/bin/perl
@@ -129,11 +237,11 @@ 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;

SPI0.MCR = SPI_MCR_MSTR | SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
KINETISK_SPI0.MCR = SPI_MCR_MSTR | SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
if (mode & 0x08) ctar |= SPI_CTAR_CPOL;
if (mode & 0x04) {
ctar |= SPI_CTAR_CPHA;
@@ -141,8 +249,8 @@ public:
} else {
ctar |= (ctar & 0x0F) << 12;
}
SPI0.CTAR0 = ctar | SPI_CTAR_FMSZ(7);
SPI0.CTAR1 = ctar | SPI_CTAR_FMSZ(15);
KINETISK_SPI0.CTAR0 = ctar | SPI_CTAR_FMSZ(7);
KINETISK_SPI0.CTAR1 = ctar | SPI_CTAR_FMSZ(15);
if (pin == 10) { // PTC4
CORE_PIN10_CONFIG = PORT_PCR_MUX(2);
p = 0x01;
@@ -170,10 +278,15 @@ 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);
*reg = 1;
pinMode(pin, OUTPUT);
*reg = 1;
p = 0;
}
pcs = p;
@@ -183,16 +296,16 @@ public:
inline void write(uint32_t b, uint32_t cont=0) __attribute__((always_inline)) {
uint32_t pcsbits = pcs << 16;
if (pcsbits) {
SPI0.PUSHR = (b & 0xFF) | pcsbits | (cont ? SPI_PUSHR_CONT : 0);
while (((SPI0.SR) & (15 << 12)) > (3 << 12)) ; // wait if FIFO full
KINETISK_SPI0.PUSHR = (b & 0xFF) | pcsbits | (cont ? SPI_PUSHR_CONT : 0);
while (((KINETISK_SPI0.SR) & (15 << 12)) > (3 << 12)) ; // wait if FIFO full
} else {
*reg = 0;
SPI0.SR = SPI_SR_EOQF;
SPI0.PUSHR = (b & 0xFF) | (cont ? 0 : SPI_PUSHR_EOQ);
KINETISK_SPI0.SR = SPI_SR_EOQF;
KINETISK_SPI0.PUSHR = (b & 0xFF) | (cont ? 0 : SPI_PUSHR_EOQ);
if (cont) {
while (((SPI0.SR) & (15 << 12)) > (3 << 12)) ;
while (((KINETISK_SPI0.SR) & (15 << 12)) > (3 << 12)) ;
} else {
while (!(SPI0.SR & SPI_SR_EOQF)) ;
while (!(KINETISK_SPI0.SR & SPI_SR_EOQF)) ;
*reg = 1;
}
}
@@ -200,27 +313,27 @@ public:
inline void write16(uint32_t b, uint32_t cont=0) __attribute__((always_inline)) {
uint32_t pcsbits = pcs << 16;
if (pcsbits) {
SPI0.PUSHR = (b & 0xFFFF) | (pcs << 16) |
KINETISK_SPI0.PUSHR = (b & 0xFFFF) | (pcs << 16) |
(cont ? SPI_PUSHR_CONT : 0) | SPI_PUSHR_CTAS(1);
while (((SPI0.SR) & (15 << 12)) > (3 << 12)) ;
while (((KINETISK_SPI0.SR) & (15 << 12)) > (3 << 12)) ;
} else {
*reg = 0;
SPI0.SR = SPI_SR_EOQF;
SPI0.PUSHR = (b & 0xFFFF) | (cont ? 0 : SPI_PUSHR_EOQ) | SPI_PUSHR_CTAS(1);
KINETISK_SPI0.SR = SPI_SR_EOQF;
KINETISK_SPI0.PUSHR = (b & 0xFFFF) | (cont ? 0 : SPI_PUSHR_EOQ) | SPI_PUSHR_CTAS(1);
if (cont) {
while (((SPI0.SR) & (15 << 12)) > (3 << 12)) ;
while (((KINETISK_SPI0.SR) & (15 << 12)) > (3 << 12)) ;
} else {
while (!(SPI0.SR & SPI_SR_EOQF)) ;
while (!(KINETISK_SPI0.SR & SPI_SR_EOQF)) ;
*reg = 1;
}
}
}
inline uint32_t read(void) __attribute__((always_inline)) {
while ((SPI0.SR & (15 << 4)) == 0) ; // TODO, could wait forever
return SPI0.POPR;
while ((KINETISK_SPI0.SR & (15 << 4)) == 0) ; // TODO, could wait forever
return KINETISK_SPI0.POPR;
}
inline void clear(void) __attribute__((always_inline)) {
SPI0.MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F) | SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF;
KINETISK_SPI0.MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F) | SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF;
}
private:
static uint8_t pcs;
@@ -228,5 +341,6 @@ private:
};
extern SPIFIFOclass SPIFIFO;

#endif
#endif // HAS_SPIFIFO

#endif

+ 21
- 0
teensy3/Server.h 查看文件

@@ -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;

+ 10
- 35
teensy3/Stream.cpp 查看文件

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

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

#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field
@@ -75,20 +74,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, const char *terminator)
{
return findUntil(target, strlen(target), terminator, strlen(terminator));
}
@@ -96,7 +95,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, const char *terminator, size_t termLen)
{
size_t index = 0; // maximum target string length is 64k bytes!
size_t termIndex = 0;
@@ -176,7 +175,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();
@@ -256,7 +255,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 +264,7 @@ String Stream::readString(size_t max)
}
if (c == 0) break;
str += (char)c;
length++;
}
return str;
}
@@ -272,7 +272,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 +281,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 查看文件

@@ -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);

+ 60
- 122
teensy3/Tone.cpp 查看文件

@@ -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,12 +28,8 @@
* SOFTWARE.
*/

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

#if 1
// IntervalTimer based tone. This allows tone() to share the timers with other
// libraries, rather than permanently hogging one PIT timer even for projects
// which never use tone(). Someday this single-tone implementation might be
@@ -42,11 +38,25 @@
static uint32_t tone_toggle_count;
static volatile uint8_t *tone_reg;
static uint8_t tone_pin=255;
static uint16_t tone_frequency=0;
static float tone_usec=0.0;
static uint32_t tone_new_count=0;
IntervalTimer tone_timer;

void tone_interrupt(void);

#if defined(KINETISK)
#define TONE_CLEAR_PIN tone_reg[0] = 1
#define TONE_TOGGLE_PIN tone_reg[128] = 1
#define TONE_OUTPUT_PIN tone_reg[384] = 1

#elif defined(KINETISL)
static uint8_t tone_mask;
#define TONE_CLEAR_PIN tone_reg[0] = tone_mask
#define TONE_TOGGLE_PIN tone_reg[4] = tone_mask
#define TONE_OUTPUT_PIN __disable_irq(); tone_reg[12] |= tone_mask; __enable_irq()

#endif

void tone(uint8_t pin, uint16_t frequency, uint32_t duration)
{
uint32_t count;
@@ -56,9 +66,11 @@ void tone(uint8_t pin, uint16_t frequency, uint32_t duration)
if (pin >= CORE_NUM_DIGITAL) return;
if (duration) {
count = (frequency * duration / 1000) * 2;
if (!(count & 1)) count++; // always full waveform cycles
} else {
count = 0xFFFFFFFF;
count = 0xFFFFFFFD;
}
if (frequency < 1) frequency = 1; // minimum is 1 Hz
usec = (float)500000.0 / (float)frequency;
config = portConfigRegister(pin);

@@ -66,28 +78,35 @@ void tone(uint8_t pin, uint16_t frequency, uint32_t duration)
// the interrupt on a single timer.
__disable_irq();
if (pin == tone_pin) {
if (frequency == tone_frequency) {
// same pin, same frequency, so just update the
// duration. Users will call repetitively call
// tone() with the same setting, expecting a
// continuous output with no glitches or phase
// changes or jitter at each call.
tone_toggle_count = count;
// changing a pin which is already playing a tone
if (usec == tone_usec) {
// same frequency, so just change the duration
tone_toggle_count = (tone_toggle_count & 1) + count - 1;
} else {
// same pin, but a new frequency.
tone_reg[0] = 1; // clear pin
tone_timer.begin(tone_interrupt, usec);
// different frequency, reduce duration to only the
// remainder of its current cycle, and configure for
// the transition to the new frequency when the
// current cycle completes
tone_usec = usec;
tone_new_count = count;
tone_toggle_count = (tone_toggle_count & 1);
}
} else {
// if playing on a different pin, immediately stop, even mid-cycle :-(
if (tone_pin < CORE_NUM_DIGITAL) {
tone_reg[0] = 1; // clear pin
TONE_CLEAR_PIN; // clear pin
}
// configure the new tone to play
tone_pin = pin;
tone_reg = portClearRegister(pin);
tone_reg[0] = 1; // clear pin
tone_reg[384] = 1; // output mode;
#if defined(KINETISL)
tone_mask = digitalPinToBitMask(pin);
#endif
TONE_CLEAR_PIN; // clear pin
TONE_OUTPUT_PIN; // output mode;
*config = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
tone_toggle_count = count;
tone_usec = usec;
tone_timer.begin(tone_interrupt, usec);
}
__enable_irq();
@@ -96,97 +115,24 @@ void tone(uint8_t pin, uint16_t frequency, uint32_t duration)

void tone_interrupt(void)
{
if (tone_toggle_count) {
tone_reg[128] = 1; // toggle
if (tone_toggle_count < 0xFFFFFFFF) tone_toggle_count--;
if (tone_toggle_count) { // odd = rising edge, even = falling edge
// not the end
TONE_TOGGLE_PIN; // toggle
tone_toggle_count--;
if (tone_toggle_count == 0xFFFFFFFB) tone_toggle_count = 0xFFFFFFFD;
} else {
tone_timer.end();
tone_reg[0] = 0; // clear
tone_pin = 255;
tone_frequency = 0;
}
}

void noTone(uint8_t pin)
{
if (pin >= CORE_NUM_DIGITAL) return;
__disable_irq();
if (pin == tone_pin) {
tone_timer.end();
tone_reg[0] = 0; // clear
tone_pin = 255;
tone_frequency = 0;
}
__enable_irq();
}
#endif



#if 0
// Old PIT timer based tone(). This implementation is slightly more efficient,
// but it consumes one of the PIT timers, even for projects which never use tone().

static uint32_t tone_toggle_count;
static volatile uint8_t *tone_reg;
static uint8_t tone_pin;

void init_tone(void)
{
if (SIM_SCGC6 & SIM_SCGC6_PIT) return;
SIM_SCGC6 |= SIM_SCGC6_PIT; // TODO: use bitband for atomic read-mod-write
PIT_MCR = 0;
PIT_TCTRL3 = 0; // disabled
tone_pin = 255;
NVIC_ENABLE_IRQ(IRQ_PIT_CH3);
}

void tone(uint8_t pin, uint16_t frequency, uint32_t duration)
{
uint32_t count, load;
volatile uint32_t *config;

init_tone();
if (pin >= CORE_NUM_DIGITAL) return;
if (duration) {
count = (frequency * duration / 1000) * 2;
} else {
count = 0xFFFFFFFF;
}
load = (F_BUS / 2) / frequency;
config = portConfigRegister(pin);
__disable_irq();
if (pin != tone_pin) {
if (tone_pin < CORE_NUM_DIGITAL) {
tone_reg[0] = 1; // clear pin
// this transition completes the tone
TONE_CLEAR_PIN; // clear
if (tone_new_count > 0) {
// begin playing a new tone
tone_timer.begin(tone_interrupt, tone_usec);
tone_toggle_count = tone_new_count;
tone_new_count = 0;
} else {
// finished playing
tone_timer.end();
tone_pin = 255;
}
tone_pin = pin;
tone_reg = portClearRegister(pin);
tone_reg[0] = 1; // clear pin
tone_reg[384] = 1; // output mode;
*config = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
}
tone_toggle_count = count;
if (PIT_LDVAL3 != load) {
PIT_TCTRL3 = 0;
PIT_LDVAL3 = load;
PIT_TCTRL3 = 3;
}
__enable_irq();
}

void pit3_isr(void)
{
PIT_TFLG3 = 1;

if (tone_toggle_count) {
tone_reg[128] = 1; // toggle
if (tone_toggle_count < 0xFFFFFFFF) tone_toggle_count--;
} else {
PIT_TCTRL3 = 0;
PIT_LDVAL3 = 0;
tone_reg[0] = 0; // clear
tone_pin = 255;
}
}

@@ -195,20 +141,12 @@ void noTone(uint8_t pin)
if (pin >= CORE_NUM_DIGITAL) return;
__disable_irq();
if (pin == tone_pin) {
PIT_TCTRL3 = 0;
PIT_LDVAL3 = 0;
tone_reg[0] = 0; // clear
tone_timer.end();
TONE_CLEAR_PIN; // clear
tone_pin = 255;
}
__enable_irq();
}
#endif










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

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

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

// Sending UDP packets

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

@@ -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 查看文件

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

#include "wiring.h"

+ 23
- 7
teensy3/WMath.cpp 查看文件

@@ -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; }


+ 51
- 5
teensy3/WProgram.h 查看文件

@@ -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

@@ -16,7 +46,7 @@
#include "HardwareSerial.h"

#define DMAMEM __attribute__ ((section(".dmabuffers"), used))
#define FASTRUN __attribute__ ((section(".fastrun")))
#define FASTRUN __attribute__ ((section(".fastrun"), noinline, noclone ))

#ifdef __cplusplus

@@ -29,8 +59,12 @@
#include "usb_midi.h"
#include "usb_rawhid.h"
#include "usb_flightsim.h"
#include "usb_mtp.h"
#include "usb_audio.h"
#include "usb_touch.h"
#include "usb_undef.h" // do not allow usb_desc.h stuff to leak to user programs

//#include "WCharacter.h"
#include "WCharacter.h"
#include "WString.h"
#include "elapsedMillis.h"
#include "IntervalTimer.h"
@@ -46,15 +80,27 @@ 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"

#endif // __cplusplus


// Fast memcpy
#if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
#ifdef __cplusplus
extern "C" {
extern void *memcpy (void *dst, const void *src, size_t count);
}
#else
extern void *memcpy (void *dst, const void *src, size_t count);
#endif
#endif


#endif // WProgram_h

+ 17
- 6
teensy3/WString.cpp 查看文件

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

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


/*********************************************/
@@ -44,7 +44,7 @@ String::String(const String &value)
*this = value;
}

#ifdef __GXX_EXPERIMENTAL_CXX0X__
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
String::String(String &&rval)
{
init();
@@ -198,7 +198,7 @@ String & String::operator = (const String &rhs)
return copy(rhs.buffer, rhs.len);
}

#ifdef __GXX_EXPERIMENTAL_CXX0X__
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
String & String::operator = (String &&rval)
{
if (this != &rval) move(rval);
@@ -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++) {

+ 13
- 2
teensy3/WString.h 查看文件

@@ -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.
@@ -53,7 +57,7 @@ public:
String(const char *cstr = (const char *)NULL);
String(const __FlashStringHelper *pgmstr);
String(const String &str);
#ifdef __GXX_EXPERIMENTAL_CXX0X__
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
String(String &&rval);
String(StringSumHelper &&rval);
#endif
@@ -78,7 +82,7 @@ public:
String & operator = (const String &rhs);
String & operator = (const char *cstr);
String & operator = (const __FlashStringHelper *pgmstr);
#ifdef __GXX_EXPERIMENTAL_CXX0X__
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
String & operator = (String &&rval);
String & operator = (StringSumHelper &&rval);
#endif
@@ -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

+ 192
- 76
teensy3/analog.c 查看文件

@@ -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,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
@@ -92,82 +131,94 @@ 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__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
VREF_TRM = 0x60;
VREF_SC = 0xE1; // enable 1.2 volt ref
#endif

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
}

#if defined(__MK20DX128__)
if (analog_reference_internal) {
ADC0_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref
} else {
ADC0_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref
}
#elif defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
if (analog_reference_internal) {
ADC0_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref
#if defined(__MK20DX256__)
ADC1_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref
#endif
} else {
ADC0_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref
#if defined(__MK20DX256__)
ADC1_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref
#endif
}
#elif defined(__MKL26Z64__)
if (analog_reference_internal) {
ADC0_SC2 = ADC_SC2_REFSEL(0); // external AREF
} else {
ADC0_SC2 = ADC_SC2_REFSEL(1); // vcc
}
#endif

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
}
@@ -179,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
@@ -203,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;
@@ -220,13 +271,19 @@ 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__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
#define DEFAULT 0
#define INTERNAL 2
#define INTERNAL1V2 2
#define INTERNAL1V1 2
#define EXTERNAL 0

#elif defined(__MKL26Z64__)
#define DEFAULT 0
#define INTERNAL 0
#define EXTERNAL 1
#endif

void analogReference(uint8_t type)
{
if (type) {
@@ -235,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
}
@@ -247,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
}
@@ -274,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();
}
}
@@ -289,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;
}
@@ -305,21 +379,51 @@ 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 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

@@ -327,52 +431,39 @@ static const uint8_t channel2sc1a[] = {

// 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 (pin <= 13) {
index = pin; // 0-13 refer to A0-A13
} else if (pin <= 23) {
index = pin - 14; // 14-23 are A0-A9
#if defined(__MK20DX256__)
} else if (pin >= 26 && pin <= 31) {
index = pin - 9; // 26-31 are A15-A20
#endif
} else if (pin >= 34 && pin <= 40) {
index = pin - 24; // 34-37 are A10-A13, 38 is temp sensor,
// 39 is vref, 40 is unused (A14 on Teensy 3.1)
} else {
return 0; // all others are invalid
}

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

__disable_irq();
startADC0:
//serial_print("startADC0\n");
#if defined(__MKL26Z64__)
if (channel & 0x40) {
ADC0_CFG2 &= ~ADC_CFG2_MUXSEL;
channel &= 0x3F;
} else {
ADC0_CFG2 |= ADC_CFG2_MUXSEL;
}
#endif
ADC0_SC1A = channel;
analogReadBusyADC0 = 1;
__enable_irq();
@@ -393,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;
@@ -426,26 +517,51 @@ 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?
__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) {
// use 3.3V VDDA power as the reference (this is the default)
DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS | DAC_C0_DACSWTRG; // 3.3V VDDA
} else {
// use whatever voltage is on the AREF pin
DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACSWTRG; // 3.3V VDDA
}
if (val < 0) val = 0;
else if (val > 4095) val = 4095;
*(int16_t *)&(DAC0_DAT0L) = val;

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


#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
void analogWriteDAC1(int val)
{
SIM_SCGC2 |= SIM_SCGC2_DAC1;
if (analog_reference_internal) {
DAC1_C0 = DAC_C0_DACEN; // 1.2V ref is DACREF_1
} else {
DAC1_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2
}
__asm__ ("usat %[value], #12, %[value]\n\t" : [value] "+r" (val)); // 0 <= val <= 4095


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




+ 36
- 1
teensy3/avr/eeprom.h 查看文件

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

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

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

#define E2END 0x80
#include "avr_functions.h"

#if defined(__MK20DX128__) || defined(__MK20DX256__)
#define E2END 0x7FF
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
#define E2END 0xFFF
#elif defined(__MKL26Z64__)
#define E2END 0x7F
#else
#define E2END 0
#endif

#endif

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

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

+ 22
- 0
teensy3/avr/io.h 查看文件

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

#include "../avr_emulation.h"

+ 67
- 5
teensy3/avr/pgmspace.h 查看文件

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

#ifndef __PGMSPACE_H_
#define __PGMSPACE_H_ 1

@@ -18,6 +40,8 @@ typedef int16_t prog_int16_t;
typedef uint16_t prog_uint16_t;
typedef int32_t prog_int32_t;
typedef uint32_t prog_uint32_t;
typedef int64_t prog_int64_t;
typedef uint64_t prog_uint64_t;

#define memchr_P(str, c, len) memchr((str), (c), (len))
#define memcmp_P(a, b, n) memcmp((a), (b), (n))
@@ -45,25 +69,63 @@ typedef uint32_t prog_uint32_t;
#define strspn_P(str, chrs) strspn((str), (chrs))
#define strstr_P(a, b) strstr((a), (b))
#define sprintf_P(s, ...) sprintf((s), __VA_ARGS__)
#define vfprintf_P(s, ...) vfprintf((s), __VA_ARGS__)
#define vfprintf_P(fp, s, ...) vfprintf((fp), (s), __VA_ARGS__)
#define printf_P(...) printf(__VA_ARGS__)
#define snprintf_P(s, n, ...) ((s), (n), __VA_ARGS__)
#define vsprintf_P(s, ...) ((s),__VA_ARGS__)
#define vsnprintf_P(s, n, ...) ((s), (n),__VA_ARGS__)
#define fprintf_P(s, ...) ((s), __VA_ARGS__)
#define snprintf_P(s, n, ...) snprintf((s), (n), __VA_ARGS__)
#define vsprintf_P(s, ...) vsprintf((s), __VA_ARGS__)
#define vsnprintf_P(s, n, ...) vsnprintf((s), (n), __VA_ARGS__)
#define fprintf_P(fp, ...) fprintf((fp), __VA_ARGS__)
#define strlen_PF(a) strlen((a))
#define strnlen_PF(src, len) strnlen((src), (len))
#define memcpy_PF(dest, src, len) memcpy((dest), (src), (len))
#define strcpy_PF(dest, src) strcpy((dest), (src))
#define strncpy_PF(dest, src, len) strncpy((dest), (src), (len))
#define strcat_PF(dest, src) strcat((dest), (src))
#define strlcat_PF(dest, src, len) strlcat((dest), (src), (len))
#define strncat_PF(dest, src, len) strncat((dest), (src), (len))
#define strcmp_PF(s1, s2) strcmp((s1), (s2))
#define strncmp_PF(s1, s2, n) strncmp((s1), (s2), (n))
#define strcasecmp_PF(s1, s2) strcasecmp((s1), (s2))
#define strncasecmp_PF(s1, s2, n) strncasecmp((s1), (s2), (n))
#define strstr_PF(s1, s2) strstr((s1), (s2))
#define strlcpy_PF(dest, src, n) strlcpy((dest), (src), (n))
#define memcmp_PF(s1, s2, n) memcmp((s1), (s2), (n))


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


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

#endif

+ 26
- 0
teensy3/avr/power.h 查看文件

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

#ifndef _AVR_POWER_H_
#define _AVR_POWER_H_ 1

#endif

+ 24
- 2
teensy3/avr/sleep.h 查看文件

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

#ifndef _AVR_SLEEP_H_
#define _AVR_SLEEP_H_ 1

@@ -11,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...

+ 21
- 0
teensy3/avr/wdt.h 查看文件

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

#ifndef _AVR_WDT_H_
#define _AVR_WDT_H_

#define WDTO_15MS 0
#define WDTO_30MS 1
#define WDTO_60MS 2
#define WDTO_120MS 3
#define WDTO_250MS 4
#define WDTO_500MS 5
#define WDTO_1S 6
#define WDTO_2S 7
#define WDTO_4S 8
#define WDTO_8S 9

#define wdt_reset()
#define wdt_enable(timeout)
#define wdt_disable()

#endif

+ 15
- 7
teensy3/avr_emulation.cpp 查看文件

@@ -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,11 +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;
@@ -41,6 +51,4 @@ volatile uint8_t * SPIFIFOclass::reg = 0;

#endif

uint8_t EIMSK = 0;



+ 1300
- 147
teensy3/avr_emulation.h
文件差異過大導致無法顯示
查看文件


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

@@ -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
@@ -94,10 +94,14 @@ static inline void eeprom_update_block(const void *buf, void *addr, uint32_t len

char * ultoa(unsigned long val, char *buf, int radix);
char * ltoa(long val, char *buf, int radix);

#if defined(_NEWLIB_VERSION) && (__NEWLIB__ < 2 || __NEWLIB__ == 2 && __NEWLIB_MINOR__ < 2)
static inline char * utoa(unsigned int val, char *buf, int radix) __attribute__((always_inline, unused));
static inline char * utoa(unsigned int val, char *buf, int radix) { return ultoa(val, buf, radix); }
static inline char * itoa(int val, char *buf, int radix) __attribute__((always_inline, unused));
static inline char * itoa(int val, char *buf, int radix) { return ltoa(val, buf, radix); }
#endif

char * dtostrf(float val, int width, unsigned int precision, char *buf);



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

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

#ifndef Binary_h
#define Binary_h


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

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

#ifndef CORE_TEENSY
#define CORE_TEENSY
#endif

+ 1278
- 14
teensy3/core_pins.h
文件差異過大導致無法顯示
查看文件


+ 316
- 27
teensy3/eeprom.c 查看文件

@@ -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,9 +28,43 @@
* 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 <stdint.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 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

#if E2END > (EEPROM_MAX-1)
#error "E2END is set larger than the maximum possible EEPROM size"
#endif

#if defined(KINETISK)

// The EEPROM is really RAM with a hardware-based backup system to
// flash memory. Selecting a smaller size EEPROM allows more wear
@@ -40,7 +74,32 @@
// (aligned to 2 or 4 byte boundaries) has twice the endurance
// compared to writing 8 bit bytes.
//
#define EEPROM_SIZE 2048

#if E2END < 32
#define EEPROM_SIZE 32
#define EEESIZE 0x09
#elif E2END < 64
#define EEPROM_SIZE 64
#define EEESIZE 0x08
#elif E2END < 128
#define EEPROM_SIZE 128
#define EEESIZE 0x07
#elif E2END < 256
#define EEPROM_SIZE 256
#define EEESIZE 0x06
#elif E2END < 512
#define EEPROM_SIZE 512
#define EEESIZE 0x05
#elif E2END < 1024
#define EEPROM_SIZE 1024
#define EEESIZE 0x04
#elif E2END < 2048
#define EEPROM_SIZE 2048
#define EEESIZE 0x03
#elif E2END < 4096
#define EEPROM_SIZE 4096
#define EEESIZE 0x02
#endif

// Writing unaligned 16 or 32 bit data is handled automatically when
// this is defined, but at a cost of extra code size. Without this,
@@ -50,23 +109,6 @@
//
#define HANDLE_UNALIGNED_WRITES

// Minimum EEPROM Endurance
// ------------------------
#if (EEPROM_SIZE == 2048) // 35000 writes/byte or 70000 writes/word
#define EEESIZE 0x33
#elif (EEPROM_SIZE == 1024) // 75000 writes/byte or 150000 writes/word
#define EEESIZE 0x34
#elif (EEPROM_SIZE == 512) // 155000 writes/byte or 310000 writes/word
#define EEESIZE 0x35
#elif (EEPROM_SIZE == 256) // 315000 writes/byte or 630000 writes/word
#define EEESIZE 0x36
#elif (EEPROM_SIZE == 128) // 635000 writes/byte or 1270000 writes/word
#define EEESIZE 0x37
#elif (EEPROM_SIZE == 64) // 1275000 writes/byte or 2550000 writes/word
#define EEESIZE 0x38
#elif (EEPROM_SIZE == 32) // 2555000 writes/byte or 5110000 writes/word
#define EEESIZE 0x39
#endif

void eeprom_initialize(void)
{
@@ -77,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_FCCOB5 = 0x03; // 0K for Dataflash, 32K for EEPROM backup
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);
@@ -94,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)
{
@@ -156,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();
}
}

@@ -171,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
@@ -199,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
@@ -250,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;
@@ -261,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;
@@ -270,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--;
@@ -279,9 +378,6 @@ void eeprom_write_block(const void *buf, void *addr, uint32_t len)
}
}




/*
void do_flash_cmd(volatile uint8_t *fstat)
{
@@ -297,3 +393,196 @@ void do_flash_cmd(volatile uint8_t *fstat)
e: 4770 bx lr
*/

#elif defined(KINETISL)

#define EEPROM_SIZE (E2END+1)

#define FLASH_BEGIN (uint16_t *)63488
#define FLASH_END (uint16_t *)65536
static uint16_t flashend = 0;

void eeprom_initialize(void)
{
const uint16_t *p = FLASH_BEGIN;

do {
if (*p++ == 0xFFFF) {
flashend = (uint32_t)(p - 2);
return;
}
} while (p < FLASH_END);
flashend = (uint32_t)(FLASH_END - 1);
}

uint8_t eeprom_read_byte(const uint8_t *addr)
{
uint32_t offset = (uint32_t)addr;
const uint16_t *p = FLASH_BEGIN;
const uint16_t *end = (const uint16_t *)((uint32_t)flashend);
uint16_t val;
uint8_t data=0xFF;

if (!end) {
eeprom_initialize();
end = (const uint16_t *)((uint32_t)flashend);
}
if (offset < EEPROM_SIZE) {
while (p <= end) {
val = *p++;
if ((val & 255) == offset) data = val >> 8;
}
}
return data;
}

static void flash_write(const uint16_t *code, uint32_t addr, uint32_t data)
{
// with great power comes great responsibility....
uint32_t stat;
*(uint32_t *)&FTFL_FCCOB3 = 0x06000000 | (addr & 0x00FFFFFC);
*(uint32_t *)&FTFL_FCCOB7 = data;
__disable_irq();
(*((void (*)(volatile uint8_t *))((uint32_t)code | 1)))(&FTFL_FSTAT);
__enable_irq();
stat = FTFL_FSTAT & 0x70;
if (stat) {
FTFL_FSTAT = stat;
}
MCM_PLACR |= MCM_PLACR_CFCC;
}

void eeprom_write_byte(uint8_t *addr, uint8_t data)
{
uint32_t offset = (uint32_t)addr;
const uint16_t *p, *end = (const uint16_t *)((uint32_t)flashend);
uint32_t i, val, flashaddr;
uint16_t do_flash_cmd[] = {
0x2380, 0x7003, 0x7803, 0xb25b, 0x2b00, 0xdafb, 0x4770};
uint8_t buf[EEPROM_SIZE];

if (offset >= EEPROM_SIZE) return;
if (!end) {
eeprom_initialize();
end = (const uint16_t *)((uint32_t)flashend);
}
if (++end < FLASH_END) {
val = (data << 8) | offset;
flashaddr = (uint32_t)end;
flashend = flashaddr;
if ((flashaddr & 2) == 0) {
val |= 0xFFFF0000;
} else {
val <<= 16;
val |= 0x0000FFFF;
}
flash_write(do_flash_cmd, flashaddr, val);
} else {
for (i=0; i < EEPROM_SIZE; i++) {
buf[i] = 0xFF;
}
for (p = FLASH_BEGIN; p < FLASH_END; p++) {
val = *p;
if ((val & 255) < EEPROM_SIZE) {
buf[val & 255] = val >> 8;
}
}
buf[offset] = data;
for (flashaddr=(uint32_t)FLASH_BEGIN; flashaddr < (uint32_t)FLASH_END; flashaddr += 1024) {
*(uint32_t *)&FTFL_FCCOB3 = 0x09000000 | flashaddr;
__disable_irq();
(*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&FTFL_FSTAT);
__enable_irq();
val = FTFL_FSTAT & 0x70;
if (val) FTFL_FSTAT = val;
MCM_PLACR |= MCM_PLACR_CFCC;
}
flashaddr=(uint32_t)FLASH_BEGIN;
for (i=0; i < EEPROM_SIZE; i++) {
if (buf[i] == 0xFF) continue;
if ((flashaddr & 2) == 0) {
val = (buf[i] << 8) | i;
} else {
val = val | (buf[i] << 24) | (i << 16);
flash_write(do_flash_cmd, flashaddr, val);
}
flashaddr += 2;
}
flashend = flashaddr;
if ((flashaddr & 2)) {
val |= 0xFFFF0000;
flash_write(do_flash_cmd, flashaddr, val);
}
}
}

/*
void do_flash_cmd(volatile uint8_t *fstat)
{
*fstat = 0x80;
while ((*fstat & 0x80) == 0) ; // wait
}
00000000 <do_flash_cmd>:
0: 2380 movs r3, #128 ; 0x80
2: 7003 strb r3, [r0, #0]
4: 7803 ldrb r3, [r0, #0]
6: b25b sxtb r3, r3
8: 2b00 cmp r3, #0
a: dafb bge.n 4 <do_flash_cmd+0x4>
c: 4770 bx lr
*/


uint16_t eeprom_read_word(const uint16_t *addr)
{
const uint8_t *p = (const uint8_t *)addr;
return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8);
}

uint32_t eeprom_read_dword(const uint32_t *addr)
{
const uint8_t *p = (const uint8_t *)addr;
return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8)
| (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
}

void eeprom_read_block(void *buf, const void *addr, uint32_t len)
{
const uint8_t *p = (const uint8_t *)addr;
uint8_t *dest = (uint8_t *)buf;
while (len--) {
*dest++ = eeprom_read_byte(p++);
}
}

int eeprom_is_ready(void)
{
return 1;
}

void eeprom_write_word(uint16_t *addr, uint16_t value)
{
uint8_t *p = (uint8_t *)addr;
eeprom_write_byte(p++, value);
eeprom_write_byte(p, value >> 8);
}

void eeprom_write_dword(uint32_t *addr, uint32_t value)
{
uint8_t *p = (uint8_t *)addr;
eeprom_write_byte(p++, value);
eeprom_write_byte(p++, value >> 8);
eeprom_write_byte(p++, value >> 16);
eeprom_write_byte(p, value >> 24);
}

void eeprom_write_block(const void *buf, void *addr, uint32_t len)
{
uint8_t *p = (uint8_t *)addr;
const uint8_t *src = (const uint8_t *)buf;
while (len--) {
eeprom_write_byte(p++, *src++);
}
}


#endif // KINETISL

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

@@ -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

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

@@ -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
@@ -36,7 +36,7 @@
#ifdef M
#undef M
#endif
#define M(n) ((n) & 0x3FFF)
#define M(n) ((n) & KEYCODE_MASK)

const KEYCODE_TYPE keycodes_ascii[] = {
M(ASCII_20), M(ASCII_21), M(ASCII_22), M(ASCII_23),

+ 506
- 135
teensy3/keylayouts.h 查看文件

@@ -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
@@ -67,138 +67,149 @@ extern "C"{
// http://en.wikipedia.org/wiki/Keyboard_layout


#define MODIFIERKEY_CTRL ( 0x01 | 0x8000 )
#define MODIFIERKEY_SHIFT ( 0x02 | 0x8000 )
#define MODIFIERKEY_ALT ( 0x04 | 0x8000 )
#define MODIFIERKEY_GUI ( 0x08 | 0x8000 )
#define MODIFIERKEY_LEFT_CTRL ( 0x01 | 0x8000 )
#define MODIFIERKEY_LEFT_SHIFT ( 0x02 | 0x8000 )
#define MODIFIERKEY_LEFT_ALT ( 0x04 | 0x8000 )
#define MODIFIERKEY_LEFT_GUI ( 0x08 | 0x8000 )
#define MODIFIERKEY_RIGHT_CTRL ( 0x10 | 0x8000 )
#define MODIFIERKEY_RIGHT_SHIFT ( 0x20 | 0x8000 )
#define MODIFIERKEY_RIGHT_ALT ( 0x40 | 0x8000 )
#define MODIFIERKEY_RIGHT_GUI ( 0x80 | 0x8000 )

#define KEY_MEDIA_VOLUME_INC 0x01
#define KEY_MEDIA_VOLUME_DEC 0x02
#define KEY_MEDIA_MUTE 0x04
#define KEY_MEDIA_PLAY_PAUSE 0x08
#define KEY_MEDIA_NEXT_TRACK 0x10
#define KEY_MEDIA_PREV_TRACK 0x20
#define KEY_MEDIA_STOP 0x40
#define KEY_MEDIA_EJECT 0x80

#define KEY_A ( 4 | 0x4000 )
#define KEY_B ( 5 | 0x4000 )
#define KEY_C ( 6 | 0x4000 )
#define KEY_D ( 7 | 0x4000 )
#define KEY_E ( 8 | 0x4000 )
#define KEY_F ( 9 | 0x4000 )
#define KEY_G ( 10 | 0x4000 )
#define KEY_H ( 11 | 0x4000 )
#define KEY_I ( 12 | 0x4000 )
#define KEY_J ( 13 | 0x4000 )
#define KEY_K ( 14 | 0x4000 )
#define KEY_L ( 15 | 0x4000 )
#define KEY_M ( 16 | 0x4000 )
#define KEY_N ( 17 | 0x4000 )
#define KEY_O ( 18 | 0x4000 )
#define KEY_P ( 19 | 0x4000 )
#define KEY_Q ( 20 | 0x4000 )
#define KEY_R ( 21 | 0x4000 )
#define KEY_S ( 22 | 0x4000 )
#define KEY_T ( 23 | 0x4000 )
#define KEY_U ( 24 | 0x4000 )
#define KEY_V ( 25 | 0x4000 )
#define KEY_W ( 26 | 0x4000 )
#define KEY_X ( 27 | 0x4000 )
#define KEY_Y ( 28 | 0x4000 )
#define KEY_Z ( 29 | 0x4000 )
#define KEY_1 ( 30 | 0x4000 )
#define KEY_2 ( 31 | 0x4000 )
#define KEY_3 ( 32 | 0x4000 )
#define KEY_4 ( 33 | 0x4000 )
#define KEY_5 ( 34 | 0x4000 )
#define KEY_6 ( 35 | 0x4000 )
#define KEY_7 ( 36 | 0x4000 )
#define KEY_8 ( 37 | 0x4000 )
#define KEY_9 ( 38 | 0x4000 )
#define KEY_0 ( 39 | 0x4000 )
#define KEY_ENTER ( 40 | 0x4000 )
#define KEY_ESC ( 41 | 0x4000 )
#define KEY_BACKSPACE ( 42 | 0x4000 )
#define KEY_TAB ( 43 | 0x4000 )
#define KEY_SPACE ( 44 | 0x4000 )
#define KEY_MINUS ( 45 | 0x4000 )
#define KEY_EQUAL ( 46 | 0x4000 )
#define KEY_LEFT_BRACE ( 47 | 0x4000 )
#define KEY_RIGHT_BRACE ( 48 | 0x4000 )
#define KEY_BACKSLASH ( 49 | 0x4000 )
#define KEY_NON_US_NUM ( 50 | 0x4000 )
#define KEY_SEMICOLON ( 51 | 0x4000 )
#define KEY_QUOTE ( 52 | 0x4000 )
#define KEY_TILDE ( 53 | 0x4000 )
#define KEY_COMMA ( 54 | 0x4000 )
#define KEY_PERIOD ( 55 | 0x4000 )
#define KEY_SLASH ( 56 | 0x4000 )
#define KEY_CAPS_LOCK ( 57 | 0x4000 )
#define KEY_F1 ( 58 | 0x4000 )
#define KEY_F2 ( 59 | 0x4000 )
#define KEY_F3 ( 60 | 0x4000 )
#define KEY_F4 ( 61 | 0x4000 )
#define KEY_F5 ( 62 | 0x4000 )
#define KEY_F6 ( 63 | 0x4000 )
#define KEY_F7 ( 64 | 0x4000 )
#define KEY_F8 ( 65 | 0x4000 )
#define KEY_F9 ( 66 | 0x4000 )
#define KEY_F10 ( 67 | 0x4000 )
#define KEY_F11 ( 68 | 0x4000 )
#define KEY_F12 ( 69 | 0x4000 )
#define KEY_PRINTSCREEN ( 70 | 0x4000 )
#define KEY_SCROLL_LOCK ( 71 | 0x4000 )
#define KEY_PAUSE ( 72 | 0x4000 )
#define KEY_INSERT ( 73 | 0x4000 )
#define KEY_HOME ( 74 | 0x4000 )
#define KEY_PAGE_UP ( 75 | 0x4000 )
#define KEY_DELETE ( 76 | 0x4000 )
#define KEY_END ( 77 | 0x4000 )
#define KEY_PAGE_DOWN ( 78 | 0x4000 )
#define KEY_RIGHT ( 79 | 0x4000 )
#define KEY_LEFT ( 80 | 0x4000 )
#define KEY_DOWN ( 81 | 0x4000 )
#define KEY_UP ( 82 | 0x4000 )
#define KEY_NUM_LOCK ( 83 | 0x4000 )
#define KEYPAD_SLASH ( 84 | 0x4000 )
#define KEYPAD_ASTERIX ( 85 | 0x4000 )
#define KEYPAD_MINUS ( 86 | 0x4000 )
#define KEYPAD_PLUS ( 87 | 0x4000 )
#define KEYPAD_ENTER ( 88 | 0x4000 )
#define KEYPAD_1 ( 89 | 0x4000 )
#define KEYPAD_2 ( 90 | 0x4000 )
#define KEYPAD_3 ( 91 | 0x4000 )
#define KEYPAD_4 ( 92 | 0x4000 )
#define KEYPAD_5 ( 93 | 0x4000 )
#define KEYPAD_6 ( 94 | 0x4000 )
#define KEYPAD_7 ( 95 | 0x4000 )
#define KEYPAD_8 ( 96 | 0x4000 )
#define KEYPAD_9 ( 97 | 0x4000 )
#define KEYPAD_0 ( 98 | 0x4000 )
#define KEYPAD_PERIOD ( 99 | 0x4000 )
#define KEY_MENU ( 101 | 0x4000 )
#define KEY_F13 ( 104 | 0x4000 )
#define KEY_F14 ( 105 | 0x4000 )
#define KEY_F15 ( 106 | 0x4000 )
#define KEY_F16 ( 107 | 0x4000 )
#define KEY_F17 ( 108 | 0x4000 )
#define KEY_F18 ( 109 | 0x4000 )
#define KEY_F19 ( 110 | 0x4000 )
#define KEY_F20 ( 111 | 0x4000 )
#define KEY_F21 ( 112 | 0x4000 )
#define KEY_F22 ( 113 | 0x4000 )
#define KEY_F23 ( 114 | 0x4000 )
#define KEY_F24 ( 115 | 0x4000 )

#define MODIFIERKEY_CTRL ( 0x01 | 0xE000 )
#define MODIFIERKEY_SHIFT ( 0x02 | 0xE000 )
#define MODIFIERKEY_ALT ( 0x04 | 0xE000 )
#define MODIFIERKEY_GUI ( 0x08 | 0xE000 )
#define MODIFIERKEY_LEFT_CTRL ( 0x01 | 0xE000 )
#define MODIFIERKEY_LEFT_SHIFT ( 0x02 | 0xE000 )
#define MODIFIERKEY_LEFT_ALT ( 0x04 | 0xE000 )
#define MODIFIERKEY_LEFT_GUI ( 0x08 | 0xE000 )
#define MODIFIERKEY_RIGHT_CTRL ( 0x10 | 0xE000 )
#define MODIFIERKEY_RIGHT_SHIFT ( 0x20 | 0xE000 )
#define MODIFIERKEY_RIGHT_ALT ( 0x40 | 0xE000 )
#define MODIFIERKEY_RIGHT_GUI ( 0x80 | 0xE000 )

#define KEY_SYSTEM_POWER_DOWN ( 0x81 | 0xE200 )
#define KEY_SYSTEM_SLEEP ( 0x82 | 0xE200 )
#define KEY_SYSTEM_WAKE_UP ( 0x83 | 0xE200 )

#define KEY_MEDIA_PLAY ( 0xB0 | 0xE400 )
#define KEY_MEDIA_PAUSE ( 0xB1 | 0xE400 )
#define KEY_MEDIA_RECORD ( 0xB2 | 0xE400 )
#define KEY_MEDIA_FAST_FORWARD ( 0xB3 | 0xE400 )
#define KEY_MEDIA_REWIND ( 0xB4 | 0xE400 )
#define KEY_MEDIA_NEXT_TRACK ( 0xB5 | 0xE400 )
#define KEY_MEDIA_PREV_TRACK ( 0xB6 | 0xE400 )
#define KEY_MEDIA_STOP ( 0xB7 | 0xE400 )
#define KEY_MEDIA_EJECT ( 0xB8 | 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 )
#define KEY_MEDIA_VOLUME_INC ( 0xE9 | 0xE400 )
#define KEY_MEDIA_VOLUME_DEC ( 0xEA | 0xE400 )

#define KEY_A ( 4 | 0xF000 )
#define KEY_B ( 5 | 0xF000 )
#define KEY_C ( 6 | 0xF000 )
#define KEY_D ( 7 | 0xF000 )
#define KEY_E ( 8 | 0xF000 )
#define KEY_F ( 9 | 0xF000 )
#define KEY_G ( 10 | 0xF000 )
#define KEY_H ( 11 | 0xF000 )
#define KEY_I ( 12 | 0xF000 )
#define KEY_J ( 13 | 0xF000 )
#define KEY_K ( 14 | 0xF000 )
#define KEY_L ( 15 | 0xF000 )
#define KEY_M ( 16 | 0xF000 )
#define KEY_N ( 17 | 0xF000 )
#define KEY_O ( 18 | 0xF000 )
#define KEY_P ( 19 | 0xF000 )
#define KEY_Q ( 20 | 0xF000 )
#define KEY_R ( 21 | 0xF000 )
#define KEY_S ( 22 | 0xF000 )
#define KEY_T ( 23 | 0xF000 )
#define KEY_U ( 24 | 0xF000 )
#define KEY_V ( 25 | 0xF000 )
#define KEY_W ( 26 | 0xF000 )
#define KEY_X ( 27 | 0xF000 )
#define KEY_Y ( 28 | 0xF000 )
#define KEY_Z ( 29 | 0xF000 )
#define KEY_1 ( 30 | 0xF000 )
#define KEY_2 ( 31 | 0xF000 )
#define KEY_3 ( 32 | 0xF000 )
#define KEY_4 ( 33 | 0xF000 )
#define KEY_5 ( 34 | 0xF000 )
#define KEY_6 ( 35 | 0xF000 )
#define KEY_7 ( 36 | 0xF000 )
#define KEY_8 ( 37 | 0xF000 )
#define KEY_9 ( 38 | 0xF000 )
#define KEY_0 ( 39 | 0xF000 )
#define KEY_ENTER ( 40 | 0xF000 )
#define KEY_ESC ( 41 | 0xF000 )
#define KEY_BACKSPACE ( 42 | 0xF000 )
#define KEY_TAB ( 43 | 0xF000 )
#define KEY_SPACE ( 44 | 0xF000 )
#define KEY_MINUS ( 45 | 0xF000 )
#define KEY_EQUAL ( 46 | 0xF000 )
#define KEY_LEFT_BRACE ( 47 | 0xF000 )
#define KEY_RIGHT_BRACE ( 48 | 0xF000 )
#define KEY_BACKSLASH ( 49 | 0xF000 )
#define KEY_NON_US_NUM ( 50 | 0xF000 )
#define KEY_SEMICOLON ( 51 | 0xF000 )
#define KEY_QUOTE ( 52 | 0xF000 )
#define KEY_TILDE ( 53 | 0xF000 )
#define KEY_COMMA ( 54 | 0xF000 )
#define KEY_PERIOD ( 55 | 0xF000 )
#define KEY_SLASH ( 56 | 0xF000 )
#define KEY_CAPS_LOCK ( 57 | 0xF000 )
#define KEY_F1 ( 58 | 0xF000 )
#define KEY_F2 ( 59 | 0xF000 )
#define KEY_F3 ( 60 | 0xF000 )
#define KEY_F4 ( 61 | 0xF000 )
#define KEY_F5 ( 62 | 0xF000 )
#define KEY_F6 ( 63 | 0xF000 )
#define KEY_F7 ( 64 | 0xF000 )
#define KEY_F8 ( 65 | 0xF000 )
#define KEY_F9 ( 66 | 0xF000 )
#define KEY_F10 ( 67 | 0xF000 )
#define KEY_F11 ( 68 | 0xF000 )
#define KEY_F12 ( 69 | 0xF000 )
#define KEY_PRINTSCREEN ( 70 | 0xF000 )
#define KEY_SCROLL_LOCK ( 71 | 0xF000 )
#define KEY_PAUSE ( 72 | 0xF000 )
#define KEY_INSERT ( 73 | 0xF000 )
#define KEY_HOME ( 74 | 0xF000 )
#define KEY_PAGE_UP ( 75 | 0xF000 )
#define KEY_DELETE ( 76 | 0xF000 )
#define KEY_END ( 77 | 0xF000 )
#define KEY_PAGE_DOWN ( 78 | 0xF000 )
#define KEY_RIGHT ( 79 | 0xF000 )
#define KEY_LEFT ( 80 | 0xF000 )
#define KEY_DOWN ( 81 | 0xF000 )
#define KEY_UP ( 82 | 0xF000 )
#define KEY_NUM_LOCK ( 83 | 0xF000 )
#define KEYPAD_SLASH ( 84 | 0xF000 )
#define KEYPAD_ASTERIX ( 85 | 0xF000 )
#define KEYPAD_MINUS ( 86 | 0xF000 )
#define KEYPAD_PLUS ( 87 | 0xF000 )
#define KEYPAD_ENTER ( 88 | 0xF000 )
#define KEYPAD_1 ( 89 | 0xF000 )
#define KEYPAD_2 ( 90 | 0xF000 )
#define KEYPAD_3 ( 91 | 0xF000 )
#define KEYPAD_4 ( 92 | 0xF000 )
#define KEYPAD_5 ( 93 | 0xF000 )
#define KEYPAD_6 ( 94 | 0xF000 )
#define KEYPAD_7 ( 95 | 0xF000 )
#define KEYPAD_8 ( 96 | 0xF000 )
#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 )
#define KEY_F15 ( 106 | 0xF000 )
#define KEY_F16 ( 107 | 0xF000 )
#define KEY_F17 ( 108 | 0xF000 )
#define KEY_F18 ( 109 | 0xF000 )
#define KEY_F19 ( 110 | 0xF000 )
#define KEY_F20 ( 111 | 0xF000 )
#define KEY_F21 ( 112 | 0xF000 )
#define KEY_F22 ( 113 | 0xF000 )
#define KEY_F23 ( 114 | 0xF000 )
#define KEY_F24 ( 115 | 0xF000 )

// for compatibility with Leonardo's slightly different names
#define KEY_UP_ARROW KEY_UP
@@ -225,6 +236,7 @@ extern "C"{

#define SHIFT_MASK 0x40
#define KEYCODE_TYPE uint8_t
#define KEYCODE_MASK 0x007F

#define ASCII_20 KEY_SPACE // 32
#define ASCII_21 KEY_1 + SHIFT_MASK // 33 !
@@ -339,6 +351,7 @@ extern "C"{
#define TILDE_BITS 0x0400
#define DIAERESIS_BITS 0x0500
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x07FF
#define DEADKEY_CIRCUMFLEX KEY_6 + SHIFT_MASK
#define DEADKEY_ACUTE_ACCENT KEY_QUOTE
#define DEADKEY_GRAVE_ACCENT KEY_TILDE
@@ -555,6 +568,7 @@ extern "C"{
#define ACUTE_ACCENT_BITS 0x0400
#define GRAVE_ACCENT_BITS 0x0500
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x07FF
#define DEADKEY_CIRCUMFLEX KEY_TILDE
#define DEADKEY_ACUTE_ACCENT KEY_EQUAL
#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK
@@ -772,6 +786,7 @@ extern "C"{
#define DIAERESIS_BITS 0x0400
#define TILDE_BITS 0x0500
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x07FF
#define DEADKEY_ACUTE_ACCENT KEY_EQUAL
#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK
#define DEADKEY_CIRCUMFLEX KEY_6 + SHIFT_MASK + ALTGR_MASK
@@ -995,6 +1010,7 @@ extern "C"{
#define CEDILLA_BITS 0x0500

#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x07FF
#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE
#define DEADKEY_ACUTE_ACCENT KEY_SLASH + ALTGR_MASK
#define DEADKEY_GRAVE_ACCENT KEY_QUOTE
@@ -1214,6 +1230,7 @@ extern "C"{
#define TILDE_BITS 0x0600
#define RING_ABOVE_BITS 0x0700
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x0FFF
#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE
#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK
#define DEADKEY_ACUTE_ACCENT KEY_SEMICOLON + RCTRL_MASK
@@ -1428,12 +1445,13 @@ extern "C"{
#define SHIFT_MASK 0x0040
#define ALTGR_MASK 0x0080
#define KEYCODE_TYPE uint8_t
#define KEYCODE_MASK 0x00FF
#define KEY_NON_US_100 63

#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 &
@@ -1643,6 +1661,7 @@ extern "C"{
#define TILDE_BITS 0x0400
#define DIAERESIS_BITS 0x0500
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x07FF
#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK
#define DEADKEY_ACUTE_ACCENT KEY_EQUAL
#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK
@@ -1867,6 +1886,7 @@ extern "C"{
#define DIAERESIS_BITS 0x0300
#define TILDE_BITS 0x0400
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x07FF
#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE
#define DEADKEY_GRAVE_ACCENT KEY_7 + ALTGR_MASK
#define DEADKEY_DIAERESIS KEY_LEFT_BRACE + SHIFT_MASK
@@ -2087,6 +2107,7 @@ extern "C"{
#define TILDE_BITS 0x0400
#define DIAERESIS_BITS 0x0500
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x07FF
#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK
#define DEADKEY_ACUTE_ACCENT KEY_EQUAL
#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK
@@ -2309,6 +2330,7 @@ extern "C"{
#define TILDE_BITS 0x0400
#define DIAERESIS_BITS 0x0500
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x07FF
#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK
#define DEADKEY_ACUTE_ACCENT KEY_EQUAL + ALTGR_MASK
#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK
@@ -2532,6 +2554,7 @@ extern "C"{
#define TILDE_BITS 0x0400
#define DIAERESIS_BITS 0x0500
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x07FF
#define DEADKEY_CIRCUMFLEX KEY_RIGHT_BRACE + SHIFT_MASK
#define DEADKEY_ACUTE_ACCENT KEY_EQUAL
#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK
@@ -2755,6 +2778,7 @@ extern "C"{
#define TILDE_BITS 0x0400
#define DIAERESIS_BITS 0x0500
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x07FF
#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE + SHIFT_MASK
#define DEADKEY_ACUTE_ACCENT KEY_QUOTE
#define DEADKEY_GRAVE_ACCENT KEY_LEFT_BRACE
@@ -2976,6 +3000,7 @@ extern "C"{
#define TILDE_BITS 0x0400
#define DIAERESIS_BITS 0x0500
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x07FF
#define DEADKEY_CIRCUMFLEX KEY_BACKSLASH
#define DEADKEY_ACUTE_ACCENT KEY_RIGHT_BRACE + SHIFT_MASK
#define DEADKEY_GRAVE_ACCENT KEY_RIGHT_BRACE + SHIFT_MASK
@@ -3194,6 +3219,7 @@ extern "C"{
#define SHIFT_MASK 0x40
#define ALTGR_MASK 0x80
#define KEYCODE_TYPE uint8_t
#define KEYCODE_MASK 0x00FF
#define KEY_NON_US_100 63

#define ASCII_20 KEY_SPACE // 32
@@ -3406,6 +3432,7 @@ extern "C"{
#define TILDE_BITS 0x0400
#define DIAERESIS_BITS 0x0500
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x07FF
#define DEADKEY_CIRCUMFLEX KEY_QUOTE + SHIFT_MASK
#define DEADKEY_ACUTE_ACCENT KEY_LEFT_BRACE
#define DEADKEY_GRAVE_ACCENT KEY_LEFT_BRACE + SHIFT_MASK
@@ -3622,6 +3649,7 @@ extern "C"{
#define TILDE_BITS 0x0400
#define ACUTE_ACCENT_BITS 0x0500
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x07FF
#define DEADKEY_CIRCUMFLEX KEY_LEFT_BRACE
#define DEADKEY_ACUTE_ACCENT KEY_QUOTE + ALTGR_MASK
#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK
@@ -3842,6 +3870,7 @@ extern "C"{
#define TILDE_BITS 0x0400
#define ACUTE_ACCENT_BITS 0x0500
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x07FF
#define DEADKEY_CIRCUMFLEX KEY_EQUAL
#define DEADKEY_ACUTE_ACCENT KEY_MINUS + ALTGR_MASK
#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK
@@ -4062,6 +4091,7 @@ extern "C"{
#define TILDE_BITS 0x0400
#define ACUTE_ACCENT_BITS 0x0500
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x07FF
#define DEADKEY_CIRCUMFLEX KEY_EQUAL
#define DEADKEY_ACUTE_ACCENT KEY_MINUS + ALTGR_MASK
#define DEADKEY_GRAVE_ACCENT KEY_EQUAL + SHIFT_MASK
@@ -4282,6 +4312,7 @@ extern "C"{
#define GRAVE_ACCENT_BITS 0x0300
#define DIAERESIS_BITS 0x0400
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x07FF
#define DEADKEY_CIRCUMFLEX KEY_QUOTE + ALTGR_MASK
#define DEADKEY_ACUTE_ACCENT KEY_LEFT_BRACE
#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK
@@ -4494,6 +4525,7 @@ extern "C"{
#define GRAVE_ACCENT_BITS 0x0100
#define ACUTE_ACCENT_BITS 0x0200
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x03FF
#define DEADKEY_ACUTE_ACCENT KEY_QUOTE + ALTGR_MASK
#define DEADKEY_GRAVE_ACCENT KEY_TILDE
#define KEY_NON_US_100 63
@@ -4501,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 &
@@ -4712,6 +4744,7 @@ extern "C"{
#define DIAERESIS_BITS 0x0400
#define RING_ABOVE_BITS 0x0500
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x07FF
#define DEADKEY_CIRCUMFLEX KEY_QUOTE + ALTGR_MASK
#define DEADKEY_ACUTE_ACCENT KEY_QUOTE
#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK
@@ -4933,6 +4966,7 @@ extern "C"{
#define TILDE_BITS 0x0400
#define DIAERESIS_BITS 0x0500
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x07FF
#define DEADKEY_CIRCUMFLEX KEY_3 + SHIFT_MASK
#define DEADKEY_ACUTE_ACCENT KEY_SEMICOLON + ALTGR_MASK
#define DEADKEY_GRAVE_ACCENT KEY_BACKSLASH + ALTGR_MASK
@@ -5172,6 +5206,7 @@ extern "C"{
//#define DIAERESIS_BITS 0x0A00
#define CEDILLA_BITS 0x0B00
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x0FFF
#define DEADKEY_ACUTE_ACCENT KEY_EQUAL // TODO: is it KEY_9 + ALTGR_MASK
#define DEADKEY_DEGREE_SIGN KEY_TILDE + SHIFT_MASK // TODO: is it KEY_5 + ALTGR_MASK
#define DEADKEY_CARON KEY_EQUAL + SHIFT_MASK // TODO: is it KEY_2 + ALTGR_MASK
@@ -5404,6 +5439,342 @@ extern "C"{
#endif // LAYOUT_CZECH


#ifdef LAYOUT_SERBIAN_LATIN_ONLY
// http://forum.pjrc.com/threads/27032-Serbian-Keyboard-Layout

#define SHIFT_MASK 0x0040
#define ALTGR_MASK 0x0080
#define DEADKEYS_MASK 0x0F00
#define CEDILLA_BITS 0x0100
#define CARON_BITS 0x0200
#define CIRCUMFLEX_BITS 0x0300
#define BREVE_BITS 0x0400
#define DEGREE_SIGN_BITS 0x0500
#define OGONEK_BITS 0x0600
#define DOT_ABOVE_BITS 0x0700
#define ACUTE_ACCENT_BITS 0x0800
#define DOUBLE_ACUTE_BITS 0x0900
#define DIAERESIS_BITS 0x0A00
#define KEYCODE_TYPE uint16_t
#define KEYCODE_MASK 0x0FFF
#define DEADKEY_CEDILLA KEY_TILDE
#define DEADKEY_CARON KEY_2 + ALTGR_MASK
#define DEADKEY_CIRCUMFLEX KEY_3 + ALTGR_MASK
#define DEADKEY_BREVE KEY_4 + ALTGR_MASK
#define DEADKEY_DEGREE_SIGN KEY_5 + ALTGR_MASK
#define DEADKEY_OGONEK KEY_6 + ALTGR_MASK
#define DEADKEY_DOT_ABOVE KEY_8 + ALTGR_MASK
#define DEADKEY_ACUTE_ACCENT KEY_9 + ALTGR_MASK
#define DEADKEY_DOUBLE_ACUTE KEY_0 + ALTGR_MASK
#define DEADKEY_DIAERESIS KEY_MINUS + ALTGR_MASK
//#define DEADKEY_CEDILLA KEY_EQUAL + ALTGR_MASK <-- TODO: why are there 2 Cedilla deadkeys?
#define KEY_NON_US_100 63

#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_3 + SHIFT_MASK // 35 #
#define ASCII_24 KEY_4 + SHIFT_MASK // 36 $
#define ASCII_25 KEY_5 + SHIFT_MASK // 37 %
#define ASCII_26 KEY_6 + SHIFT_MASK // 38 &
#define ASCII_27 KEY_MINUS // 39 '
#define ASCII_28 KEY_8 + SHIFT_MASK // 40 (
#define ASCII_29 KEY_9 + SHIFT_MASK // 41 )
#define ASCII_2A KEY_EQUAL + SHIFT_MASK // 42 *
#define ASCII_2B KEY_EQUAL // 43 +
#define ASCII_2C KEY_COMMA // 44 ,
#define ASCII_2D KEY_SLASH // 45 - TODO: verify
#define ASCII_2E KEY_PERIOD // 46 .
#define ASCII_2F KEY_7 + SHIFT_MASK // 47 /
#define ASCII_30 KEY_0 // 48 0
#define ASCII_31 KEY_1 // 49 1
#define ASCII_32 KEY_2 // 50 2
#define ASCII_33 KEY_3 // 51 3
#define ASCII_34 KEY_4 // 52 4
#define ASCII_35 KEY_5 // 53 5
#define ASCII_36 KEY_6 // 54 6
#define ASCII_37 KEY_7 // 55 7
#define ASCII_38 KEY_8 // 55 8
#define ASCII_39 KEY_9 // 57 9
#define ASCII_3A KEY_PERIOD + SHIFT_MASK // 58 :
#define ASCII_3B KEY_COMMA + SHIFT_MASK // 59 ;
#define ASCII_3C KEY_NON_US_100 // 60 <
#define ASCII_3D KEY_0 + SHIFT_MASK // 61 =
#define ASCII_3E KEY_NON_US_100 + SHIFT_MASK // 62 >
#define ASCII_3F KEY_MINUS + SHIFT_MASK // 63 ?
#define ASCII_40 KEY_V + ALTGR_MASK // 64 @
#define ASCII_41 KEY_A + SHIFT_MASK // 65 A
#define ASCII_42 KEY_B + SHIFT_MASK // 66 B
#define ASCII_43 KEY_C + SHIFT_MASK // 67 C
#define ASCII_44 KEY_D + SHIFT_MASK // 68 D
#define ASCII_45 KEY_E + SHIFT_MASK // 69 E
#define ASCII_46 KEY_F + SHIFT_MASK // 70 F
#define ASCII_47 KEY_G + SHIFT_MASK // 71 G
#define ASCII_48 KEY_H + SHIFT_MASK // 72 H
#define ASCII_49 KEY_I + SHIFT_MASK // 73 I
#define ASCII_4A KEY_J + SHIFT_MASK // 74 J
#define ASCII_4B KEY_K + SHIFT_MASK // 75 K
#define ASCII_4C KEY_L + SHIFT_MASK // 76 L
#define ASCII_4D KEY_M + SHIFT_MASK // 77 M
#define ASCII_4E KEY_N + SHIFT_MASK // 78 N
#define ASCII_4F KEY_O + SHIFT_MASK // 79 O
#define ASCII_50 KEY_P + SHIFT_MASK // 80 P
#define ASCII_51 KEY_Q + SHIFT_MASK // 81 Q
#define ASCII_52 KEY_R + SHIFT_MASK // 82 R
#define ASCII_53 KEY_S + SHIFT_MASK // 83 S
#define ASCII_54 KEY_T + SHIFT_MASK // 84 T
#define ASCII_55 KEY_U + SHIFT_MASK // 85 U
#define ASCII_56 KEY_V + SHIFT_MASK // 86 V
#define ASCII_57 KEY_W + SHIFT_MASK // 87 W
#define ASCII_58 KEY_X + SHIFT_MASK // 88 X
#define ASCII_59 KEY_Z + SHIFT_MASK // 89 Y
#define ASCII_5A KEY_Y + SHIFT_MASK // 90 Z
#define ASCII_5B KEY_F + ALTGR_MASK // 91 [
#define ASCII_5C KEY_Q + ALTGR_MASK // 92
#define ASCII_5D KEY_G + ALTGR_MASK // 93 ]
#define ASCII_5E CIRCUMFLEX_BITS + KEY_SPACE // 94 ^
#define ASCII_5F KEY_SLASH + SHIFT_MASK // 95 _ TODO: verify
#define ASCII_60 KEY_7 + ALTGR_MASK // 96 `
#define ASCII_61 KEY_A // 97 a
#define ASCII_62 KEY_B // 98 b
#define ASCII_63 KEY_C // 99 c
#define ASCII_64 KEY_D // 100 d
#define ASCII_65 KEY_E // 101 e
#define ASCII_66 KEY_F // 102 f
#define ASCII_67 KEY_G // 103 g
#define ASCII_68 KEY_H // 104 h
#define ASCII_69 KEY_I // 105 i
#define ASCII_6A KEY_J // 106 j
#define ASCII_6B KEY_K // 107 k
#define ASCII_6C KEY_L // 108 l
#define ASCII_6D KEY_M // 109 m
#define ASCII_6E KEY_N // 110 n
#define ASCII_6F KEY_O // 111 o
#define ASCII_70 KEY_P // 112 p
#define ASCII_71 KEY_Q // 113 q
#define ASCII_72 KEY_R // 114 r
#define ASCII_73 KEY_S // 115 s
#define ASCII_74 KEY_T // 116 t
#define ASCII_75 KEY_U // 117 u
#define ASCII_76 KEY_V // 118 v
#define ASCII_77 KEY_W // 119 w
#define ASCII_78 KEY_X // 120 x
#define ASCII_79 KEY_Z // 121 y
#define ASCII_7A KEY_Y // 122 z
#define ASCII_7B KEY_B + ALTGR_MASK // 123 {
#define ASCII_7C KEY_W + ALTGR_MASK // 124 |
#define ASCII_7D KEY_N + ALTGR_MASK // 125 }
#define ASCII_7E KEY_1 + ALTGR_MASK // 126 ~
#define ASCII_7F KEY_BACKSPACE // 127
#define ISO_8859_1_A0 KEY_SPACE // 160 Nonbreakng Space
#define ISO_8859_1_A1 0 // 161 ¡ Inverted Exclamation
#define ISO_8859_1_A2 0 // 162 ¢ Cent Sign
#define ISO_8859_1_A3 0 // 163 £ Pound Sign
#define ISO_8859_1_A4 KEY_BACKSLASH + ALTGR_MASK // 164 ¤ Currency Sign
#define ISO_8859_1_A5 0 // 165 ¥ YEN SIGN
#define ISO_8859_1_A6 0 // 166 ¦ BROKEN BAR
#define ISO_8859_1_A7 KEY_M + ALTGR_MASK // 167 § SECTION SIGN
#define ISO_8859_1_A8 DIAERESIS_BITS + KEY_SPACE // 168 ¨ DIAERESIS
#define ISO_8859_1_A9 0 // 169 © COPYRIGHT SIGN
#define ISO_8859_1_AA 0 // 170 ª FEMININE ORDINAL
#define ISO_8859_1_AB 0 // 171 « LEFT DOUBLE ANGLE QUOTE
#define ISO_8859_1_AC 0 // 172 ¬ NOT SIGN
#define ISO_8859_1_AD 0 // 173 SOFT HYPHEN
#define ISO_8859_1_AE 0 // 174 ® REGISTERED SIGN
#define ISO_8859_1_AF 0 // 175 ¯ MACRON
#define ISO_8859_1_B0 DEGREE_SIGN_BITS + KEY_SPACE // 176 ° DEGREE SIGN
#define ISO_8859_1_B1 0 // 177 ± PLUS-MINUS SIGN
#define ISO_8859_1_B2 0 // 178 ² SUPERSCRIPT TWO
#define ISO_8859_1_B3 0 // 179 ³ SUPERSCRIPT THREE
#define ISO_8859_1_B4 ACUTE_ACCENT_BITS + KEY_SPACE // 180 ´ ACUTE ACCENT
#define ISO_8859_1_B5 0 // 181 µ MICRO SIGN
#define ISO_8859_1_B6 0 // 182 ¶ PILCROW SIGN
#define ISO_8859_1_B7 0 // 183 · MIDDLE DOT
#define ISO_8859_1_B8 CEDILLA_BITS + KEY_SPACE // 184 ¸ CEDILLA
#define ISO_8859_1_B9 0 // 185 ¹ SUPERSCRIPT ONE
#define ISO_8859_1_BA 0 // 186 º MASCULINE ORDINAL
#define ISO_8859_1_BB 0 // 187 » RIGHT DOUBLE ANGLE QUOTE
#define ISO_8859_1_BC 0 // 188 ¼ FRACTION ONE QUARTER
#define ISO_8859_1_BD 0 // 189 ½ FRACTION ONE HALF
#define ISO_8859_1_BE 0 // 190 ¾ FRACTION THREE QUARTERS
#define ISO_8859_1_BF 0 // 191 ¿ INVERTED QUESTION MARK
#define ISO_8859_1_C0 0 // 192 À A GRAVE
#define ISO_8859_1_C1 ACUTE_ACCENT_BITS + KEY_A + SHIFT_MASK // 193 Á A ACUTE
#define ISO_8859_1_C2 CIRCUMFLEX_BITS + KEY_A + SHIFT_MASK // 194 Â A CIRCUMFLEX
#define ISO_8859_1_C3 0 // 195 Ã A TILDE
#define ISO_8859_1_C4 DIAERESIS_BITS + KEY_A + SHIFT_MASK // 196 Ä A DIAERESIS
#define ISO_8859_1_C5 0 // 197 Å A RING ABOVE
#define ISO_8859_1_C6 0 // 198 Æ AE
#define ISO_8859_1_C7 CEDILLA_BITS + KEY_C + SHIFT_MASK // 199 Ç C CEDILLA
#define ISO_8859_1_C8 0 // 200 È E GRAVE
#define ISO_8859_1_C9 ACUTE_ACCENT_BITS + KEY_E + SHIFT_MASK // 201 É E ACUTE
#define ISO_8859_1_CA CIRCUMFLEX_BITS + KEY_E + SHIFT_MASK // 202 Ê E CIRCUMFLEX
#define ISO_8859_1_CB DIAERESIS_BITS + KEY_E + SHIFT_MASK // 203 Ë E DIAERESIS
#define ISO_8859_1_CC 0 // 204 Ì I GRAVE
#define ISO_8859_1_CD ACUTE_ACCENT_BITS + KEY_I + SHIFT_MASK // 205 Í I ACUTE
#define ISO_8859_1_CE CIRCUMFLEX_BITS + KEY_I + SHIFT_MASK // 206 Î I CIRCUMFLEX
#define ISO_8859_1_CF DIAERESIS_BITS + KEY_I + SHIFT_MASK // 207 Ï I DIAERESIS
#define ISO_8859_1_D0 0 // 208 Ð ETH
#define ISO_8859_1_D1 0 // 209 Ñ N TILDE
#define ISO_8859_1_D2 0 // 210 Ò O GRAVE
#define ISO_8859_1_D3 ACUTE_ACCENT_BITS + KEY_O + SHIFT_MASK // 211 Ó O ACUTE
#define ISO_8859_1_D4 CIRCUMFLEX_BITS + KEY_O + SHIFT_MASK // 212 Ô O CIRCUMFLEX
#define ISO_8859_1_D5 0 // 213 Õ O TILDE
#define ISO_8859_1_D6 DIAERESIS_BITS + KEY_O + SHIFT_MASK // 214 Ö O DIAERESIS
#define ISO_8859_1_D7 KEY_RIGHT_BRACE + ALTGR_MASK // 215 × MULTIPLICATION
#define ISO_8859_1_D8 0 // 216 Ø O STROKE
#define ISO_8859_1_D9 0 // 217 Ù U GRAVE
#define ISO_8859_1_DA ACUTE_ACCENT_BITS + KEY_U + SHIFT_MASK // 218 Ú U ACUTE
#define ISO_8859_1_DB CIRCUMFLEX_BITS + KEY_U + SHIFT_MASK // 219 Û U CIRCUMFLEX
#define ISO_8859_1_DC DIAERESIS_BITS + KEY_U + SHIFT_MASK // 220 Ü U DIAERESIS
#define ISO_8859_1_DD ACUTE_ACCENT_BITS + KEY_Z + SHIFT_MASK // 221 Ý Y ACUTE
#define ISO_8859_1_DE 0 // 222 Þ THORN
#define ISO_8859_1_DF KEY_QUOTE + ALTGR_MASK // 223 ß SHARP S
#define ISO_8859_1_E0 0 // 224 à a GRAVE
#define ISO_8859_1_E1 ACUTE_ACCENT_BITS + KEY_A // 225 á a ACUTE
#define ISO_8859_1_E2 CIRCUMFLEX_BITS + KEY_A // 226 â a CIRCUMFLEX
#define ISO_8859_1_E3 0 // 227 ã a TILDE
#define ISO_8859_1_E4 DIAERESIS_BITS + KEY_A // 228 ä a DIAERESIS
#define ISO_8859_1_E5 0 // 229 å a RING ABOVE
#define ISO_8859_1_E6 0 // 230 æ ae
#define ISO_8859_1_E7 CEDILLA_BITS + KEY_C // 231 ç c CEDILLA
#define ISO_8859_1_E8 0 // 232 è e GRAVE
#define ISO_8859_1_E9 ACUTE_ACCENT_BITS + KEY_E // 233 é e ACUTE
#define ISO_8859_1_EA CIRCUMFLEX_BITS + KEY_E // 234 ê e CIRCUMFLEX
#define ISO_8859_1_EB DIAERESIS_BITS + KEY_E // 235 ë e DIAERESIS
#define ISO_8859_1_EC 0 // 236 ì i GRAVE
#define ISO_8859_1_ED ACUTE_ACCENT_BITS + KEY_I // 237 í i ACUTE
#define ISO_8859_1_EE CIRCUMFLEX_BITS + KEY_I // 238 î i CIRCUMFLEX
#define ISO_8859_1_EF DIAERESIS_BITS + KEY_I // 239 ï i DIAERESIS
#define ISO_8859_1_F0 0 // 240 ð ETH
#define ISO_8859_1_F1 0 // 241 ñ n TILDE
#define ISO_8859_1_F2 0 // 242 ò o GRAVE
#define ISO_8859_1_F3 ACUTE_ACCENT_BITS + KEY_O // 243 ó o ACUTE
#define ISO_8859_1_F4 CIRCUMFLEX_BITS + KEY_O // 244 ô o CIRCUMFLEX
#define ISO_8859_1_F5 0 // 245 õ o TILDE
#define ISO_8859_1_F6 DIAERESIS_BITS + KEY_O // 246 ö o DIAERESIS
#define ISO_8859_1_F7 KEY_LEFT_BRACE + ALTGR_MASK // 247 ÷ DIVISION
#define ISO_8859_1_F8 0 // 248 ø o STROKE
#define ISO_8859_1_F9 0 // 249 ù u GRAVE
#define ISO_8859_1_FA ACUTE_ACCENT_BITS + KEY_U // 250 ú u ACUTE
#define ISO_8859_1_FB CIRCUMFLEX_BITS + KEY_U // 251 û u CIRCUMFLEX
#define ISO_8859_1_FC DIAERESIS_BITS + KEY_U // 252 ü u DIAERESIS
#define ISO_8859_1_FD ACUTE_ACCENT_BITS + KEY_Z // 253 ý y ACUTE
#define ISO_8859_1_FE 0 // 254 þ THORN
#define ISO_8859_1_FF 0 // 255 ÿ y DIAERESIS
#define UNICODE_20AC KEY_E + ALTGR_MASK // € Euro Sign

#define UNICODE_EXTRA00 0x0160 // S caron
#define KEYCODE_EXTRA00 KEY_LEFT_BRACE + SHIFT_MASK
#define UNICODE_EXTRA01 0x0161 // s caron
#define KEYCODE_EXTRA01 KEY_LEFT_BRACE
#define UNICODE_EXTRA02 0x0110 // D with stroke
#define KEYCODE_EXTRA02 KEY_RIGHT_BRACE + SHIFT_MASK
#define UNICODE_EXTRA03 0x0111 // d with stroke
#define KEYCODE_EXTRA03 KEY_RIGHT_BRACE
#define UNICODE_EXTRA04 0x010C // C with caron
#define KEYCODE_EXTRA04 KEY_SEMICOLON + SHIFT_MASK
#define UNICODE_EXTRA05 0x010D // c with caron
#define KEYCODE_EXTRA05 KEY_SEMICOLON
#define UNICODE_EXTRA06 0x0106 // C with acute
#define KEYCODE_EXTRA06 KEY_QUOTE + SHIFT_MASK
#define UNICODE_EXTRA07 0x0107 // c with acute
#define KEYCODE_EXTRA07 KEY_QUOTE
#define UNICODE_EXTRA08 0x017D // Z with caron
#define KEYCODE_EXTRA08 KEY_BACKSLASH + SHIFT_MASK
#define UNICODE_EXTRA09 0x017E // z with caron
#define KEYCODE_EXTRA09 KEY_BACKSLASH

#define UNICODE_EXTRA10 0x0141 // L with stroke
#define KEYCODE_EXTRA10 KEY_L + ALTGR_MASK
#define UNICODE_EXTRA11 0x0142 // l with stroke
#define KEYCODE_EXTRA11 KEY_K + ALTGR_MASK
#define UNICODE_EXTRA12 0x010E // D with caron
#define KEYCODE_EXTRA12 CARON_BITS + KEY_D + SHIFT_MASK
#define UNICODE_EXTRA13 0x010F // d with caron
#define KEYCODE_EXTRA13 CARON_BITS + KEY_D
#define UNICODE_EXTRA14 0x011A // E with caron
#define KEYCODE_EXTRA14 CARON_BITS + KEY_E + SHIFT_MASK
#define UNICODE_EXTRA15 0x011B // e with caron
#define KEYCODE_EXTRA15 CARON_BITS + KEY_E
#define UNICODE_EXTRA16 0x013D // L with caron
#define KEYCODE_EXTRA16 CARON_BITS + KEY_L + SHIFT_MASK
#define UNICODE_EXTRA17 0x013E // l with caron
#define KEYCODE_EXTRA17 CARON_BITS + KEY_L
#define UNICODE_EXTRA18 0x0147 // N with caron
#define KEYCODE_EXTRA18 CARON_BITS + KEY_N + SHIFT_MASK
#define UNICODE_EXTRA19 0x0148 // n with caron
#define KEYCODE_EXTRA19 CARON_BITS + KEY_N

#define UNICODE_EXTRA20 0x0158 // R with caron
#define KEYCODE_EXTRA20 CARON_BITS + KEY_R + SHIFT_MASK
#define UNICODE_EXTRA21 0x0159 // r with caron
#define KEYCODE_EXTRA21 CARON_BITS + KEY_R
#define UNICODE_EXTRA22 0x0164 // T with caron
#define KEYCODE_EXTRA22 CARON_BITS + KEY_T + SHIFT_MASK
#define UNICODE_EXTRA23 0x0165 // t with caron
#define KEYCODE_EXTRA23 CARON_BITS + KEY_T
#define UNICODE_EXTRA24 0x0102 // A with breve
#define KEYCODE_EXTRA24 BREVE_BITS + KEY_A + SHIFT_MASK
#define UNICODE_EXTRA25 0x0103 // a with breve
#define KEYCODE_EXTRA25 BREVE_BITS + KEY_A
#define UNICODE_EXTRA26 0x016E // U with ring above TODO: verify
#define KEYCODE_EXTRA26 DEADKEY_DEGREE_SIGN + KEY_U + SHIFT_MASK
#define UNICODE_EXTRA27 0x016F // u with ring above TODO: verify
#define KEYCODE_EXTRA27 DEADKEY_DEGREE_SIGN + KEY_U
#define UNICODE_EXTRA28 0x0104 // A with ogonek
#define KEYCODE_EXTRA28 OGONEK_BITS + KEY_A + SHIFT_MASK
#define UNICODE_EXTRA29 0x0105 // a with ogonek
#define KEYCODE_EXTRA29 OGONEK_BITS + KEY_A

#define UNICODE_EXTRA30 0x0118 // E with ogonek
#define KEYCODE_EXTRA30 OGONEK_BITS + KEY_E + SHIFT_MASK
#define UNICODE_EXTRA31 0x0119 // e with ogonek
#define KEYCODE_EXTRA31 OGONEK_BITS + KEY_E
#define UNICODE_EXTRA32 0x017B // Z with dot above
#define KEYCODE_EXTRA32 DEADKEY_DOT_ABOVE + KEY_Z + SHIFT_MASK
#define UNICODE_EXTRA33 0x017C // z with dot above
#define KEYCODE_EXTRA33 DEADKEY_DOT_ABOVE + KEY_Z
#define UNICODE_EXTRA34 0x0139 // L with acute
#define KEYCODE_EXTRA34 ACUTE_ACCENT_BITS + KEY_L + SHIFT_MASK
#define UNICODE_EXTRA35 0x013A // l with acute
#define KEYCODE_EXTRA35 ACUTE_ACCENT_BITS + KEY_L
#define UNICODE_EXTRA36 0x0143 // N with acute
#define KEYCODE_EXTRA36 ACUTE_ACCENT_BITS + KEY_N + SHIFT_MASK
#define UNICODE_EXTRA37 0x0144 // n with acute
#define KEYCODE_EXTRA37 ACUTE_ACCENT_BITS + KEY_N
#define UNICODE_EXTRA38 0x0154 // R with acute
#define KEYCODE_EXTRA38 ACUTE_ACCENT_BITS + KEY_R + SHIFT_MASK
#define UNICODE_EXTRA39 0x0155 // r with acute
#define KEYCODE_EXTRA39 ACUTE_ACCENT_BITS + KEY_R

#define UNICODE_EXTRA40 0x015A // S with acute
#define KEYCODE_EXTRA40 ACUTE_ACCENT_BITS + KEY_S + SHIFT_MASK
#define UNICODE_EXTRA41 0x015B // s with acute
#define KEYCODE_EXTRA41 ACUTE_ACCENT_BITS + KEY_S
#define UNICODE_EXTRA42 0x0179 // Z with acute
#define KEYCODE_EXTRA42 ACUTE_ACCENT_BITS + KEY_Z + SHIFT_MASK
#define UNICODE_EXTRA43 0x017A // z with acute
#define KEYCODE_EXTRA43 ACUTE_ACCENT_BITS + KEY_Z
#define UNICODE_EXTRA44 0x0150 // O with double acute
#define KEYCODE_EXTRA44 DOUBLE_ACUTE_BITS + KEY_O + SHIFT_MASK
#define UNICODE_EXTRA45 0x0151 // o with double acute
#define KEYCODE_EXTRA45 DOUBLE_ACUTE_BITS + KEY_O
#define UNICODE_EXTRA46 0x0170 // U with double acute
#define KEYCODE_EXTRA46 DOUBLE_ACUTE_BITS + KEY_u + SHIFT_MASK
#define UNICODE_EXTRA47 0x0171 // u with double acute
#define KEYCODE_EXTRA47 DOUBLE_ACUTE_BITS + KEY_u
#define UNICODE_EXTRA48 0x015E // S with cedilla
#define KEYCODE_EXTRA48 CEDILLA_BITS + KEY_S + SHIFT_MASK
#define UNICODE_EXTRA49 0x015F // s with cedilla
#define KEYCODE_EXTRA49 CEDILLA_BITS + KEY_S

#define UNICODE_EXTRA50 0x201A // single low quote
#define KEYCODE_EXTRA50 KEY_TILDE
#define UNICODE_EXTRA51 0x20AC // euro sign
#define KEYCODE_EXTRA51 KEY_E + ALTGR_MASK

#endif // LAYOUT_SERBIAN_LATIN_ONLY




+ 3602
- 430
teensy3/kinetis.h
文件差異過大導致無法顯示
查看文件


+ 32
- 2
teensy3/main.cpp 查看文件

@@ -1,8 +1,38 @@
#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)
{
#if !defined(ARDUINO)
#ifdef USING_MAKEFILE

// To use Teensy 3.0 without Arduino, simply put your code here.
// For example:

+ 63
- 71
teensy3/math_helper.c 查看文件

@@ -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;
}
}
}
}
}
/**

+ 336
- 0
teensy3/memcpy-armv7m.S 查看文件

@@ -0,0 +1,336 @@
/*
* Copyright (c) 2013 ARM Ltd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the company may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#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.

If compiled with GCC, this file should be enclosed within following
pre-processing check:
if defined (__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__)

Prototype: void *memcpy (void *dst, const void *src, size_t count);

The job will be done in 5 steps.
Step 1: Align src/dest pointers, copy mis-aligned if fail to align both
Step 2: Repeatedly copy big block size of __OPT_BIG_BLOCK_SIZE
Step 3: Repeatedly copy big block size of __OPT_MID_BLOCK_SIZE
Step 4: Copy word by word
Step 5: Copy byte-to-byte

Tunable options:
__OPT_BIG_BLOCK_SIZE: Size of big block in words. Default to 64.
__OPT_MID_BLOCK_SIZE: Size of big block in words. Default to 16.
*/
#ifndef __OPT_BIG_BLOCK_SIZE
#define __OPT_BIG_BLOCK_SIZE (4 * 16)
#endif

#ifndef __OPT_MID_BLOCK_SIZE
#define __OPT_MID_BLOCK_SIZE (4 * 4)
#endif

#if __OPT_BIG_BLOCK_SIZE == 16
#define BEGIN_UNROLL_BIG_BLOCK \
.irp offset, 0,4,8,12
#elif __OPT_BIG_BLOCK_SIZE == 32
#define BEGIN_UNROLL_BIG_BLOCK \
.irp offset, 0,4,8,12,16,20,24,28
#elif __OPT_BIG_BLOCK_SIZE == 64
#define BEGIN_UNROLL_BIG_BLOCK \
.irp offset, 0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60
#else
#error "Illegal __OPT_BIG_BLOCK_SIZE"
#endif

#if __OPT_MID_BLOCK_SIZE == 8
#define BEGIN_UNROLL_MID_BLOCK \
.irp offset, 0,4
#elif __OPT_MID_BLOCK_SIZE == 16
#define BEGIN_UNROLL_MID_BLOCK \
.irp offset, 0,4,8,12
#else
#error "Illegal __OPT_MID_BLOCK_SIZE"
#endif

#define END_UNROLL .endr

.syntax unified
.text
.align 2
.global memcpy
.thumb
.thumb_func
.type memcpy, %function
memcpy:
@ r0: dst
@ r1: src
@ r2: len
#ifdef __ARM_FEATURE_UNALIGNED
/* In case of UNALIGNED access supported, ip is not used in
function body. */
mov ip, r0
#else
push {r0}
#endif
orr r3, r1, r0
ands r3, r3, #3
bne .Lmisaligned_copy

.Lbig_block:
subs r2, __OPT_BIG_BLOCK_SIZE
blo .Lmid_block

/* Kernel loop for big block copy */
.align 2
.Lbig_block_loop:
BEGIN_UNROLL_BIG_BLOCK
#ifdef __ARM_ARCH_7EM__
ldr r3, [r1], #4
str r3, [r0], #4
END_UNROLL
#else /* __ARM_ARCH_7M__ */
ldr r3, [r1, \offset]
str r3, [r0, \offset]
END_UNROLL
adds r0, __OPT_BIG_BLOCK_SIZE
adds r1, __OPT_BIG_BLOCK_SIZE
#endif
subs r2, __OPT_BIG_BLOCK_SIZE
bhs .Lbig_block_loop

.Lmid_block:
adds r2, __OPT_BIG_BLOCK_SIZE - __OPT_MID_BLOCK_SIZE
blo .Lcopy_word_by_word

/* Kernel loop for mid-block copy */
.align 2
.Lmid_block_loop:
BEGIN_UNROLL_MID_BLOCK
#ifdef __ARM_ARCH_7EM__
ldr r3, [r1], #4
str r3, [r0], #4
END_UNROLL
#else /* __ARM_ARCH_7M__ */
ldr r3, [r1, \offset]
str r3, [r0, \offset]
END_UNROLL
adds r0, __OPT_MID_BLOCK_SIZE
adds r1, __OPT_MID_BLOCK_SIZE
#endif
subs r2, __OPT_MID_BLOCK_SIZE
bhs .Lmid_block_loop

.Lcopy_word_by_word:
adds r2, __OPT_MID_BLOCK_SIZE - 4
blo .Lcopy_less_than_4

/* Kernel loop for small block copy */
.align 2
.Lcopy_word_by_word_loop:
ldr r3, [r1], #4
str r3, [r0], #4
subs r2, #4
bhs .Lcopy_word_by_word_loop

.Lcopy_less_than_4:
adds r2, #4
beq .Ldone

lsls r2, r2, #31
itt ne
ldrbne r3, [r1], #1
strbne r3, [r0], #1

bcc .Ldone
#ifdef __ARM_FEATURE_UNALIGNED
ldrh r3, [r1]
strh r3, [r0]
#else
ldrb r3, [r1]
strb r3, [r0]
ldrb r3, [r1, #1]
strb r3, [r0, #1]
#endif /* __ARM_FEATURE_UNALIGNED */

.Ldone:
#ifdef __ARM_FEATURE_UNALIGNED
mov r0, ip
#else
pop {r0}
#endif
bx lr

.align 2
.Lmisaligned_copy:
#ifdef __ARM_FEATURE_UNALIGNED
/* Define label DST_ALIGNED to BIG_BLOCK. It will go to aligned copy
once destination is adjusted to aligned. */
#define Ldst_aligned Lbig_block

/* Copy word by word using LDR when alignment can be done in hardware,
i.e., SCTLR.A is set, supporting unaligned access in LDR and STR. */

cmp r2, #8
blo .Lbyte_copy

/* if src is aligned, just go to the big block loop. */
lsls r3, r1, #30
beq .Ldst_aligned
#else
/* if len < 12, misalignment adjustment has more overhead than
just byte-to-byte copy. Also, len must >=8 to guarantee code
afterward work correctly. */
cmp r2, #12
blo .Lbyte_copy
#endif /* __ARM_FEATURE_UNALIGNED */

/* Align dst only, not trying to align src. That is the because
handling of aligned src and misaligned dst need more overhead than
otherwise. By doing this the worst case is when initial src is aligned,
additional up to 4 byte additional copy will executed, which is
acceptable. */

ands r3, r0, #3
beq .Ldst_aligned

rsb r3, #4
subs r2, r3

lsls r3, r3, #31
itt ne
ldrbne r3, [r1], #1
strbne r3, [r0], #1

bcc .Ldst_aligned

#ifdef __ARM_FEATURE_UNALIGNED
ldrh r3, [r1], #2
strh r3, [r0], #2
b .Ldst_aligned
#else
ldrb r3, [r1], #1
strb r3, [r0], #1
ldrb r3, [r1], #1
strb r3, [r0], #1
/* Now that dst is aligned */
.Ldst_aligned:
/* if r1 is aligned now, it means r0/r1 has the same misalignment,
and they are both aligned now. Go aligned copy. */
ands r3, r1, #3
beq .Lbig_block

/* dst is aligned, but src isn't. Misaligned copy. */

push {r4, r5}
subs r2, #4

/* Backward r1 by misaligned bytes, to make r1 aligned.
Since we need to restore r1 to unaligned address after the loop,
we need keep the offset bytes to ip and sub it from r1 afterward. */
subs r1, r3
rsb ip, r3, #4

/* Pre-load on word */
ldr r4, [r1], #4

cmp r3, #2
beq .Lmisaligned_copy_2_2
cmp r3, #3
beq .Lmisaligned_copy_3_1

.macro mis_src_copy shift
1:
lsrs r4, r4, \shift
ldr r3, [r1], #4
lsls r5, r3, 32-\shift
orr r4, r4, r5
str r4, [r0], #4
mov r4, r3
subs r2, #4
bhs 1b
.endm

.Lmisaligned_copy_1_3:
mis_src_copy shift=8
b .Lsrc_misaligned_tail

.Lmisaligned_copy_3_1:
mis_src_copy shift=24
b .Lsrc_misaligned_tail

.Lmisaligned_copy_2_2:
/* For 2_2 misalignment, ldr is still faster than 2 x ldrh. */
mis_src_copy shift=16

.Lsrc_misaligned_tail:
adds r2, #4
subs r1, ip
pop {r4, r5}

#endif /* __ARM_FEATURE_UNALIGNED */

.Lbyte_copy:
subs r2, #4
blo .Lcopy_less_than_4

.Lbyte_copy_loop:
subs r2, #1
ldrb r3, [r1], #1
strb r3, [r0], #1
bhs .Lbyte_copy_loop

ldrb r3, [r1]
strb r3, [r0]
ldrb r3, [r1, #1]
strb r3, [r0, #1]
ldrb r3, [r1, #2]
strb r3, [r0, #2]

#ifdef __ARM_FEATURE_UNALIGNED
mov r0, ip
#else
pop {r0}
#endif
bx lr

.size memcpy, .-memcpy
#endif

#endif // __MK20DX128__ || __MK20DX256__ || __MK66FX1M0__


+ 93
- 0
teensy3/memset.S 查看文件

@@ -0,0 +1,93 @@
/*
* Copyright (c) 2014 Travis Geiselbrecht
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
//#include <asm.h>
//#include <arch/arm/cores.h>
#if defined (__OPTIMIZE_SIZE__)
#if defined (__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__)
.global memset
.text
.syntax unified
.thumb
.align 2

/* void *memset(void *s, int c, size_t n); */
.type memset, %function
.thumb_func
memset:
//FUNCTION(memset)
// save the original pointer
push { r0, lr }

// check for zero length
cbz r2, .L_done

// short memsets aren't worth optimizing and make sure we have
// enough headroom to try to do dwordwise move optimization
cmp r2, #16
blt .L_bytewise

// see how many bytes we need to move to align to dword boundaries
and r3, r0, #7
cbz r3, .L_prepare_dwordwise
rsb r3, #8
subs r2, r3

.L_bytewise_align:
// bytewise to align memset
subs r3, r3, #1
strb r1, [r0], #1
bgt .L_bytewise_align

.L_prepare_dwordwise:
// fill a pair of 32 bit registers with the 8 bit value
uxtb r1, r1
orr r1, r1, r1, lsl #8
orr r1, r1, r1, lsl #16
mov r12, r1

// load the number of dwords left
lsrs r3, r2, #3

.L_dwordwise:
// dwordwise memset
subs r3, r3, #1
strd r1, r12, [r0], #8
bgt .L_dwordwise

// remaining bytes
ands r2, #7
beq .L_done

.L_bytewise:
// bytewise memset
subs r2, r2, #1
strb r1, [r0], #1
bgt .L_bytewise

.L_done:
// restore the base pointer as return value
pop { r0, pc }

#endif
#endif

+ 766
- 61
teensy3/mk20dx128.c
文件差異過大導致無法顯示
查看文件


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

@@ -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

+ 6
- 3
teensy3/mk20dx128.ld 查看文件

@@ -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
@@ -96,15 +96,18 @@ SECTIONS

.bss : {
. = ALIGN(4);
_sbss = .;
_sbss = .;
__bss_start__ = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
__bss_end = .;
__bss_end__ = .;
} > RAM

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



+ 7
- 39
teensy3/mk20dx256.ld 查看文件

@@ -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.
@@ -35,41 +35,6 @@ MEMORY
}


/* INCLUDE common.ld */


/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 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.
*/



SECTIONS
{
.text : {
@@ -131,15 +96,18 @@ SECTIONS

.bss : {
. = ALIGN(4);
_sbss = .;
_sbss = .;
__bss_start__ = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
__bss_end = .;
__bss_end__ = .;
} > RAM

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



+ 115
- 0
teensy3/mk64fx512.ld 查看文件

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

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


SECTIONS
{
.text : {
. = 0;
KEEP(*(.vectors))
*(.startup*)
/* TODO: does linker detect startup overflow onto flashconfig? */
. = 0x400;
KEEP(*(.flashconfig*))
*(.text*)
*(.rodata*)
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
} > FLASH = 0xFF

.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
__exidx_end = .;
} > FLASH
_etext = .;

.usbdescriptortable (NOLOAD) : {
/* . = ORIGIN(RAM); */
. = ALIGN(512);
*(.usbdescriptortable*)
} > RAM

.dmabuffers (NOLOAD) : {
. = ALIGN(4);
*(.dmabuffers*)
} > RAM

.usbbuffers (NOLOAD) : {
. = ALIGN(4);
*(.usbbuffers*)
} > RAM

.data : AT (_etext) {
. = ALIGN(4);
_sdata = .;
*(.fastrun*)
*(.data*)
. = ALIGN(4);
_edata = .;
} > RAM

.noinit (NOLOAD) : {
*(.noinit*)
} > RAM

.bss : {
. = ALIGN(4);
_sbss = .;
__bss_start__ = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
__bss_end = .;
__bss_end__ = .;
} > RAM

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





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

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

MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 1024K
RAM (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 256K
}


SECTIONS
{
.text : {
. = 0;
KEEP(*(.vectors))
*(.startup*)
/* TODO: does linker detect startup overflow onto flashconfig? */
. = 0x400;
KEEP(*(.flashconfig*))
*(.text*)
*(.rodata*)
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
} > FLASH = 0xFF

.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
__exidx_end = .;
} > FLASH
_etext = .;

.usbdescriptortable (NOLOAD) : {
/* . = ORIGIN(RAM); */
. = ALIGN(512);
*(.usbdescriptortable*)
} > RAM

.dmabuffers (NOLOAD) : {
. = ALIGN(4);
*(.dmabuffers*)
} > RAM

.usbbuffers (NOLOAD) : {
. = ALIGN(4);
*(.usbbuffers*)
} > RAM

.data : AT (_etext) {
. = ALIGN(4);
_sdata = .;
*(.fastrun*)
*(.data*)
. = ALIGN(4);
_edata = .;
} > RAM

.noinit (NOLOAD) : {
*(.noinit*)
} > RAM

.bss : {
. = ALIGN(4);
_sbss = .;
__bss_start__ = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
__bss_end = .;
__bss_end__ = .;
} > RAM

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





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

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

MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 62K
RAM (rwx) : ORIGIN = 0x1FFFF800, LENGTH = 8K
}


SECTIONS
{
.text : {
. = 0;
KEEP(*(.vectors))
*(.startup*)
/* TODO: does linker detect startup overflow onto flashconfig? */
. = 0x400;
KEEP(*(.flashconfig*))
*(.text*)
*(.rodata*)
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
} > FLASH = 0xFF

.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
__exidx_end = .;
} > FLASH
_etext = .;

.usbdescriptortable (NOLOAD) : {
/* . = ORIGIN(RAM); */
. = ALIGN(512);
*(.usbdescriptortable*)
} > RAM

.dmabuffers (NOLOAD) : {
. = ALIGN(4);
*(.dmabuffers*)
} > RAM

.usbbuffers (NOLOAD) : {
. = ALIGN(4);
*(.usbbuffers*)
} > RAM

.data : AT (_etext) {
. = ALIGN(4);
_sdata = .;
*(.fastrun*)
*(.data*)
. = ALIGN(4);
_edata = .;
} > RAM

.noinit (NOLOAD) : {
*(.noinit*)
} > RAM

.bss : {
. = ALIGN(4);
_sbss = .;
__bss_start__ = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
__bss_end = .;
__bss_end__ = .;
} > RAM

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



+ 35
- 0
teensy3/new.cpp 查看文件

@@ -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 查看文件

@@ -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__)));


+ 151
- 17
teensy3/nonstd.c 查看文件

@@ -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.
@@ -30,18 +30,11 @@

#include "avr_functions.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

size_t strlen(const char *s)
{
size_t n=0;

while (*s++) n++;
return n;
}


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

// TODO: actually write an efficient dtostrf()....
#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)
{
char format[20];
sprintf(format, "%%%d.%df", width, precision);
sprintf(buf, format, val);
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";
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;
if (pad > 0) {
e += pad;
while (pad-- > 0) *p++ = ' ';
}
if (sign) *p++ = '-';
if (decpt == 0 && precision > 0) {
*p++ = '0';
*p++ = '.';
}
else if (decpt < 0 && precision > 0) {
*p++ = '0';
*p++ = '.';
// print leading zeros
while ( decpt < 0 ) {
decpt++;
*p++ = '0';
}
}
// print digits
while (p < e) {
*p++ = *s++;
if (p == e) break;
if (--decpt == 0) *p++ = '.';
}
if (width < 0) {
pad = (reqd + width) * -1;
while (pad-- > 0) *p++ = ' ';
}
*p = 0;

//char format[20];
//sprintf(format, "%%%d.%df", width, precision);
//sprintf(buf, format, val);
return buf;
}


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

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

+ 179
- 32
teensy3/pins_arduino.h 查看文件

@@ -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,54 +33,167 @@

#include <stdint.h>

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

#if defined(__MK20DX128__)
#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__)
#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__)
#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__)
#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 34
#define NUM_ANALOG_INPUTS 14

#define analogInputToDigitalPin(p) (((p) < 10) ? (p) + 14 : -1)
#define digitalPinHasPWM(p) (((p) >= 3 && (p) <= 6) || (p) == 9 || (p) == 10 || ((p) >= 20 && (p) <= 23))
#define NUM_DIGITAL_PINS CORE_NUM_DIGITAL
#define NUM_ANALOG_INPUTS CORE_NUM_ANALOG


#define NOT_AN_INTERRUPT -1
#define digitalPinToInterrupt(p) ((p) < NUM_DIGITAL_PINS ? (p) : -1)


#if defined(__MK20DX128__)
#define analogInputToDigitalPin(p) (((p) <= 9) ? (p) + 14 : (((p) <= 13) ? (p) + 24 : -1))
#define digitalPinHasPWM(p) (((p) >= 3 && (p) <= 6) || (p) == 9 || (p) == 10 || ((p) >= 20 && (p) <= 23))
#define digitalPinToInterrupt(p) ((p) < NUM_DIGITAL_PINS ? (p) : -1)
#elif defined(__MK20DX256__)
#define analogInputToDigitalPin(p) (((p) <= 9) ? (p) + 14 : (((p) <= 13) ? (p) + 24 : (((p) == 14) ? 40 : (((p) <= 20) ? (p) + 11 : -1))))
#define digitalPinHasPWM(p) (((p) >= 3 && (p) <= 6) || (p) == 9 || (p) == 10 || ((p) >= 20 && (p) <= 23) || (p) == 25 || (p) == 32)
#define digitalPinToInterrupt(p) ((p) < NUM_DIGITAL_PINS ? (p) : -1)
#elif defined(__MKL26Z64__)
#define analogInputToDigitalPin(p) (((p) <= 9) ? (p) + 14 : (((p) <= 12) ? (p) + 14 : -1))
#define digitalPinHasPWM(p) ((p) == 3 || (p) == 4 || (p) == 6 || (p) == 9 || (p) == 10 || (p) == 16 || (p) == 17 || (p) == 20 || (p) == 22 || (p) == 23)
#define digitalPinToInterrupt(p) ((((p) >= 2 && (p) <= 15) || ((p) >= 20 && (p) <= 23)) ? (p) : -1)
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
// TODO analogInputToDigitalPin needs update...
#define analogInputToDigitalPin(p) (((p) <= 9) ? (p) + 14 : (((p) >= 12 && (p) <= 20) ? (p) + 19 : -1))
#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)
#endif

#define digitalPinToPCICR(p) ((volatile uint8_t *)0)
#define digitalPinToPCICRbit(p) (0)
#define digitalPinToPCIFR(p) ((volatile uint8_t *)0)
#define digitalPinToPCIFRbit(p) (0)
#define digitalPinToPCMSK(p) ((volatile uint8_t *)0)
#define digitalPinToPCMSKbit(p) (0)


#if defined(KINETISK)
struct digital_pin_bitband_and_config_table_struct {
volatile uint32_t *reg;
volatile uint32_t *config;
};
extern const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM[];

// compatibility macros
#define digitalPinToPort(pin) (pin)
#define digitalPinToBitMask(pin) (1)
@@ -91,11 +204,32 @@ extern const struct digital_pin_bitband_and_config_table_struct digital_pin_to_i
#define portInputRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 128))
#define portModeRegister(pin) ((volatile uint8_t *)(digital_pin_to_info_PGM[(pin)].reg + 160))
#define portConfigRegister(pin) ((volatile uint32_t *)(digital_pin_to_info_PGM[(pin)].config))


#define digitalPinToPortReg(pin) (portOutputRegister(pin))
#define digitalPinToBit(pin) (1)

#elif defined(KINETISL)
struct digital_pin_bitband_and_config_table_struct {
volatile uint8_t *reg;
volatile uint32_t *config;
uint8_t mask;
};
extern const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM[];
// compatibility macros
#define digitalPinToPort(pin) (pin)
#define digitalPinToBitMask(pin) (digital_pin_to_info_PGM[(pin)].mask)
#define portOutputRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 0))
#define portSetRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 4))
#define portClearRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 8))
#define portToggleRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 12))
#define portInputRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 16))
#define portModeRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 20))
#define portConfigRegister(pin) ((digital_pin_to_info_PGM[(pin)].config))
#define digitalPinToPortReg(pin) (portOutputRegister(pin))
//#define digitalPinToBit(pin) (1)

#endif



#define NOT_ON_TIMER 0
static inline uint8_t digitalPinToTimer(uint8_t) __attribute__((always_inline, unused));
@@ -123,7 +257,11 @@ static inline uint8_t digitalPinToTimer(uint8_t pin)
// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX
// pins are NOT connected to anything by default.
//
#if F_CPU >= 20000000 && !defined(USB_DISABLED)
#define SERIAL_PORT_MONITOR Serial
#else
#define SERIAL_PORT_MONITOR Serial1
#endif
#define SERIAL_PORT_USBVIRTUAL Serial
#define SERIAL_PORT_HARDWARE Serial1
#define SERIAL_PORT_HARDWARE1 Serial2
@@ -131,6 +269,15 @@ 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

#endif

+ 720
- 198
teensy3/pins_teensy.c
文件差異過大導致無法顯示
查看文件


+ 79
- 0
teensy3/ser_print.c 查看文件

@@ -0,0 +1,79 @@
/* 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"

#ifdef KINETISL

// Simple polling-only Serial1 support for Teensy-LC

// this is really only useful for extremely low-level troubleshooting

void ser_write(uint8_t c)
{
while ((UART0_S1 & UART_S1_TDRE) == 0) /* wait */ ;
UART0_D = c;
}

void ser_print(const char *p)
{
while (*p) {
char c = *p++;
if (c == '\n') ser_write('\r');
ser_write(c);
}
}

static void ser_print_hex1(unsigned int n)
{
n &= 15;
if (n < 10) {
ser_write('0' + n);
} else {
ser_write('A' - 10 + n);
}
}

void ser_print_hex(unsigned int n)
{
ser_print_hex1(n >> 4);
ser_print_hex1(n);
}

void ser_print_hex32(unsigned int n)
{
ser_print_hex(n >> 24);
ser_print_hex(n >> 16);
ser_print_hex(n >> 8);
ser_print_hex(n);
}

#endif

+ 40
- 0
teensy3/ser_print.h 查看文件

@@ -0,0 +1,40 @@
/* 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"{
#endif
void ser_print(const char *p);
void ser_print_hex(unsigned int n);
void ser_print_hex32(unsigned int n);
#ifdef __cplusplus
} // extern "C"
#endif


+ 331
- 62
teensy3/serial1.c 查看文件

@@ -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,8 +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
#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


@@ -53,29 +59,51 @@ 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;
static volatile uint8_t *transmit_pin=NULL;
#if TX_BUFFER_SIZE > 255
#if defined(KINETISK)
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
#elif defined(KINETISL)
static volatile uint8_t *transmit_pin=NULL;
static uint8_t transmit_mask=0;
#define transmit_assert() *(transmit_pin+4) = transmit_mask;
#define transmit_deassert() *(transmit_pin+8) = transmit_mask;
static volatile uint8_t *rts_pin=NULL;
static uint8_t rts_mask=0;
#define rts_assert() *(rts_pin+8) = rts_mask;
#define rts_deassert() *(rts_pin+4) = rts_mask;
#endif
#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
static volatile uint8_t rx_buffer_head = 0;
static volatile uint8_t rx_buffer_tail = 0;
#endif
static uint8_t rx_pin_num = 0;
static uint8_t tx_pin_num = 1;

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

#ifdef HAS_KINETISK_UART0_FIFO
#define C2_ENABLE UART_C2_TE | UART_C2_RE | UART_C2_RIE | UART_C2_ILIE
#else
#define C2_ENABLE UART_C2_TE | UART_C2_RE | UART_C2_RIE
#endif
#define C2_TX_ACTIVE C2_ENABLE | UART_C2_TIE
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE
#define C2_TX_INACTIVE C2_ENABLE
@@ -88,16 +116,48 @@ void serial_begin(uint32_t divisor)
tx_buffer_head = 0;
tx_buffer_tail = 0;
transmitting = 0;
CORE_PIN0_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3);
CORE_PIN1_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3);
switch (rx_pin_num) {
case 0: CORE_PIN0_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break;
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) {
case 1: CORE_PIN1_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); break;
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;
//UART0_C1 = 0;
#ifdef HAS_KINETISK_UART0_FIFO
UART0_C1 = UART_C1_ILT;
UART0_TWFIFO = 2; // tx watermark, causes S1_TDRE to set
UART0_RWFIFO = 4; // rx watermark, causes S1_RDRF to set
UART0_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE;
#else
UART0_C1 = 0;
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;
#endif
UART0_C2 = C2_TX_INACTIVE;
NVIC_SET_PRIORITY(IRQ_UART0_STATUS, IRQ_PRIORITY);
NVIC_ENABLE_IRQ(IRQ_UART0_STATUS);
@@ -105,24 +165,32 @@ void serial_begin(uint32_t divisor)

void serial_format(uint32_t format)
{
uint8_t c;
c = UART0_C1;
c = (c & ~0x13) | (format & 0x03); // configure parity
if (format & 0x04) c |= 0x10; // 9 bits (might include parity)
UART0_C1 = c;
if ((format & 0x0F) == 0x04) UART0_C3 |= 0x40; // 8N2 is 9 bit with 9th bit always 1
c = UART0_S2 & ~0x10;
if (format & 0x10) c |= 0x10; // rx invert
UART0_S2 = c;
c = UART0_C3 & ~0x10;
if (format & 0x20) c |= 0x10; // tx invert
UART0_C3 = c;
uint8_t c;
c = UART0_C1;
c = (c & ~0x13) | (format & 0x03); // configure parity
if (format & 0x04) c |= 0x10; // 9 bits (might include parity)
UART0_C1 = c;
if ((format & 0x0F) == 0x04) UART0_C3 |= 0x40; // 8N2 is 9 bit with 9th bit always 1
c = UART0_S2 & ~0x10;
if (format & 0x10) c |= 0x10; // rx invert
UART0_S2 = c;
c = UART0_C3 & ~0x10;
if (format & 0x20) c |= 0x10; // tx invert
UART0_C3 = c;
#ifdef SERIAL_9BIT_SUPPORT
c = UART0_C4 & 0x1F;
if (format & 0x08) c |= 0x20; // 9 bit mode with parity (requires 10 bits)
UART0_C4 = c;
use9Bits = format & 0x80;
c = UART0_C4 & 0x1F;
if (format & 0x08) c |= 0x20; // 9 bit mode with parity (requires 10 bits)
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
}

@@ -132,10 +200,33 @@ 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();
}

void serial_set_transmit_pin(uint8_t pin)
@@ -144,6 +235,126 @@ void serial_set_transmit_pin(uint8_t pin)
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
transmit_pin = portOutputRegister(pin);
#if defined(KINETISL)
transmit_mask = digitalPinToBitMask(pin);
#endif
}

void serial_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_UART0)) {
switch (tx_pin_num & 127) {
case 1: CORE_PIN1_CONFIG = 0; break; // PTB17
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) {
cfg = PORT_PCR_DSE | PORT_PCR_ODE;
} else {
cfg = PORT_PCR_DSE | PORT_PCR_SRE;
}
switch (pin & 127) {
case 1: CORE_PIN1_CONFIG = cfg | PORT_PCR_MUX(3); break;
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
}
}
tx_pin_num = pin;
}

void serial_set_rx(uint8_t pin)
{
if (pin == rx_pin_num) return;
if ((SIM_SCGC4 & SIM_SCGC4_UART0)) {
switch (rx_pin_num) {
case 0: CORE_PIN0_CONFIG = 0; break; // PTB16
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) {
case 0: CORE_PIN0_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break;
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
}
}
rx_pin_num = pin;
}



int serial_set_rts(uint8_t pin)
{
if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return 0;
if (pin < CORE_NUM_DIGITAL) {
rts_pin = portOutputRegister(pin);
#if defined(KINETISL)
rts_mask = digitalPinToBitMask(pin);
#endif
pinMode(pin, OUTPUT);
rts_assert();
} else {
rts_pin = NULL;
return 0;
}
/*
if (pin == 6) {
CORE_PIN6_CONFIG = PORT_PCR_MUX(3);
} else if (pin == 19) {
CORE_PIN19_CONFIG = PORT_PCR_MUX(3);
} else {
UART0_MODEM &= ~UART_MODEM_RXRTSE;
return 0;
}
UART0_MODEM |= UART_MODEM_RXRTSE;
*/
return 1;
}

int serial_set_cts(uint8_t pin)
{
#if defined(KINETISK)
if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return 0;
if (pin == 18) {
CORE_PIN18_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_PE; // weak pulldown
} else if (pin == 20) {
CORE_PIN20_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_PE; // weak pulldown
} else {
UART0_MODEM &= ~UART_MODEM_TXCTSE;
return 0;
}
UART0_MODEM |= UART_MODEM_TXCTSE;
return 1;
#else
return 0;
#endif
}

void serial_putchar(uint32_t c)
@@ -151,15 +362,15 @@ void serial_putchar(uint32_t c)
uint32_t head, n;

if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return;
if (transmit_pin) *transmit_pin = 1;
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;
@@ -175,25 +386,26 @@ void serial_putchar(uint32_t c)
UART0_C2 = C2_TX_ACTIVE;
}

#ifdef HAS_KINETISK_UART0_FIFO
void serial_write(const void *buf, unsigned int count)
{
const uint8_t *p = (const uint8_t *)buf;
const uint8_t *end = p + count;
uint32_t head, n;
uint32_t head, n;

if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return;
if (transmit_pin) *transmit_pin = 1;
if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return;
if (transmit_pin) transmit_assert();
while (p < end) {
head = tx_buffer_head;
if (++head >= TX_BUFFER_SIZE) head = 0;
head = tx_buffer_head;
if (++head >= SERIAL1_TX_BUFFER_SIZE) head = 0;
if (tx_buffer_tail == head) {
UART0_C2 = C2_TX_ACTIVE;
UART0_C2 = C2_TX_ACTIVE;
do {
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;
@@ -204,12 +416,19 @@ void serial_write(const void *buf, unsigned int count)
}
} while (tx_buffer_tail == head);
}
tx_buffer[head] = *p++;
transmitting = 1;
tx_buffer_head = head;
tx_buffer[head] = *p++;
transmitting = 1;
tx_buffer_head = head;
}
UART0_C2 = C2_TX_ACTIVE;
UART0_C2 = C2_TX_ACTIVE;
}
#else
void serial_write(const void *buf, unsigned int count)
{
const uint8_t *p = (const uint8_t *)buf;
while (count-- > 0) serial_putchar(*p++);
}
#endif

void serial_flush(void)
{
@@ -222,7 +441,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;
}

@@ -233,7 +452,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)
@@ -244,9 +463,15 @@ 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 = SERIAL1_RX_BUFFER_SIZE + head - tail;
if (avail <= RTS_LOW_WATERMARK) rts_assert();
}
return c;
}

@@ -257,31 +482,37 @@ 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];
}

void serial_clear(void)
{
#ifdef HAS_KINETISK_UART0_FIFO
if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return;
UART0_C2 &= ~(UART_C2_RE | UART_C2_RIE | UART_C2_ILIE);
UART0_CFIFO = UART_CFIFO_RXFLUSH;
UART0_C2 |= (UART_C2_RE | UART_C2_RIE | UART_C2_ILIE);
#endif
rx_buffer_head = rx_buffer_tail;
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
// 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
// LIN break detect UART_S2_LBKDIF
// RxD pin active edge UART_S2_RXEDGIF

void uart0_status_isr(void)
{
uint32_t head, newhead, tail, n;
uint8_t avail, c;
uint32_t head, tail, n;
uint8_t c;
#ifdef HAS_KINETISK_UART0_FIFO
uint32_t newhead;
uint8_t avail;

if (UART0_S1 & (UART_S1_RDRF | UART_S1_IDLE)) {
__disable_irq();
@@ -310,16 +541,25 @@ void uart0_status_isr(void)
head = rx_buffer_head;
tail = rx_buffer_tail;
do {
n = UART0_D;
if (use9Bits && (UART0_C3 & 0x80)) n |= 0x100;
if (use9Bits && (UART0_C3 & 0x80)) {
n = UART0_D | 0x100;
} else {
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;
}
} while (--avail > 0);
rx_buffer_head = head;
if (rts_pin) {
int avail;
if (head >= tail) avail = head - tail;
else avail = SERIAL1_RX_BUFFER_SIZE + head - tail;
if (avail >= RTS_HIGH_WATERMARK) rts_deassert();
}
}
}
c = UART0_C2;
@@ -328,7 +568,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);
@@ -337,9 +577,38 @@ void uart0_status_isr(void)
tx_buffer_tail = tail;
if (UART0_S1 & UART_S1_TDRE) UART0_C2 = C2_TX_COMPLETING;
}
#else
if (UART0_S1 & UART_S1_RDRF) {
if (use9Bits && (UART0_C3 & 0x80)) {
n = UART0_D | 0x100;
} else {
n = UART0_D;
}
head = rx_buffer_head + 1;
if (head >= SERIAL1_RX_BUFFER_SIZE) head = 0;
if (head != rx_buffer_tail) {
rx_buffer[head] = n;
rx_buffer_head = head;
}
}
c = UART0_C2;
if ((c & UART_C2_TIE) && (UART0_S1 & UART_S1_TDRE)) {
head = tx_buffer_head;
tail = tx_buffer_tail;
if (head == tail) {
UART0_C2 = C2_TX_COMPLETING;
} else {
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;
tx_buffer_tail = tail;
}
}
#endif
if ((c & UART_C2_TCIE) && (UART0_S1 & UART_S1_TC)) {
transmitting = 0;
if (transmit_pin) *transmit_pin = 0;
if (transmit_pin) transmit_deassert();
UART0_C2 = C2_TX_INACTIVE;
}
}

+ 0
- 0
teensy3/serial1_doughboy.txt 查看文件


部分文件因文件數量過多而無法顯示

Loading…
取消
儲存