diff --git a/Packages_Patches/hardware/teensy/avr/boards.txt b/Packages_Patches/hardware/teensy/avr/boards.txt
index 0bf2b19..693927f 100644
--- a/Packages_Patches/hardware/teensy/avr/boards.txt
+++ b/Packages_Patches/hardware/teensy/avr/boards.txt
@@ -4,12 +4,20 @@ menu.opt=Optimize
 menu.keys=Keyboard Layout
 
 
+# TODO: consider whether these compiler warnings are worthwhile
+# -Wno-error=unused-function
+# -Wno-error=unused-but-set-variable
+# -Wno-error=unused-variable
+# -Wno-unused-parameter
+# -Wno-unused-but-set-parameter
+# -Wno-sign-compare
+
+
 teensy41.name=Teensy 4.1
-teensy41.upload.maximum_size=8126464
+#teensy41.upload.maximum_size=8126464
 teensy41.build.board=TEENSY41
 teensy41.build.flags.ld=-Wl,--gc-sections,--relax "-T{build.core.path}/imxrt1062_t41.ld"
-teensy41.upload.maximum_data_size=524288
-#teensy41.upload.maximum_data_size=1048576
+#teensy41.upload.maximum_data_size=524288
 teensy41.upload.tool=teensyloader
 teensy41.upload.protocol=halfkay
 teensy41.build.core=teensy4
@@ -27,7 +35,7 @@ teensy41.build.flags.common=-g -Wall -ffunction-sections -fdata-sections -nostdl
 teensy41.build.flags.dep=-MMD
 teensy41.build.flags.optimize=-Os
 teensy41.build.flags.cpu=-mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16
-teensy41.build.flags.defs=-D__IMXRT1062__ -DTEENSYDUINO=152
+teensy41.build.flags.defs=-D__IMXRT1062__ -DTEENSYDUINO=156
 teensy41.build.flags.cpp=-std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing
 teensy41.build.flags.c=
 teensy41.build.flags.S=-x assembler-with-cpp
@@ -203,11 +211,212 @@ teensy41.menu.keys.usint.build.keylayout=US_INTERNATIONAL
 
 
 
+
+teensyMM.name=Teensy MicroMod
+#teensyMM.upload.maximum_size=16515072
+teensyMM.build.board=TEENSY_MICROMOD
+teensyMM.build.flags.ld=-Wl,--gc-sections,--relax "-T{build.core.path}/imxrt1062_mm.ld"
+#teensyMM.upload.maximum_data_size=524288
+#teensyMM.upload.maximum_data_size=1048576
+teensyMM.upload.tool=teensyloader
+teensyMM.upload.protocol=halfkay
+teensyMM.build.core=teensy4
+teensyMM.build.mcu=imxrt1062
+teensyMM.build.warn_data_percentage=99
+teensyMM.build.toolchain=arm/bin/
+teensyMM.build.command.gcc=arm-none-eabi-gcc
+teensyMM.build.command.g++=arm-none-eabi-g++
+teensyMM.build.command.ar=arm-none-eabi-gcc-ar
+teensyMM.build.command.objcopy=arm-none-eabi-objcopy
+teensyMM.build.command.objdump=arm-none-eabi-objdump
+teensyMM.build.command.linker=arm-none-eabi-gcc
+teensyMM.build.command.size=arm-none-eabi-size
+teensyMM.build.flags.common=-g -Wall -ffunction-sections -fdata-sections -nostdlib
+teensyMM.build.flags.dep=-MMD
+teensyMM.build.flags.optimize=-Os
+teensyMM.build.flags.cpu=-mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16
+teensyMM.build.flags.defs=-D__IMXRT1062__ -DTEENSYDUINO=156
+teensyMM.build.flags.cpp=-std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing
+teensyMM.build.flags.c=
+teensyMM.build.flags.S=-x assembler-with-cpp
+teensyMM.build.flags.libs=-larm_cortexM7lfsp_math -lm -lstdc++
+teensyMM.serial.restart_cmd=false
+teensyMM.menu.usb.serial=Serial
+teensyMM.menu.usb.serial.build.usbtype=USB_SERIAL
+teensyMM.menu.usb.serial2=Dual Serial
+teensyMM.menu.usb.serial2.build.usbtype=USB_DUAL_SERIAL
+teensyMM.menu.usb.serial3=Triple Serial
+teensyMM.menu.usb.serial3.build.usbtype=USB_TRIPLE_SERIAL
+teensyMM.menu.usb.keyboard=Keyboard
+teensyMM.menu.usb.keyboard.build.usbtype=USB_KEYBOARDONLY
+teensyMM.menu.usb.keyboard.fake_serial=teensy_gateway
+teensyMM.menu.usb.touch=Keyboard + Touch Screen
+teensyMM.menu.usb.touch.build.usbtype=USB_TOUCHSCREEN
+teensyMM.menu.usb.touch.fake_serial=teensy_gateway
+teensyMM.menu.usb.hidtouch=Keyboard + Mouse + Touch Screen
+teensyMM.menu.usb.hidtouch.build.usbtype=USB_HID_TOUCHSCREEN
+teensyMM.menu.usb.hidtouch.fake_serial=teensy_gateway
+teensyMM.menu.usb.hid=Keyboard + Mouse + Joystick
+teensyMM.menu.usb.hid.build.usbtype=USB_HID
+teensyMM.menu.usb.hid.fake_serial=teensy_gateway
+teensyMM.menu.usb.serialhid=Serial + Keyboard + Mouse + Joystick
+teensyMM.menu.usb.serialhid.build.usbtype=USB_SERIAL_HID
+teensyMM.menu.usb.midi=MIDI
+teensyMM.menu.usb.midi.build.usbtype=USB_MIDI
+teensyMM.menu.usb.midi.fake_serial=teensy_gateway
+teensyMM.menu.usb.midi4=MIDIx4
+teensyMM.menu.usb.midi4.build.usbtype=USB_MIDI4
+teensyMM.menu.usb.midi4.fake_serial=teensy_gateway
+teensyMM.menu.usb.midi16=MIDIx16
+teensyMM.menu.usb.midi16.build.usbtype=USB_MIDI16
+teensyMM.menu.usb.midi16.fake_serial=teensy_gateway
+teensyMM.menu.usb.serialmidi=Serial + MIDI
+teensyMM.menu.usb.serialmidi.build.usbtype=USB_MIDI_SERIAL
+teensyMM.menu.usb.serialmidi4=Serial + MIDIx4
+teensyMM.menu.usb.serialmidi4.build.usbtype=USB_MIDI4_SERIAL
+teensyMM.menu.usb.serialmidi16=Serial + MIDIx16
+teensyMM.menu.usb.serialmidi16.build.usbtype=USB_MIDI16_SERIAL
+teensyMM.menu.usb.audio=Audio
+teensyMM.menu.usb.audio.build.usbtype=USB_AUDIO
+teensyMM.menu.usb.audio.fake_serial=teensy_gateway
+teensyMM.menu.usb.serialmidiaudio=Serial + MIDI + Audio
+teensyMM.menu.usb.serialmidiaudio.build.usbtype=USB_MIDI_AUDIO_SERIAL
+teensyMM.menu.usb.serialmidi16audio=Serial + MIDIx16 + Audio
+teensyMM.menu.usb.serialmidi16audio.build.usbtype=USB_MIDI16_AUDIO_SERIAL
+teensyMM.menu.usb.mtp=MTP Disk (Experimental)
+teensyMM.menu.usb.mtp.build.usbtype=USB_MTPDISK
+teensyMM.menu.usb.mtp.fake_serial=teensy_gateway
+teensyMM.menu.usb.rawhid=Raw HID
+teensyMM.menu.usb.rawhid.build.usbtype=USB_RAWHID
+teensyMM.menu.usb.rawhid.fake_serial=teensy_gateway
+teensyMM.menu.usb.flightsim=Flight Sim Controls
+teensyMM.menu.usb.flightsim.build.usbtype=USB_FLIGHTSIM
+teensyMM.menu.usb.flightsim.fake_serial=teensy_gateway
+teensyMM.menu.usb.flightsimjoystick=Flight Sim Controls + Joystick
+teensyMM.menu.usb.flightsimjoystick.build.usbtype=USB_FLIGHTSIM_JOYSTICK
+teensyMM.menu.usb.flightsimjoystick.fake_serial=teensy_gateway
+#teensyMM.menu.usb.disable=No USB
+#teensyMM.menu.usb.disable.build.usbtype=USB_DISABLED
+
+teensyMM.menu.speed.600=600 MHz
+teensyMM.menu.speed.528=528 MHz
+teensyMM.menu.speed.450=450 MHz
+teensyMM.menu.speed.396=396 MHz
+teensyMM.menu.speed.150=150 MHz
+teensyMM.menu.speed.24=24 MHz
+teensyMM.menu.speed.720=720 MHz (overclock)
+teensyMM.menu.speed.816=816 MHz (overclock)
+teensyMM.menu.speed.912=912 MHz (overclock, cooling req'd)
+teensyMM.menu.speed.960=960 MHz (overclock, cooling req'd)
+teensyMM.menu.speed.1008=1.008 GHz (overclock, cooling req'd)
+teensyMM.menu.speed.1008.build.fcpu=1008000000
+teensyMM.menu.speed.960.build.fcpu=960000000
+teensyMM.menu.speed.912.build.fcpu=912000000
+teensyMM.menu.speed.816.build.fcpu=816000000
+teensyMM.menu.speed.720.build.fcpu=720000000
+teensyMM.menu.speed.600.build.fcpu=600000000
+teensyMM.menu.speed.528.build.fcpu=528000000
+teensyMM.menu.speed.450.build.fcpu=450000000
+teensyMM.menu.speed.396.build.fcpu=396000000
+teensyMM.menu.speed.150.build.fcpu=150000000
+teensyMM.menu.speed.24.build.fcpu=24000000
+
+teensyMM.menu.opt.o2std=Faster
+teensyMM.menu.opt.o2std.build.flags.optimize=-O2
+teensyMM.menu.opt.o2std.build.flags.ldspecs=
+#teensyMM.menu.opt.o2lto=Faster with LTO
+#teensyMM.menu.opt.o2lto.build.flags.optimize=-O2 -flto -fno-fat-lto-objects
+#teensyMM.menu.opt.o2lto.build.flags.ldspecs=-fuse-linker-plugin
+teensyMM.menu.opt.o1std=Fast
+teensyMM.menu.opt.o1std.build.flags.optimize=-O1
+teensyMM.menu.opt.o1std.build.flags.ldspecs=
+#teensyMM.menu.opt.o1lto=Fast with LTO
+#teensyMM.menu.opt.o1lto.build.flags.optimize=-O1 -flto -fno-fat-lto-objects
+#teensyMM.menu.opt.o1lto.build.flags.ldspecs=-fuse-linker-plugin
+teensyMM.menu.opt.o3std=Fastest
+teensyMM.menu.opt.o3std.build.flags.optimize=-O3
+teensyMM.menu.opt.o3std.build.flags.ldspecs=
+#teensyMM.menu.opt.o3purestd=Fastest + pure-code
+#teensyMM.menu.opt.o3purestd.build.flags.optimize=-O3 -mpure-code -D__PURE_CODE__
+#teensyMM.menu.opt.o3purestd.build.flags.ldspecs=
+#teensyMM.menu.opt.o3lto=Fastest with LTO
+#teensyMM.menu.opt.o3lto.build.flags.optimize=-O3 -flto -fno-fat-lto-objects
+#teensyMM.menu.opt.o3lto.build.flags.ldspecs=-fuse-linker-plugin
+#teensyMM.menu.opt.o3purelto=Fastest + pure-code with LTO
+#teensyMM.menu.opt.o3purelto.build.flags.optimize=-O3 -mpure-code -D__PURE_CODE__ -flto -fno-fat-lto-objects
+#teensyMM.menu.opt.o3purelto.build.flags.ldspecs=-fuse-linker-plugin
+teensyMM.menu.opt.ogstd=Debug
+teensyMM.menu.opt.ogstd.build.flags.optimize=-Og
+teensyMM.menu.opt.ogstd.build.flags.ldspecs=
+#teensyMM.menu.opt.oglto=Debug with LTO
+#teensyMM.menu.opt.oglto.build.flags.optimize=-Og -flto -fno-fat-lto-objects
+#teensyMM.menu.opt.oglto.build.flags.ldspecs=-fuse-linker-plugin
+teensyMM.menu.opt.osstd=Smallest Code
+teensyMM.menu.opt.osstd.build.flags.optimize=-Os --specs=nano.specs
+teensyMM.menu.opt.osstd.build.flags.ldspecs=
+#teensyMM.menu.opt.oslto=Smallest Code with LTO
+#teensyMM.menu.opt.oslto.build.flags.optimize=-Os -flto -fno-fat-lto-objects --specs=nano.specs
+#teensyMM.menu.opt.oslto.build.flags.ldspecs=-fuse-linker-plugin
+
+teensyMM.menu.keys.en-us=US English
+teensyMM.menu.keys.en-us.build.keylayout=US_ENGLISH
+teensyMM.menu.keys.fr-ca=Canadian French
+teensyMM.menu.keys.fr-ca.build.keylayout=CANADIAN_FRENCH
+teensyMM.menu.keys.xx-ca=Canadian Multilingual
+teensyMM.menu.keys.xx-ca.build.keylayout=CANADIAN_MULTILINGUAL
+teensyMM.menu.keys.cz-cz=Czech
+teensyMM.menu.keys.cz-cz.build.keylayout=CZECH
+teensyMM.menu.keys.da-da=Danish
+teensyMM.menu.keys.da-da.build.keylayout=DANISH
+teensyMM.menu.keys.fi-fi=Finnish
+teensyMM.menu.keys.fi-fi.build.keylayout=FINNISH
+teensyMM.menu.keys.fr-fr=French
+teensyMM.menu.keys.fr-fr.build.keylayout=FRENCH
+teensyMM.menu.keys.fr-be=French Belgian
+teensyMM.menu.keys.fr-be.build.keylayout=FRENCH_BELGIAN
+teensyMM.menu.keys.fr-ch=French Swiss
+teensyMM.menu.keys.fr-ch.build.keylayout=FRENCH_SWISS
+teensyMM.menu.keys.de-de=German
+teensyMM.menu.keys.de-de.build.keylayout=GERMAN
+teensyMM.menu.keys.de-dm=German (Mac)
+teensyMM.menu.keys.de-dm.build.keylayout=GERMAN_MAC
+teensyMM.menu.keys.de-ch=German Swiss
+teensyMM.menu.keys.de-ch.build.keylayout=GERMAN_SWISS
+teensyMM.menu.keys.is-is=Icelandic
+teensyMM.menu.keys.is-is.build.keylayout=ICELANDIC
+teensyMM.menu.keys.en-ie=Irish
+teensyMM.menu.keys.en-ie.build.keylayout=IRISH
+teensyMM.menu.keys.it-it=Italian
+teensyMM.menu.keys.it-it.build.keylayout=ITALIAN
+teensyMM.menu.keys.no-no=Norwegian
+teensyMM.menu.keys.no-no.build.keylayout=NORWEGIAN
+teensyMM.menu.keys.pt-pt=Portuguese
+teensyMM.menu.keys.pt-pt.build.keylayout=PORTUGUESE
+teensyMM.menu.keys.pt-br=Portuguese Brazilian
+teensyMM.menu.keys.pt-br.build.keylayout=PORTUGUESE_BRAZILIAN
+teensyMM.menu.keys.rs-rs=Serbian (Latin Only)
+teensyMM.menu.keys.rs-rs.build.keylayout=SERBIAN_LATIN_ONLY
+teensyMM.menu.keys.es-es=Spanish
+teensyMM.menu.keys.es-es.build.keylayout=SPANISH
+teensyMM.menu.keys.es-mx=Spanish Latin America
+teensyMM.menu.keys.es-mx.build.keylayout=SPANISH_LATIN_AMERICA
+teensyMM.menu.keys.sv-se=Swedish
+teensyMM.menu.keys.sv-se.build.keylayout=SWEDISH
+teensyMM.menu.keys.tr-tr=Turkish (partial)
+teensyMM.menu.keys.tr-tr.build.keylayout=TURKISH
+teensyMM.menu.keys.en-gb=United Kingdom
+teensyMM.menu.keys.en-gb.build.keylayout=UNITED_KINGDOM
+teensyMM.menu.keys.usint=US International
+teensyMM.menu.keys.usint.build.keylayout=US_INTERNATIONAL
+
+
+
+
 teensy40.name=Teensy 4.0
-teensy40.upload.maximum_size=2031616
+#teensy40.upload.maximum_size=2031616
 teensy40.build.board=TEENSY40
 teensy40.build.flags.ld=-Wl,--gc-sections,--relax "-T{build.core.path}/imxrt1062.ld"
-teensy40.upload.maximum_data_size=524288
+#teensy40.upload.maximum_data_size=524288
 #teensy40.upload.maximum_data_size=1048576
 teensy40.upload.tool=teensyloader
 teensy40.upload.protocol=halfkay
@@ -226,7 +435,7 @@ teensy40.build.flags.common=-g -Wall -ffunction-sections -fdata-sections -nostdl
 teensy40.build.flags.dep=-MMD
 teensy40.build.flags.optimize=-Os
 teensy40.build.flags.cpu=-mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16
-teensy40.build.flags.defs=-D__IMXRT1062__ -DTEENSYDUINO=152
+teensy40.build.flags.defs=-D__IMXRT1062__ -DTEENSYDUINO=156
 teensy40.build.flags.cpp=-std=gnu++14 -fno-exceptions -fpermissive -fno-rtti -fno-threadsafe-statics -felide-constructors -Wno-error=narrowing
 teensy40.build.flags.c=
 teensy40.build.flags.S=-x assembler-with-cpp
@@ -422,16 +631,16 @@ teensy36.build.command.objdump=arm-none-eabi-objdump
 teensy36.build.command.linker=arm-none-eabi-g++
 
 teensy36.build.command.size=arm-none-eabi-size
-teensy36.build.flags.common=-g -Wall -ffunction-sections -fdata-sections -nostdlib
+teensy36.build.flags.common=-g -Wall -ffunction-sections -fdata-sections -nostdlib -mno-unaligned-access
 teensy36.build.flags.dep=-MMD
 teensy36.build.flags.optimize=-Os
 teensy36.build.flags.cpu=-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fsingle-precision-constant
-teensy36.build.flags.defs=-D__MK66FX1M0__ -DTEENSYDUINO=152
+teensy36.build.flags.defs=-D__MK66FX1M0__ -DTEENSYDUINO=156
 teensy36.build.flags.cpp=-fno-exceptions -fpermissive -felide-constructors -std=gnu++14 -Wno-error=narrowing -fno-rtti
 teensy36.build.flags.c=
 teensy36.build.flags.S=-x assembler-with-cpp
-teensy36.build.flags.ld=-Wl,--gc-sections,--relax,--defsym=__rtc_localtime={extra.time.local} "-T{build.core.path}/mk66fx1m0.ld" -lstdc++
-teensy36.build.flags.libs=-larm_cortexM4lf_math -lm
+teensy36.build.flags.ld=-Wl,--gc-sections,--relax,--defsym=__rtc_localtime={extra.time.local} "-T{build.core.path}/mk66fx1m0.ld"
+teensy36.build.flags.libs=-larm_cortexM4lf_math -lm -lstdc++
 teensy36.serial.restart_cmd=false
 teensy36.menu.usb.serial=Serial
 teensy36.menu.usb.serial.build.usbtype=USB_SERIAL
@@ -635,16 +844,16 @@ teensy35.build.command.objdump=arm-none-eabi-objdump
 teensy35.build.command.linker=arm-none-eabi-g++
 
 teensy35.build.command.size=arm-none-eabi-size
-teensy35.build.flags.common=-g -Wall -ffunction-sections -fdata-sections -nostdlib
+teensy35.build.flags.common=-g -Wall -ffunction-sections -fdata-sections -nostdlib -mno-unaligned-access
 teensy35.build.flags.dep=-MMD
 teensy35.build.flags.optimize=-Os
 teensy35.build.flags.cpu=-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fsingle-precision-constant
-teensy35.build.flags.defs=-D__MK64FX512__ -DTEENSYDUINO=152
+teensy35.build.flags.defs=-D__MK64FX512__ -DTEENSYDUINO=156
 teensy35.build.flags.cpp=-fno-exceptions -fpermissive -felide-constructors -std=gnu++14 -Wno-error=narrowing -fno-rtti
 teensy35.build.flags.c=
 teensy35.build.flags.S=-x assembler-with-cpp
-teensy35.build.flags.ld=-Wl,--gc-sections,--relax,--defsym=__rtc_localtime={extra.time.local} "-T{build.core.path}/mk64fx512.ld" -lstdc++
-teensy35.build.flags.libs=-larm_cortexM4lf_math -lm
+teensy35.build.flags.ld=-Wl,--gc-sections,--relax,--defsym=__rtc_localtime={extra.time.local} "-T{build.core.path}/mk64fx512.ld"
+teensy35.build.flags.libs=-larm_cortexM4lf_math -lm -lstdc++
 teensy35.serial.restart_cmd=false
 teensy35.menu.usb.serial=Serial
 teensy35.menu.usb.serial.build.usbtype=USB_SERIAL
@@ -838,16 +1047,16 @@ teensy31.build.command.objdump=arm-none-eabi-objdump
 teensy31.build.command.linker=arm-none-eabi-g++
 
 teensy31.build.command.size=arm-none-eabi-size
-teensy31.build.flags.common=-g -Wall -ffunction-sections -fdata-sections -nostdlib
+teensy31.build.flags.common=-g -Wall -ffunction-sections -fdata-sections -nostdlib -mno-unaligned-access
 teensy31.build.flags.dep=-MMD
 teensy31.build.flags.optimize=-Os
 teensy31.build.flags.cpu=-mthumb -mcpu=cortex-m4 -fsingle-precision-constant
-teensy31.build.flags.defs=-D__MK20DX256__ -DTEENSYDUINO=152
+teensy31.build.flags.defs=-D__MK20DX256__ -DTEENSYDUINO=156
 teensy31.build.flags.cpp=-fno-exceptions -fpermissive -felide-constructors -std=gnu++14 -Wno-error=narrowing -fno-rtti
 teensy31.build.flags.c=
 teensy31.build.flags.S=-x assembler-with-cpp
-teensy31.build.flags.ld=-Wl,--gc-sections,--relax,--defsym=__rtc_localtime={extra.time.local} "-T{build.core.path}/mk20dx256.ld" -lstdc++
-teensy31.build.flags.libs=-larm_cortexM4l_math -lm
+teensy31.build.flags.ld=-Wl,--gc-sections,--relax,--defsym=__rtc_localtime={extra.time.local} "-T{build.core.path}/mk20dx256.ld"
+teensy31.build.flags.libs=-larm_cortexM4l_math -lm -lstdc++
 teensy31.serial.restart_cmd=false
 teensy31.menu.usb.serial=Serial
 teensy31.menu.usb.serial.build.usbtype=USB_SERIAL
@@ -1052,17 +1261,17 @@ teensy30.build.command.objdump=arm-none-eabi-objdump
 teensy30.build.command.linker=arm-none-eabi-g++
 
 teensy30.build.command.size=arm-none-eabi-size
-teensy30.build.flags.common=-g -Wall -ffunction-sections -fdata-sections -nostdlib
+teensy30.build.flags.common=-g -Wall -ffunction-sections -fdata-sections -nostdlib -mno-unaligned-access
 teensy30.build.flags.dep=-MMD
 teensy30.build.flags.optimize=-Os
 teensy30.build.flags.cpu=-mthumb -mcpu=cortex-m4 -fsingle-precision-constant
-teensy30.build.flags.defs=-D__MK20DX128__ -DTEENSYDUINO=152
+teensy30.build.flags.defs=-D__MK20DX128__ -DTEENSYDUINO=156
 teensy30.build.flags.cpp=-fno-exceptions -fpermissive -felide-constructors -std=gnu++14 -Wno-error=narrowing -fno-rtti
 teensy30.build.flags.c=
 teensy30.build.flags.S=-x assembler-with-cpp
-teensy30.build.flags.ld=-Wl,--gc-sections,--relax,--defsym=__rtc_localtime={extra.time.local} "-T{build.core.path}/mk20dx128.ld" -lstdc++
+teensy30.build.flags.ld=-Wl,--gc-sections,--relax,--defsym=__rtc_localtime={extra.time.local} "-T{build.core.path}/mk20dx128.ld"
 teensy30.build.flags.ldspecs=--specs=nano.specs
-teensy30.build.flags.libs=-larm_cortexM4l_math -lm
+teensy30.build.flags.libs=-larm_cortexM4l_math -lm -lstdc++
 teensy30.serial.restart_cmd=false
 
 teensy30.menu.usb.serial=Serial
@@ -1216,15 +1425,15 @@ teensyLC.build.command.objdump=arm-none-eabi-objdump
 teensyLC.build.command.linker=arm-none-eabi-g++
 
 teensyLC.build.command.size=arm-none-eabi-size
-teensyLC.build.flags.common=-g -Wall -ffunction-sections -fdata-sections -nostdlib
+teensyLC.build.flags.common=-g -Wall -ffunction-sections -fdata-sections -nostdlib -mno-unaligned-access
 teensyLC.build.flags.dep=-MMD
 teensyLC.build.flags.cpu=-mthumb -mcpu=cortex-m0plus -fsingle-precision-constant
-teensyLC.build.flags.defs=-D__MKL26Z64__ -DTEENSYDUINO=152
+teensyLC.build.flags.defs=-D__MKL26Z64__ -DTEENSYDUINO=156
 teensyLC.build.flags.cpp=-fno-exceptions -fpermissive -felide-constructors -std=gnu++14 -Wno-error=narrowing -fno-rtti
 teensyLC.build.flags.c=
 teensyLC.build.flags.S=-x assembler-with-cpp
-teensyLC.build.flags.ld=-Wl,--gc-sections,--relax,--defsym=__rtc_localtime={extra.time.local} "-T{build.core.path}/mkl26z64.ld" -lstdc++
-teensyLC.build.flags.libs=-larm_cortexM0l_math -lm
+teensyLC.build.flags.ld=-Wl,--gc-sections,--relax,--defsym=__rtc_localtime={extra.time.local} "-T{build.core.path}/mkl26z64.ld"
+teensyLC.build.flags.libs=-larm_cortexM0l_math -lm -lstdc++
 teensyLC.serial.restart_cmd=false
 teensyLC.menu.usb.serial=Serial
 teensyLC.menu.usb.serial.build.usbtype=USB_SERIAL
@@ -1374,7 +1583,7 @@ teensypp2.build.flags.common=-g -Wall -ffunction-sections -fdata-sections
 teensypp2.build.flags.dep=-MMD
 teensypp2.build.flags.optimize=-Os
 teensypp2.build.flags.cpu=-mmcu=at90usb1286
-teensypp2.build.flags.defs=-DTEENSYDUINO=152 -DARDUINO_ARCH_AVR
+teensypp2.build.flags.defs=-DTEENSYDUINO=156 -DARDUINO_ARCH_AVR
 teensypp2.build.flags.cpp=-fno-exceptions -fpermissive -felide-constructors -std=gnu++11
 teensypp2.build.flags.c=
 teensypp2.build.flags.S=-x assembler-with-cpp
@@ -1491,7 +1700,7 @@ teensy2.build.flags.common=-g -Wall -ffunction-sections -fdata-sections
 teensy2.build.flags.dep=-MMD
 teensy2.build.flags.optimize=-Os
 teensy2.build.flags.cpu=-mmcu=atmega32u4
-teensy2.build.flags.defs=-DTEENSYDUINO=152 -DARDUINO_ARCH_AVR
+teensy2.build.flags.defs=-DTEENSYDUINO=156 -DARDUINO_ARCH_AVR
 teensy2.build.flags.cpp=-fno-exceptions -fpermissive -felide-constructors -std=gnu++11
 teensy2.build.flags.c=
 teensy2.build.flags.S=-x assembler-with-cpp
diff --git a/Packages_Patches/hardware/teensy/avr/cores/teensy/Stream.cpp b/Packages_Patches/hardware/teensy/avr/cores/teensy/Stream.cpp
new file mode 100644
index 0000000..6c78ed5
--- /dev/null
+++ b/Packages_Patches/hardware/teensy/avr/cores/teensy/Stream.cpp
@@ -0,0 +1,446 @@
+/*
+ Stream.cpp - adds parsing methods to Stream class
+ Copyright (c) 2008 David A. Mellis.  All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Created July 2011
+ parsing functions based on TextFinder library by Michael Margolis
+ */
+
+#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
+
+// private method to read stream with timeout
+int Stream::timedRead()
+{
+  int c;
+  unsigned long startMillis = millis();
+
+  do
+  {
+    c = read();
+
+    if (c >= 0)
+      return c;
+
+    yield();
+  } while (millis() - startMillis < _timeout);
+
+  Serial.print(("timedRead timeout = "));
+  Serial.println(_timeout);
+
+  return -1;     // -1 indicates timeout
+}
+
+// private method to peek stream with timeout
+int Stream::timedPeek()
+{
+  int c;
+  unsigned long startMillis = millis();
+
+  do
+  {
+    c = peek();
+
+    if (c >= 0)
+      return c;
+
+    yield();
+  } while (millis() - startMillis < _timeout);
+
+  return -1;     // -1 indicates timeout
+}
+
+// returns peek of the next digit in the stream or -1 if timeout
+// discards non-numeric characters
+int Stream::peekNextDigit()
+{
+  int c;
+
+  while (1)
+  {
+    c = timedPeek();
+
+    if (c < 0)
+      return c;  // timeout
+
+    if (c == '-')
+      return c;
+
+    if (c >= '0' && c <= '9')
+      return c;
+
+    read();  // discard non-numeric
+  }
+}
+
+// Public Methods
+//////////////////////////////////////////////////////////////
+
+void Stream::setTimeout(unsigned long timeout)  // sets the maximum number of milliseconds to wait
+{
+  _timeout = timeout;
+}
+
+// find returns true if the target string is found
+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(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(const char *target, const char *terminator)
+{
+  if (target == nullptr)
+    return true;
+
+  size_t tlen = (terminator == nullptr) ? 0 : strlen(terminator);
+
+  return findUntil(target, strlen(target), terminator, tlen);
+}
+
+// reads data from the stream until the target string of the given length is found
+// search terminated if the terminator string is found
+// returns true if target string is found, false if terminated or timed out
+bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen)
+{
+  size_t index = 0;  // maximum target string length is 64k bytes!
+  size_t termIndex = 0;
+  int c;
+
+  if ( target == nullptr)
+    return true;
+
+  if ( *target == 0)
+    return true;  // return true if target is a null string
+
+  if (terminator == nullptr)
+    termLen = 0;
+
+  while ( (c = timedRead()) > 0)
+  {
+    if ( c == target[index])
+    {
+      //////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
+      if (++index >= targetLen)
+      {
+        // return true if all chars in the target match
+        return true;
+      }
+    }
+    else
+    {
+      index = 0;  // reset index if any char does not match
+    }
+
+    if (termLen > 0 && c == terminator[termIndex])
+    {
+      if (++termIndex >= termLen)
+        return false;       // return false if terminate string found before target string
+    }
+    else
+      termIndex = 0;
+  }
+
+  return false;
+}
+
+
+// returns the first valid (long) integer value from the current position.
+// initial characters that are not digits (or the minus sign) are skipped
+// function is terminated by the first character that is not a digit.
+long Stream::parseInt()
+{
+  return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
+}
+
+// as above but a given skipChar is ignored
+// this allows format characters (typically commas) in values to be ignored
+long Stream::parseInt(char skipChar)
+{
+  boolean isNegative = false;
+  long value = 0;
+  int c;
+
+  c = peekNextDigit();
+
+  // ignore non numeric leading characters
+  if (c < 0)
+    return 0; // zero returned if timeout
+
+  do
+  {
+    if (c == skipChar)
+      ; // ignore this charactor
+    else if (c == '-')
+      isNegative = true;
+    else if (c >= '0' && c <= '9')       // is c a digit?
+      value = value * 10 + c - '0';
+
+    read();  // consume the character we got with peek
+    c = timedPeek();
+  }
+  while ( (c >= '0' && c <= '9') || c == skipChar );
+
+  if (isNegative)
+    value = -value;
+
+  return value;
+}
+
+
+// as parseInt but returns a floating point value
+float Stream::parseFloat()
+{
+  return parseFloat(NO_SKIP_CHAR);
+}
+
+// as above but the given skipChar is ignored
+// this allows format characters (typically commas) in values to be ignored
+float Stream::parseFloat(char skipChar)
+{
+  boolean isNegative = false;
+  boolean isFraction = false;
+  long value = 0;
+  int c;
+  float fraction = 1.0;
+
+  c = peekNextDigit();
+
+  // ignore non numeric leading characters
+  if (c < 0)
+    return 0; // zero returned if timeout
+
+  do
+  {
+    if (c == skipChar)
+      ; // ignore
+    else if (c == '-')
+      isNegative = true;
+    else if (c == '.')
+      isFraction = true;
+    else if (c >= '0' && c <= '9')
+    {
+      // is c a digit?
+      value = value * 10 + c - '0';
+
+      if (isFraction)
+        fraction *= 0.1f;
+    }
+
+    read();  // consume the character we got with peek
+    c = timedPeek();
+  }
+  while ( (c >= '0' && c <= '9')  || c == '.' || c == skipChar );
+
+  if (isNegative)
+    value = -value;
+
+  if (isFraction)
+    return value * fraction;
+  else
+    return value;
+}
+
+// read characters from stream into buffer
+// terminates if length characters have been read, or timeout (see setTimeout)
+// returns the number of characters placed in the buffer
+// the buffer is NOT null terminated.
+//
+size_t Stream::readBytes(char *buffer, size_t length)
+{
+  if (buffer == nullptr)
+    return 0;
+
+  size_t count = 0;
+
+  while (count < length)
+  {
+    int c = timedRead();
+
+    if (c < 0)
+    {
+      setReadError();
+      break;
+    }
+
+    *buffer++ = (char)c;
+    count++;
+  }
+
+  return count;
+}
+
+
+// as readBytes with terminator character
+// terminates if length characters have been read, timeout, or if the terminator character  detected
+// returns the number of characters placed in the buffer (0 means no valid data found)
+
+size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
+{
+  if (buffer == nullptr)
+    return 0;
+
+  if (length < 1)
+    return 0;
+
+  length--;
+  size_t index = 0;
+
+  while (index < length)
+  {
+    int c = timedRead();
+
+    if (c == terminator)
+      break;
+
+    if (c < 0)
+    {
+      setReadError();
+      break;
+    }
+
+    *buffer++ = (char)c;
+    index++;
+  }
+
+  *buffer = 0;
+  return index; // return number of characters, not including null terminator
+}
+
+#if 1
+// From nRF52
+
+String Stream::readString(size_t max)
+{
+  String ret;
+  int c = timedRead();
+
+  while (c >= 0)
+  {
+    ret += (char)c;
+    c = timedRead();
+  }
+
+  return ret;
+}
+
+char readStringBuffer[2048];
+
+char* Stream::readCharsUntil(char terminator, size_t max)
+{
+  uint16_t offset = 0;
+
+  int c = timedRead();
+
+  readStringBuffer[offset++] = c;
+
+  while (c >= 0 && c != terminator)
+  {
+    c = timedRead();
+
+    readStringBuffer[offset++] = c;
+  }
+
+  readStringBuffer[offset] = 0;
+
+  return readStringBuffer;
+}
+
+String Stream::readStringUntil(char terminator, size_t max)
+{
+  String ret;
+  uint16_t offset = 0;
+
+  int c = timedRead();
+
+  readStringBuffer[offset++] = c;
+
+  while (c >= 0 && c != terminator)
+  {
+    c = timedRead();
+
+    readStringBuffer[offset++] = c;
+  }
+
+  readStringBuffer[offset] = 0;
+
+  ret = String(readStringBuffer);
+
+  return String(readStringBuffer);
+}
+
+#else
+
+String Stream::readString(size_t max)
+{
+  String str;
+  size_t length = 0;
+
+  while (length < max)
+  {
+    int c = timedRead();
+
+    if (c < 0)
+    {
+      setReadError();
+      break;  // timeout
+    }
+
+    if (c == 0)
+      break;
+
+    str += (char)c;
+    length++;
+  }
+
+  return str;
+}
+
+String Stream::readStringUntil(char terminator, size_t max)
+{
+  String str;
+  size_t length = 0;
+
+  while (length < max)
+  {
+    int c = timedRead();
+
+    if (c < 0)
+    {
+      setReadError();
+      break;  // timeout
+    }
+
+    if (c == 0 || c == terminator)
+      break;
+
+    str += (char)c;
+    length++;
+  }
+
+  return str;
+}
+#endif
diff --git a/Packages_Patches/hardware/teensy/avr/cores/teensy/Stream.h b/Packages_Patches/hardware/teensy/avr/cores/teensy/Stream.h
index 2577958..e63330a 100644
--- a/Packages_Patches/hardware/teensy/avr/cores/teensy/Stream.h
+++ b/Packages_Patches/hardware/teensy/avr/cores/teensy/Stream.h
@@ -26,48 +26,124 @@
 class Stream : public Print
 {
   public:
-	Stream() : _timeout(1000), read_error(0) {}
-	virtual int available() = 0;
-	virtual int read() = 0;
-	virtual int peek() = 0;
-	virtual void flush() = 0;
+    constexpr Stream() : _timeout(1000), read_error(0) {}
+    virtual int available() = 0;
+    virtual int read() = 0;
+    virtual int peek() = 0;
 
-	void setTimeout(unsigned long timeout);
-	bool find(const char *target);
-	bool find(const uint8_t *target) { return find ((const char *)target); }
-	bool find(const 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();
-	float parseFloat(char skipChar);
-	size_t readBytes(char *buffer, size_t length);
-	size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
-	size_t readBytesUntil(char terminator, char *buffer, size_t length);
-	size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); }
-	String readString(size_t max = 120);
-	String readStringUntil(char terminator, size_t max = 120);
-	int getReadError() { return read_error; }
-	void clearReadError() { setReadError(0); }
+    void setTimeout(unsigned long timeout);
+    bool find(const char *target);
+    
+    bool find(const uint8_t *target) 
+    {
+      return find ((const char *)target);
+    }
+    
+    bool find(const String &target) 
+    {
+      return find(target.c_str());
+    }
+    
+    bool find(const char *target, size_t length);
+    
+    bool find(const uint8_t *target, size_t length) 
+    {
+      return find ((const char *)target, length);
+    }
+    
+    bool find(const String &target, size_t length) 
+    {
+      return find(target.c_str(), length);
+    }
+    
+    bool findUntil(const char *target, const char *terminator);
+    
+    bool findUntil(const uint8_t *target, const char *terminator) 
+    {
+      return findUntil((const char *)target, terminator);
+    }
+    
+    bool findUntil(const String &target, const char *terminator) 
+    {
+      return findUntil(target.c_str(), terminator);
+    }
+    
+    bool findUntil(const char *target, const String &terminator) 
+    {
+      return findUntil(target, terminator.c_str());
+    }
+    
+    bool findUntil(const String &target, const String &terminator) 
+    {
+      return findUntil(target.c_str(), terminator.c_str());
+    }
+    
+    bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen);
+    
+    bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) 
+    {
+      return findUntil((const char *)target, targetLen, terminate, termLen);
+    }
+    
+    bool findUntil(const String &target, size_t targetLen, const char *terminate, size_t termLen);
+    bool findUntil(const char *target, size_t targetLen, const String &terminate, size_t termLen);
+    bool findUntil(const String &target, size_t targetLen, const String &terminate, size_t termLen);
+    
+    long parseInt();
+    long parseInt(char skipChar);
+    
+    float parseFloat();
+    float parseFloat(char skipChar);
+    
+    size_t readBytes(char *buffer, size_t length);
+    
+    size_t readBytes(uint8_t *buffer, size_t length) 
+    {
+      return readBytes((char *)buffer, length);
+    }
+    
+    size_t readBytesUntil(char terminator, char *buffer, size_t length);
+    
+    size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length) 
+    {
+      return readBytesUntil(terminator, (char *)buffer, length);
+    }
+
+    ////////////////////////////////////////////////////////////
+    String readString(size_t max = 512);
+    String readStringUntil(char terminator, size_t max = 512);
+
+    // KH, to not use String
+    char* readCharsUntil(char terminator, size_t max = 512);
+    ////////////////////////////////////////////////////////////
+
+    int getReadError() 
+    {
+      return read_error;
+    }
+    
+    void clearReadError() 
+    {
+      setReadError(0);
+    }
+    
   protected:
-	void setReadError(int err = 1) { read_error = err; }
-	unsigned long _timeout;
-	
-  // KH
-	int timedRead();
-	//////
-	
+    void setReadError(int err = 1) 
+    {
+      read_error = err;
+    }
+    
+    unsigned long _timeout;
+
+    // KH
+    int timedRead();
+    int timedPeek();
+    int peekNextDigit();
+    //////
+
   private:
-	char read_error;
-	
-	//int timedRead();
-	
-	int timedPeek();
-	int peekNextDigit();
+    char read_error;
 };
 
-#endif	
+#endif
+
diff --git a/Packages_Patches/hardware/teensy/avr/cores/teensy3/Stream.cpp b/Packages_Patches/hardware/teensy/avr/cores/teensy3/Stream.cpp
new file mode 100644
index 0000000..6c78ed5
--- /dev/null
+++ b/Packages_Patches/hardware/teensy/avr/cores/teensy3/Stream.cpp
@@ -0,0 +1,446 @@
+/*
+ Stream.cpp - adds parsing methods to Stream class
+ Copyright (c) 2008 David A. Mellis.  All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Created July 2011
+ parsing functions based on TextFinder library by Michael Margolis
+ */
+
+#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
+
+// private method to read stream with timeout
+int Stream::timedRead()
+{
+  int c;
+  unsigned long startMillis = millis();
+
+  do
+  {
+    c = read();
+
+    if (c >= 0)
+      return c;
+
+    yield();
+  } while (millis() - startMillis < _timeout);
+
+  Serial.print(("timedRead timeout = "));
+  Serial.println(_timeout);
+
+  return -1;     // -1 indicates timeout
+}
+
+// private method to peek stream with timeout
+int Stream::timedPeek()
+{
+  int c;
+  unsigned long startMillis = millis();
+
+  do
+  {
+    c = peek();
+
+    if (c >= 0)
+      return c;
+
+    yield();
+  } while (millis() - startMillis < _timeout);
+
+  return -1;     // -1 indicates timeout
+}
+
+// returns peek of the next digit in the stream or -1 if timeout
+// discards non-numeric characters
+int Stream::peekNextDigit()
+{
+  int c;
+
+  while (1)
+  {
+    c = timedPeek();
+
+    if (c < 0)
+      return c;  // timeout
+
+    if (c == '-')
+      return c;
+
+    if (c >= '0' && c <= '9')
+      return c;
+
+    read();  // discard non-numeric
+  }
+}
+
+// Public Methods
+//////////////////////////////////////////////////////////////
+
+void Stream::setTimeout(unsigned long timeout)  // sets the maximum number of milliseconds to wait
+{
+  _timeout = timeout;
+}
+
+// find returns true if the target string is found
+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(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(const char *target, const char *terminator)
+{
+  if (target == nullptr)
+    return true;
+
+  size_t tlen = (terminator == nullptr) ? 0 : strlen(terminator);
+
+  return findUntil(target, strlen(target), terminator, tlen);
+}
+
+// reads data from the stream until the target string of the given length is found
+// search terminated if the terminator string is found
+// returns true if target string is found, false if terminated or timed out
+bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen)
+{
+  size_t index = 0;  // maximum target string length is 64k bytes!
+  size_t termIndex = 0;
+  int c;
+
+  if ( target == nullptr)
+    return true;
+
+  if ( *target == 0)
+    return true;  // return true if target is a null string
+
+  if (terminator == nullptr)
+    termLen = 0;
+
+  while ( (c = timedRead()) > 0)
+  {
+    if ( c == target[index])
+    {
+      //////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
+      if (++index >= targetLen)
+      {
+        // return true if all chars in the target match
+        return true;
+      }
+    }
+    else
+    {
+      index = 0;  // reset index if any char does not match
+    }
+
+    if (termLen > 0 && c == terminator[termIndex])
+    {
+      if (++termIndex >= termLen)
+        return false;       // return false if terminate string found before target string
+    }
+    else
+      termIndex = 0;
+  }
+
+  return false;
+}
+
+
+// returns the first valid (long) integer value from the current position.
+// initial characters that are not digits (or the minus sign) are skipped
+// function is terminated by the first character that is not a digit.
+long Stream::parseInt()
+{
+  return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
+}
+
+// as above but a given skipChar is ignored
+// this allows format characters (typically commas) in values to be ignored
+long Stream::parseInt(char skipChar)
+{
+  boolean isNegative = false;
+  long value = 0;
+  int c;
+
+  c = peekNextDigit();
+
+  // ignore non numeric leading characters
+  if (c < 0)
+    return 0; // zero returned if timeout
+
+  do
+  {
+    if (c == skipChar)
+      ; // ignore this charactor
+    else if (c == '-')
+      isNegative = true;
+    else if (c >= '0' && c <= '9')       // is c a digit?
+      value = value * 10 + c - '0';
+
+    read();  // consume the character we got with peek
+    c = timedPeek();
+  }
+  while ( (c >= '0' && c <= '9') || c == skipChar );
+
+  if (isNegative)
+    value = -value;
+
+  return value;
+}
+
+
+// as parseInt but returns a floating point value
+float Stream::parseFloat()
+{
+  return parseFloat(NO_SKIP_CHAR);
+}
+
+// as above but the given skipChar is ignored
+// this allows format characters (typically commas) in values to be ignored
+float Stream::parseFloat(char skipChar)
+{
+  boolean isNegative = false;
+  boolean isFraction = false;
+  long value = 0;
+  int c;
+  float fraction = 1.0;
+
+  c = peekNextDigit();
+
+  // ignore non numeric leading characters
+  if (c < 0)
+    return 0; // zero returned if timeout
+
+  do
+  {
+    if (c == skipChar)
+      ; // ignore
+    else if (c == '-')
+      isNegative = true;
+    else if (c == '.')
+      isFraction = true;
+    else if (c >= '0' && c <= '9')
+    {
+      // is c a digit?
+      value = value * 10 + c - '0';
+
+      if (isFraction)
+        fraction *= 0.1f;
+    }
+
+    read();  // consume the character we got with peek
+    c = timedPeek();
+  }
+  while ( (c >= '0' && c <= '9')  || c == '.' || c == skipChar );
+
+  if (isNegative)
+    value = -value;
+
+  if (isFraction)
+    return value * fraction;
+  else
+    return value;
+}
+
+// read characters from stream into buffer
+// terminates if length characters have been read, or timeout (see setTimeout)
+// returns the number of characters placed in the buffer
+// the buffer is NOT null terminated.
+//
+size_t Stream::readBytes(char *buffer, size_t length)
+{
+  if (buffer == nullptr)
+    return 0;
+
+  size_t count = 0;
+
+  while (count < length)
+  {
+    int c = timedRead();
+
+    if (c < 0)
+    {
+      setReadError();
+      break;
+    }
+
+    *buffer++ = (char)c;
+    count++;
+  }
+
+  return count;
+}
+
+
+// as readBytes with terminator character
+// terminates if length characters have been read, timeout, or if the terminator character  detected
+// returns the number of characters placed in the buffer (0 means no valid data found)
+
+size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
+{
+  if (buffer == nullptr)
+    return 0;
+
+  if (length < 1)
+    return 0;
+
+  length--;
+  size_t index = 0;
+
+  while (index < length)
+  {
+    int c = timedRead();
+
+    if (c == terminator)
+      break;
+
+    if (c < 0)
+    {
+      setReadError();
+      break;
+    }
+
+    *buffer++ = (char)c;
+    index++;
+  }
+
+  *buffer = 0;
+  return index; // return number of characters, not including null terminator
+}
+
+#if 1
+// From nRF52
+
+String Stream::readString(size_t max)
+{
+  String ret;
+  int c = timedRead();
+
+  while (c >= 0)
+  {
+    ret += (char)c;
+    c = timedRead();
+  }
+
+  return ret;
+}
+
+char readStringBuffer[2048];
+
+char* Stream::readCharsUntil(char terminator, size_t max)
+{
+  uint16_t offset = 0;
+
+  int c = timedRead();
+
+  readStringBuffer[offset++] = c;
+
+  while (c >= 0 && c != terminator)
+  {
+    c = timedRead();
+
+    readStringBuffer[offset++] = c;
+  }
+
+  readStringBuffer[offset] = 0;
+
+  return readStringBuffer;
+}
+
+String Stream::readStringUntil(char terminator, size_t max)
+{
+  String ret;
+  uint16_t offset = 0;
+
+  int c = timedRead();
+
+  readStringBuffer[offset++] = c;
+
+  while (c >= 0 && c != terminator)
+  {
+    c = timedRead();
+
+    readStringBuffer[offset++] = c;
+  }
+
+  readStringBuffer[offset] = 0;
+
+  ret = String(readStringBuffer);
+
+  return String(readStringBuffer);
+}
+
+#else
+
+String Stream::readString(size_t max)
+{
+  String str;
+  size_t length = 0;
+
+  while (length < max)
+  {
+    int c = timedRead();
+
+    if (c < 0)
+    {
+      setReadError();
+      break;  // timeout
+    }
+
+    if (c == 0)
+      break;
+
+    str += (char)c;
+    length++;
+  }
+
+  return str;
+}
+
+String Stream::readStringUntil(char terminator, size_t max)
+{
+  String str;
+  size_t length = 0;
+
+  while (length < max)
+  {
+    int c = timedRead();
+
+    if (c < 0)
+    {
+      setReadError();
+      break;  // timeout
+    }
+
+    if (c == 0 || c == terminator)
+      break;
+
+    str += (char)c;
+    length++;
+  }
+
+  return str;
+}
+#endif
diff --git a/Packages_Patches/hardware/teensy/avr/cores/teensy3/Stream.h b/Packages_Patches/hardware/teensy/avr/cores/teensy3/Stream.h
index 8171b9e..e63330a 100644
--- a/Packages_Patches/hardware/teensy/avr/cores/teensy3/Stream.h
+++ b/Packages_Patches/hardware/teensy/avr/cores/teensy3/Stream.h
@@ -26,55 +26,124 @@
 class Stream : public Print
 {
   public:
-	constexpr Stream() : _timeout(1000), read_error(0) {}
-	virtual int available() = 0;
-	virtual int read() = 0;
-	virtual int peek() = 0;
+    constexpr Stream() : _timeout(1000), read_error(0) {}
+    virtual int available() = 0;
+    virtual int read() = 0;
+    virtual int peek() = 0;
 
-	void setTimeout(unsigned long timeout);
-	bool find(const char *target);
-	bool find(const uint8_t *target) { return find ((const char *)target); }
-	bool find(const String &target) { return find(target.c_str()); }
-	bool find(const char *target, size_t length);
-	bool find(const uint8_t *target, size_t length) { return find ((const char *)target, length); }
-	bool find(const String &target, size_t length) { return find(target.c_str(), length); }
-	bool findUntil(const char *target, const char *terminator);
-	bool findUntil(const uint8_t *target, const char *terminator) { return findUntil((const char *)target, terminator); }
-	bool findUntil(const String &target, const char *terminator) { return findUntil(target.c_str(), terminator); }
-	bool findUntil(const char *target, const String &terminator) { return findUntil(target, terminator.c_str()); }
-	bool findUntil(const String &target, const String &terminator) { return findUntil(target.c_str(), terminator.c_str()); }
-	bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen);
-	bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) {return findUntil((const char *)target, targetLen, terminate, termLen); }
-	bool findUntil(const String &target, size_t targetLen, const char *terminate, size_t termLen);
-	bool findUntil(const char *target, size_t targetLen, const String &terminate, size_t termLen);
-	bool findUntil(const String &target, size_t targetLen, const String &terminate, size_t termLen);
-	long parseInt();
-	long parseInt(char skipChar);
-	float parseFloat();
-	float parseFloat(char skipChar);
-	size_t readBytes(char *buffer, size_t length);
-	size_t readBytes(uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
-	size_t readBytesUntil(char terminator, char *buffer, size_t length);
-	size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); }
-	String readString(size_t max = 120);
-	String readStringUntil(char terminator, size_t max = 120);
-	int getReadError() { return read_error; }
-	void clearReadError() { setReadError(0); }
+    void setTimeout(unsigned long timeout);
+    bool find(const char *target);
+    
+    bool find(const uint8_t *target) 
+    {
+      return find ((const char *)target);
+    }
+    
+    bool find(const String &target) 
+    {
+      return find(target.c_str());
+    }
+    
+    bool find(const char *target, size_t length);
+    
+    bool find(const uint8_t *target, size_t length) 
+    {
+      return find ((const char *)target, length);
+    }
+    
+    bool find(const String &target, size_t length) 
+    {
+      return find(target.c_str(), length);
+    }
+    
+    bool findUntil(const char *target, const char *terminator);
+    
+    bool findUntil(const uint8_t *target, const char *terminator) 
+    {
+      return findUntil((const char *)target, terminator);
+    }
+    
+    bool findUntil(const String &target, const char *terminator) 
+    {
+      return findUntil(target.c_str(), terminator);
+    }
+    
+    bool findUntil(const char *target, const String &terminator) 
+    {
+      return findUntil(target, terminator.c_str());
+    }
+    
+    bool findUntil(const String &target, const String &terminator) 
+    {
+      return findUntil(target.c_str(), terminator.c_str());
+    }
+    
+    bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen);
+    
+    bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) 
+    {
+      return findUntil((const char *)target, targetLen, terminate, termLen);
+    }
+    
+    bool findUntil(const String &target, size_t targetLen, const char *terminate, size_t termLen);
+    bool findUntil(const char *target, size_t targetLen, const String &terminate, size_t termLen);
+    bool findUntil(const String &target, size_t targetLen, const String &terminate, size_t termLen);
+    
+    long parseInt();
+    long parseInt(char skipChar);
+    
+    float parseFloat();
+    float parseFloat(char skipChar);
+    
+    size_t readBytes(char *buffer, size_t length);
+    
+    size_t readBytes(uint8_t *buffer, size_t length) 
+    {
+      return readBytes((char *)buffer, length);
+    }
+    
+    size_t readBytesUntil(char terminator, char *buffer, size_t length);
+    
+    size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length) 
+    {
+      return readBytesUntil(terminator, (char *)buffer, length);
+    }
+
+    ////////////////////////////////////////////////////////////
+    String readString(size_t max = 512);
+    String readStringUntil(char terminator, size_t max = 512);
+
+    // KH, to not use String
+    char* readCharsUntil(char terminator, size_t max = 512);
+    ////////////////////////////////////////////////////////////
+
+    int getReadError() 
+    {
+      return read_error;
+    }
+    
+    void clearReadError() 
+    {
+      setReadError(0);
+    }
+    
   protected:
-	void setReadError(int err = 1) { read_error = err; }
-	unsigned long _timeout;
-	
-	// KH
-	int timedRead();
-	//////
-	
+    void setReadError(int err = 1) 
+    {
+      read_error = err;
+    }
+    
+    unsigned long _timeout;
+
+    // KH
+    int timedRead();
+    int timedPeek();
+    int peekNextDigit();
+    //////
+
   private:
-	char read_error;
-	
-	//int timedRead();
-	
-	int timedPeek();
-	int peekNextDigit();
+    char read_error;
 };
 
 #endif
+
diff --git a/Packages_Patches/hardware/teensy/avr/cores/teensy4/Stream.cpp b/Packages_Patches/hardware/teensy/avr/cores/teensy4/Stream.cpp
new file mode 100644
index 0000000..6c78ed5
--- /dev/null
+++ b/Packages_Patches/hardware/teensy/avr/cores/teensy4/Stream.cpp
@@ -0,0 +1,446 @@
+/*
+ Stream.cpp - adds parsing methods to Stream class
+ Copyright (c) 2008 David A. Mellis.  All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Created July 2011
+ parsing functions based on TextFinder library by Michael Margolis
+ */
+
+#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
+
+// private method to read stream with timeout
+int Stream::timedRead()
+{
+  int c;
+  unsigned long startMillis = millis();
+
+  do
+  {
+    c = read();
+
+    if (c >= 0)
+      return c;
+
+    yield();
+  } while (millis() - startMillis < _timeout);
+
+  Serial.print(("timedRead timeout = "));
+  Serial.println(_timeout);
+
+  return -1;     // -1 indicates timeout
+}
+
+// private method to peek stream with timeout
+int Stream::timedPeek()
+{
+  int c;
+  unsigned long startMillis = millis();
+
+  do
+  {
+    c = peek();
+
+    if (c >= 0)
+      return c;
+
+    yield();
+  } while (millis() - startMillis < _timeout);
+
+  return -1;     // -1 indicates timeout
+}
+
+// returns peek of the next digit in the stream or -1 if timeout
+// discards non-numeric characters
+int Stream::peekNextDigit()
+{
+  int c;
+
+  while (1)
+  {
+    c = timedPeek();
+
+    if (c < 0)
+      return c;  // timeout
+
+    if (c == '-')
+      return c;
+
+    if (c >= '0' && c <= '9')
+      return c;
+
+    read();  // discard non-numeric
+  }
+}
+
+// Public Methods
+//////////////////////////////////////////////////////////////
+
+void Stream::setTimeout(unsigned long timeout)  // sets the maximum number of milliseconds to wait
+{
+  _timeout = timeout;
+}
+
+// find returns true if the target string is found
+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(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(const char *target, const char *terminator)
+{
+  if (target == nullptr)
+    return true;
+
+  size_t tlen = (terminator == nullptr) ? 0 : strlen(terminator);
+
+  return findUntil(target, strlen(target), terminator, tlen);
+}
+
+// reads data from the stream until the target string of the given length is found
+// search terminated if the terminator string is found
+// returns true if target string is found, false if terminated or timed out
+bool Stream::findUntil(const char *target, size_t targetLen, const char *terminator, size_t termLen)
+{
+  size_t index = 0;  // maximum target string length is 64k bytes!
+  size_t termIndex = 0;
+  int c;
+
+  if ( target == nullptr)
+    return true;
+
+  if ( *target == 0)
+    return true;  // return true if target is a null string
+
+  if (terminator == nullptr)
+    termLen = 0;
+
+  while ( (c = timedRead()) > 0)
+  {
+    if ( c == target[index])
+    {
+      //////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
+      if (++index >= targetLen)
+      {
+        // return true if all chars in the target match
+        return true;
+      }
+    }
+    else
+    {
+      index = 0;  // reset index if any char does not match
+    }
+
+    if (termLen > 0 && c == terminator[termIndex])
+    {
+      if (++termIndex >= termLen)
+        return false;       // return false if terminate string found before target string
+    }
+    else
+      termIndex = 0;
+  }
+
+  return false;
+}
+
+
+// returns the first valid (long) integer value from the current position.
+// initial characters that are not digits (or the minus sign) are skipped
+// function is terminated by the first character that is not a digit.
+long Stream::parseInt()
+{
+  return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
+}
+
+// as above but a given skipChar is ignored
+// this allows format characters (typically commas) in values to be ignored
+long Stream::parseInt(char skipChar)
+{
+  boolean isNegative = false;
+  long value = 0;
+  int c;
+
+  c = peekNextDigit();
+
+  // ignore non numeric leading characters
+  if (c < 0)
+    return 0; // zero returned if timeout
+
+  do
+  {
+    if (c == skipChar)
+      ; // ignore this charactor
+    else if (c == '-')
+      isNegative = true;
+    else if (c >= '0' && c <= '9')       // is c a digit?
+      value = value * 10 + c - '0';
+
+    read();  // consume the character we got with peek
+    c = timedPeek();
+  }
+  while ( (c >= '0' && c <= '9') || c == skipChar );
+
+  if (isNegative)
+    value = -value;
+
+  return value;
+}
+
+
+// as parseInt but returns a floating point value
+float Stream::parseFloat()
+{
+  return parseFloat(NO_SKIP_CHAR);
+}
+
+// as above but the given skipChar is ignored
+// this allows format characters (typically commas) in values to be ignored
+float Stream::parseFloat(char skipChar)
+{
+  boolean isNegative = false;
+  boolean isFraction = false;
+  long value = 0;
+  int c;
+  float fraction = 1.0;
+
+  c = peekNextDigit();
+
+  // ignore non numeric leading characters
+  if (c < 0)
+    return 0; // zero returned if timeout
+
+  do
+  {
+    if (c == skipChar)
+      ; // ignore
+    else if (c == '-')
+      isNegative = true;
+    else if (c == '.')
+      isFraction = true;
+    else if (c >= '0' && c <= '9')
+    {
+      // is c a digit?
+      value = value * 10 + c - '0';
+
+      if (isFraction)
+        fraction *= 0.1f;
+    }
+
+    read();  // consume the character we got with peek
+    c = timedPeek();
+  }
+  while ( (c >= '0' && c <= '9')  || c == '.' || c == skipChar );
+
+  if (isNegative)
+    value = -value;
+
+  if (isFraction)
+    return value * fraction;
+  else
+    return value;
+}
+
+// read characters from stream into buffer
+// terminates if length characters have been read, or timeout (see setTimeout)
+// returns the number of characters placed in the buffer
+// the buffer is NOT null terminated.
+//
+size_t Stream::readBytes(char *buffer, size_t length)
+{
+  if (buffer == nullptr)
+    return 0;
+
+  size_t count = 0;
+
+  while (count < length)
+  {
+    int c = timedRead();
+
+    if (c < 0)
+    {
+      setReadError();
+      break;
+    }
+
+    *buffer++ = (char)c;
+    count++;
+  }
+
+  return count;
+}
+
+
+// as readBytes with terminator character
+// terminates if length characters have been read, timeout, or if the terminator character  detected
+// returns the number of characters placed in the buffer (0 means no valid data found)
+
+size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
+{
+  if (buffer == nullptr)
+    return 0;
+
+  if (length < 1)
+    return 0;
+
+  length--;
+  size_t index = 0;
+
+  while (index < length)
+  {
+    int c = timedRead();
+
+    if (c == terminator)
+      break;
+
+    if (c < 0)
+    {
+      setReadError();
+      break;
+    }
+
+    *buffer++ = (char)c;
+    index++;
+  }
+
+  *buffer = 0;
+  return index; // return number of characters, not including null terminator
+}
+
+#if 1
+// From nRF52
+
+String Stream::readString(size_t max)
+{
+  String ret;
+  int c = timedRead();
+
+  while (c >= 0)
+  {
+    ret += (char)c;
+    c = timedRead();
+  }
+
+  return ret;
+}
+
+char readStringBuffer[2048];
+
+char* Stream::readCharsUntil(char terminator, size_t max)
+{
+  uint16_t offset = 0;
+
+  int c = timedRead();
+
+  readStringBuffer[offset++] = c;
+
+  while (c >= 0 && c != terminator)
+  {
+    c = timedRead();
+
+    readStringBuffer[offset++] = c;
+  }
+
+  readStringBuffer[offset] = 0;
+
+  return readStringBuffer;
+}
+
+String Stream::readStringUntil(char terminator, size_t max)
+{
+  String ret;
+  uint16_t offset = 0;
+
+  int c = timedRead();
+
+  readStringBuffer[offset++] = c;
+
+  while (c >= 0 && c != terminator)
+  {
+    c = timedRead();
+
+    readStringBuffer[offset++] = c;
+  }
+
+  readStringBuffer[offset] = 0;
+
+  ret = String(readStringBuffer);
+
+  return String(readStringBuffer);
+}
+
+#else
+
+String Stream::readString(size_t max)
+{
+  String str;
+  size_t length = 0;
+
+  while (length < max)
+  {
+    int c = timedRead();
+
+    if (c < 0)
+    {
+      setReadError();
+      break;  // timeout
+    }
+
+    if (c == 0)
+      break;
+
+    str += (char)c;
+    length++;
+  }
+
+  return str;
+}
+
+String Stream::readStringUntil(char terminator, size_t max)
+{
+  String str;
+  size_t length = 0;
+
+  while (length < max)
+  {
+    int c = timedRead();
+
+    if (c < 0)
+    {
+      setReadError();
+      break;  // timeout
+    }
+
+    if (c == 0 || c == terminator)
+      break;
+
+    str += (char)c;
+    length++;
+  }
+
+  return str;
+}
+#endif
diff --git a/Packages_Patches/hardware/teensy/avr/cores/teensy4/Stream.h b/Packages_Patches/hardware/teensy/avr/cores/teensy4/Stream.h
index 8171b9e..e63330a 100644
--- a/Packages_Patches/hardware/teensy/avr/cores/teensy4/Stream.h
+++ b/Packages_Patches/hardware/teensy/avr/cores/teensy4/Stream.h
@@ -26,55 +26,124 @@
 class Stream : public Print
 {
   public:
-	constexpr Stream() : _timeout(1000), read_error(0) {}
-	virtual int available() = 0;
-	virtual int read() = 0;
-	virtual int peek() = 0;
+    constexpr Stream() : _timeout(1000), read_error(0) {}
+    virtual int available() = 0;
+    virtual int read() = 0;
+    virtual int peek() = 0;
 
-	void setTimeout(unsigned long timeout);
-	bool find(const char *target);
-	bool find(const uint8_t *target) { return find ((const char *)target); }
-	bool find(const String &target) { return find(target.c_str()); }
-	bool find(const char *target, size_t length);
-	bool find(const uint8_t *target, size_t length) { return find ((const char *)target, length); }
-	bool find(const String &target, size_t length) { return find(target.c_str(), length); }
-	bool findUntil(const char *target, const char *terminator);
-	bool findUntil(const uint8_t *target, const char *terminator) { return findUntil((const char *)target, terminator); }
-	bool findUntil(const String &target, const char *terminator) { return findUntil(target.c_str(), terminator); }
-	bool findUntil(const char *target, const String &terminator) { return findUntil(target, terminator.c_str()); }
-	bool findUntil(const String &target, const String &terminator) { return findUntil(target.c_str(), terminator.c_str()); }
-	bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen);
-	bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) {return findUntil((const char *)target, targetLen, terminate, termLen); }
-	bool findUntil(const String &target, size_t targetLen, const char *terminate, size_t termLen);
-	bool findUntil(const char *target, size_t targetLen, const String &terminate, size_t termLen);
-	bool findUntil(const String &target, size_t targetLen, const String &terminate, size_t termLen);
-	long parseInt();
-	long parseInt(char skipChar);
-	float parseFloat();
-	float parseFloat(char skipChar);
-	size_t readBytes(char *buffer, size_t length);
-	size_t readBytes(uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
-	size_t readBytesUntil(char terminator, char *buffer, size_t length);
-	size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); }
-	String readString(size_t max = 120);
-	String readStringUntil(char terminator, size_t max = 120);
-	int getReadError() { return read_error; }
-	void clearReadError() { setReadError(0); }
+    void setTimeout(unsigned long timeout);
+    bool find(const char *target);
+    
+    bool find(const uint8_t *target) 
+    {
+      return find ((const char *)target);
+    }
+    
+    bool find(const String &target) 
+    {
+      return find(target.c_str());
+    }
+    
+    bool find(const char *target, size_t length);
+    
+    bool find(const uint8_t *target, size_t length) 
+    {
+      return find ((const char *)target, length);
+    }
+    
+    bool find(const String &target, size_t length) 
+    {
+      return find(target.c_str(), length);
+    }
+    
+    bool findUntil(const char *target, const char *terminator);
+    
+    bool findUntil(const uint8_t *target, const char *terminator) 
+    {
+      return findUntil((const char *)target, terminator);
+    }
+    
+    bool findUntil(const String &target, const char *terminator) 
+    {
+      return findUntil(target.c_str(), terminator);
+    }
+    
+    bool findUntil(const char *target, const String &terminator) 
+    {
+      return findUntil(target, terminator.c_str());
+    }
+    
+    bool findUntil(const String &target, const String &terminator) 
+    {
+      return findUntil(target.c_str(), terminator.c_str());
+    }
+    
+    bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen);
+    
+    bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) 
+    {
+      return findUntil((const char *)target, targetLen, terminate, termLen);
+    }
+    
+    bool findUntil(const String &target, size_t targetLen, const char *terminate, size_t termLen);
+    bool findUntil(const char *target, size_t targetLen, const String &terminate, size_t termLen);
+    bool findUntil(const String &target, size_t targetLen, const String &terminate, size_t termLen);
+    
+    long parseInt();
+    long parseInt(char skipChar);
+    
+    float parseFloat();
+    float parseFloat(char skipChar);
+    
+    size_t readBytes(char *buffer, size_t length);
+    
+    size_t readBytes(uint8_t *buffer, size_t length) 
+    {
+      return readBytes((char *)buffer, length);
+    }
+    
+    size_t readBytesUntil(char terminator, char *buffer, size_t length);
+    
+    size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length) 
+    {
+      return readBytesUntil(terminator, (char *)buffer, length);
+    }
+
+    ////////////////////////////////////////////////////////////
+    String readString(size_t max = 512);
+    String readStringUntil(char terminator, size_t max = 512);
+
+    // KH, to not use String
+    char* readCharsUntil(char terminator, size_t max = 512);
+    ////////////////////////////////////////////////////////////
+
+    int getReadError() 
+    {
+      return read_error;
+    }
+    
+    void clearReadError() 
+    {
+      setReadError(0);
+    }
+    
   protected:
-	void setReadError(int err = 1) { read_error = err; }
-	unsigned long _timeout;
-	
-	// KH
-	int timedRead();
-	//////
-	
+    void setReadError(int err = 1) 
+    {
+      read_error = err;
+    }
+    
+    unsigned long _timeout;
+
+    // KH
+    int timedRead();
+    int timedPeek();
+    int peekNextDigit();
+    //////
+
   private:
-	char read_error;
-	
-	//int timedRead();
-	
-	int timedPeek();
-	int peekNextDigit();
+    char read_error;
 };
 
 #endif
+