| Teensy 2.0, LC, 3.x, 4.x core libraries for Arduino. | |||||
| Teensy 4.x core libraries. | |||||
| The latest stable version of Teensy's core library is always available in the Teensyduino installer, at this page: | The latest stable version of Teensy's core library is always available in the Teensyduino installer, at this page: | ||||
| # 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 | |||||
| size_t 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 | |||||
| digitalToggleFast KEYWORD2 | |||||
| digitalToggle KEYWORD2 | |||||
| transmitterEnable KEYWORD2 | |||||
| attachRts KEYWORD2 | |||||
| attachCts KEYWORD2 | |||||
| PROGMEM LITERAL1 | |||||
| FLASHMEM LITERAL1 | |||||
| DMAMEM LITERAL1 | |||||
| EXTMEM LITERAL1 | |||||
| FASTRUN LITERAL1 | |||||
| Serial4 KEYWORD1 | |||||
| Serial5 KEYWORD1 | |||||
| Serial6 KEYWORD1 | |||||
| Serial7 KEYWORD1 | |||||
| Serial8 KEYWORD1 | |||||
| SerialUSB1 KEYWORD1 | |||||
| SerialUSB2 KEYWORD1 | |||||
| setRX KEYWORD2 | |||||
| setTX KEYWORD2 | |||||
| write9bit KEYWORD2 | |||||
| addMemoryForRead KEYWORD2 | |||||
| addMemoryForWrite KEYWORD2 | |||||
| clear KEYWORD2 | |||||
| EventResponder LITERAL1 | |||||
| EventResponderRef LITERAL1 | |||||
| attachImmediate KEYWORD2 | |||||
| triggerEvent KEYWORD2 | |||||
| clearEvent KEYWORD2 | |||||
| getStatus KEYWORD2 | |||||
| getData KEYWORD2 | |||||
| setContext KEYWORD2 | |||||
| getContext KEYWORD2 | |||||
| waitForEvent KEYWORD2 | |||||
| MillisTimer LITERAL1 | |||||
| beginRepeating KEYWORD2 | |||||
| delayNanoseconds KEYWORD2 | |||||
| extmem_malloc KEYWORD2 | |||||
| extmem_free KEYWORD2 | |||||
| extmem_calloc KEYWORD2 | |||||
| extmem_realloc KEYWORD2 | |||||
| strcasecmp KEYWORD2 | |||||
| # removed by Arduino 1.0, 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 | |||||
| FILE_READ LITERAL1 | |||||
| FILE_WRITE LITERAL1 | |||||
| FILE_WRITE_BEGIN LITERAL1 | |||||
| # 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 | |||||
| FlightSimData KEYWORD2 | |||||
| FlightSimEvent KEYWORD2 | |||||
| onChange KEYWORD2 | |||||
| update KEYWORD2 | |||||
| isEnabled KEYWORD2 | |||||
| getFrameCount KEYWORD2 | |||||
| XPlaneRef KEYWORD2 | |||||
| # USB Touchscreen | |||||
| TouchscreenUSB KEYWORD1 |
| #include "WProgram.h" | |||||
| #include "pins_arduino.h" |
| #if ARDUINO >= 100 | |||||
| #ifndef client_h | |||||
| #define client_h | |||||
| #include "Print.h" | |||||
| #include "Stream.h" | |||||
| #include "IPAddress.h" | |||||
| class Client : public Stream { | |||||
| public: | |||||
| virtual int connect(IPAddress ip, uint16_t port) =0; | |||||
| virtual int connect(const char *host, uint16_t port) =0; | |||||
| virtual size_t write(uint8_t) =0; | |||||
| virtual size_t write(const uint8_t *buf, size_t size) =0; | |||||
| virtual int available() = 0; | |||||
| virtual int read() = 0; | |||||
| virtual int read(uint8_t *buf, size_t size) = 0; | |||||
| virtual int peek() = 0; | |||||
| virtual void flush() = 0; | |||||
| virtual void stop() = 0; | |||||
| virtual uint8_t connected() = 0; | |||||
| virtual operator bool() = 0; | |||||
| protected: | |||||
| uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; | |||||
| }; | |||||
| #endif | |||||
| #endif |
| /* Teensyduino Core Library - File base class | |||||
| * http://www.pjrc.com/teensy/ | |||||
| * Copyright (c) 2020 PJRC.COM, LLC. | |||||
| * | |||||
| * Permission is hereby granted, free of charge, to any person obtaining | |||||
| * a copy of this software and associated documentation files (the | |||||
| * "Software"), to deal in the Software without restriction, including | |||||
| * without limitation the rights to use, copy, modify, merge, publish, | |||||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||||
| * permit persons to whom the Software is furnished to do so, subject to | |||||
| * the following conditions: | |||||
| * | |||||
| * 1. The above copyright notice and this permission notice shall be | |||||
| * included in all copies or substantial portions of the Software. | |||||
| * | |||||
| * 2. If the Software is incorporated into a build system that allows | |||||
| * selection among a list of target devices, then similar target | |||||
| * devices manufactured by PJRC.COM must be included in the list of | |||||
| * target devices and selectable in the same manner. | |||||
| * | |||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
| * SOFTWARE. | |||||
| */ | |||||
| #ifndef FS_H | |||||
| #define FS_H | |||||
| #ifdef __cplusplus | |||||
| #include <Arduino.h> | |||||
| #define FILE_READ 0 | |||||
| #define FILE_WRITE 1 | |||||
| #define FILE_WRITE_BEGIN 2 | |||||
| enum SeekMode { | |||||
| SeekSet = 0, | |||||
| SeekCur = 1, | |||||
| SeekEnd = 2 | |||||
| }; | |||||
| //#define FILE_WHOAMI | |||||
| class File : public Stream { | |||||
| public: | |||||
| File() : f(nullptr) { } | |||||
| File(File *file) { | |||||
| // "file" must only be a class derived from File | |||||
| // can we use is_same or is_polymorphic with static_assert? | |||||
| // or is_base_of | |||||
| //static_assert(std::is_same<decltype(*file),File>::value, | |||||
| //"File(File *file) constructor only accepts pointers " | |||||
| //"to derived classes, not File itself"); | |||||
| f = file; | |||||
| if (f) f->refcount++; | |||||
| } | |||||
| File(const File &file) { | |||||
| //Serial.println("File copy constructor"); | |||||
| //static int copycount=0; | |||||
| //if (++copycount > 20) while (1) ; | |||||
| f = file.f; | |||||
| if (f) f->refcount++; | |||||
| } | |||||
| File& operator = (const File &file) { | |||||
| //Serial.println("File assignment"); | |||||
| //static int assigncount=0; | |||||
| //if (++assigncount > 20) while (1) ; | |||||
| invalidate(); | |||||
| f = file.f; | |||||
| if (f) f->refcount++; | |||||
| return *this; | |||||
| } | |||||
| virtual ~File() { | |||||
| invalidate(); | |||||
| } | |||||
| #ifdef FILE_WHOAMI | |||||
| virtual void whoami() { // testing only | |||||
| Serial.printf(" File this=%x, f=%x\n", (int)this, (int)f); | |||||
| if (f) f->whoami(); | |||||
| } | |||||
| unsigned int getRefcount() { // testing only | |||||
| return refcount; | |||||
| } | |||||
| #endif | |||||
| virtual size_t read(void *buf, size_t nbyte) { | |||||
| return (f) ? f->read(buf, nbyte) : 0; | |||||
| } | |||||
| virtual size_t write(const void *buf, size_t size) { | |||||
| return (f) ? f->write(buf, size) : 0; | |||||
| } | |||||
| virtual int available() { | |||||
| return (f) ? f->available() : 0; | |||||
| } | |||||
| virtual int peek() { | |||||
| return (f) ? f->peek() : -1; | |||||
| } | |||||
| virtual void flush() { | |||||
| if (f) f->flush(); | |||||
| } | |||||
| virtual bool truncate(uint64_t size=0) { | |||||
| return (f) ? f->truncate(size) : false; | |||||
| } | |||||
| virtual bool seek(uint64_t pos, int mode) { | |||||
| return (f) ? f->seek(pos, mode) : false; | |||||
| } | |||||
| virtual uint64_t position() { | |||||
| return (f) ? f->position() : 0; | |||||
| } | |||||
| virtual uint64_t size() { | |||||
| return (f) ? f->size() : 0; | |||||
| } | |||||
| virtual void close() { | |||||
| if (f) f->close(); | |||||
| } | |||||
| virtual operator bool() { | |||||
| return (f) ? (bool)*f : false; | |||||
| } | |||||
| virtual const char* name() { | |||||
| return (f) ? f->name() : ""; | |||||
| } | |||||
| virtual bool isDirectory() { | |||||
| return (f) ? f->isDirectory() : false; | |||||
| } | |||||
| virtual File openNextFile(uint8_t mode=0) { | |||||
| return (f) ? f->openNextFile(mode) : *this; | |||||
| } | |||||
| virtual void rewindDirectory(void) { | |||||
| if (f) f->rewindDirectory(); | |||||
| } | |||||
| bool seek(uint64_t pos) { | |||||
| return seek(pos, SeekSet); | |||||
| } | |||||
| int read() { | |||||
| if (!f) return -1; | |||||
| unsigned char b; | |||||
| if (f->read(&b, 1) < 1) return -1; | |||||
| return b; | |||||
| } | |||||
| size_t write(uint8_t b) { | |||||
| return write(&b, 1); | |||||
| } | |||||
| size_t write(const char *str) { | |||||
| return write(str, strlen(str)); | |||||
| } | |||||
| size_t readBytes(char *buffer, size_t length) { | |||||
| return read(buffer, length); | |||||
| } | |||||
| private: | |||||
| void invalidate() { | |||||
| if (f && --(f->refcount) == 0) delete f; | |||||
| } | |||||
| union { | |||||
| // instances of base File class use this pointer | |||||
| File *f; | |||||
| // instances of derived classes (which actually access media) | |||||
| // use this reference count which is managed by the base class | |||||
| unsigned int refcount; | |||||
| }; | |||||
| }; | |||||
| class FS | |||||
| { | |||||
| public: | |||||
| FS() {} | |||||
| virtual File open(const char *filename, uint8_t mode = FILE_READ) = 0; | |||||
| virtual bool exists(const char *filepath) = 0; | |||||
| virtual bool mkdir(const char *filepath) = 0; | |||||
| virtual bool rename(const char *oldfilepath, const char *newfilepath) = 0; | |||||
| virtual bool remove(const char *filepath) = 0; | |||||
| virtual bool rmdir(const char *filepath) = 0; | |||||
| virtual uint64_t usedSize() = 0; | |||||
| virtual uint64_t totalSize() = 0; | |||||
| }; | |||||
| #endif // __cplusplus | |||||
| #endif // FS_H |
| /* UART (hardware serial) for Teensy & Teensy++ | |||||
| * http://www.pjrc.com/teensy/ | |||||
| * Copyright (c) 2008 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: | |||||
| * | |||||
| * 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/io.h> | |||||
| #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]; | |||||
| static volatile uint8_t rx_buffer_head = 0; | |||||
| static volatile uint8_t rx_buffer_tail = 0; | |||||
| #define TX_BUFFER_SIZE 40 | |||||
| static volatile uint8_t tx_buffer[TX_BUFFER_SIZE]; | |||||
| static volatile uint8_t tx_buffer_head = 0; | |||||
| static volatile uint8_t tx_buffer_tail = 0; | |||||
| static volatile uint8_t transmitting = 0; | |||||
| static volatile uint8_t tx_enable_pin = 255; | |||||
| // Public Methods ////////////////////////////////////////////////////////////// | |||||
| void HardwareSerial::_begin(uint16_t baud_count, uint8_t txen_pin) | |||||
| { | |||||
| tx_enable_pin = txen_pin; | |||||
| if (txen_pin < 255) { | |||||
| pinMode(txen_pin, OUTPUT); | |||||
| digitalWrite(txen_pin, LOW); | |||||
| } | |||||
| if ((baud_count & 1) && baud_count <= 4096) { | |||||
| UCSR1A = (1<<U2X1); | |||||
| UBRR1 = baud_count - 1; | |||||
| } else { | |||||
| UCSR1A = 0; | |||||
| UBRR1 = (baud_count >> 1) - 1; | |||||
| } | |||||
| if (!(UCSR1B & (1<<TXEN1))) { | |||||
| rx_buffer_head = 0; | |||||
| rx_buffer_tail = 0; | |||||
| tx_buffer_head = 0; | |||||
| tx_buffer_tail = 0; | |||||
| transmitting = 0; | |||||
| UCSR1C = (1<<UCSZ11) | (1<<UCSZ10); | |||||
| UCSR1B = (1<<RXEN1) | (1<<TXCIE1) | (1<<TXEN1) | (1<<RXCIE1); | |||||
| } | |||||
| } | |||||
| void HardwareSerial::end(void) | |||||
| { | |||||
| while (transmitting) ; // wait for buffered data to send | |||||
| UCSR1B = 0; | |||||
| rx_buffer_head = 0; | |||||
| rx_buffer_tail = 0; | |||||
| } | |||||
| void HardwareSerial::transmitterEnable(uint8_t pin) | |||||
| { | |||||
| while (transmitting) ; | |||||
| pinMode(pin, OUTPUT); | |||||
| digitalWrite(pin, LOW); | |||||
| tx_enable_pin = pin; | |||||
| } | |||||
| int HardwareSerial::available(void) | |||||
| { | |||||
| uint8_t head, tail; | |||||
| head = rx_buffer_head; | |||||
| tail = rx_buffer_tail; | |||||
| if (head >= tail) return head - tail; | |||||
| 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; | |||||
| head = rx_buffer_head; | |||||
| tail = rx_buffer_tail; | |||||
| if (head == tail) return -1; | |||||
| if (++tail >= RX_BUFFER_SIZE) tail = 0; | |||||
| return rx_buffer[tail]; | |||||
| } | |||||
| int HardwareSerial::read(void) | |||||
| { | |||||
| uint8_t c, i; | |||||
| if (rx_buffer_head == rx_buffer_tail) return -1; | |||||
| i = rx_buffer_tail + 1; | |||||
| if (i >= RX_BUFFER_SIZE) i = 0; | |||||
| c = rx_buffer[i]; | |||||
| rx_buffer_tail = i; | |||||
| return c; | |||||
| } | |||||
| void HardwareSerial::flush() | |||||
| { | |||||
| #if ARDUINO >= 100 | |||||
| while (transmitting) ; // wait for buffered data to send | |||||
| #else | |||||
| rx_buffer_head = rx_buffer_tail; | |||||
| #endif | |||||
| } | |||||
| void HardwareSerial::clear() | |||||
| { | |||||
| rx_buffer_head = rx_buffer_tail; | |||||
| } | |||||
| #if ARDUINO >= 100 | |||||
| size_t HardwareSerial::write(uint8_t c) | |||||
| #else | |||||
| void HardwareSerial::write(uint8_t c) | |||||
| #endif | |||||
| { | |||||
| uint8_t i; | |||||
| uint8_t status; | |||||
| if (!(UCSR1B & (1<<TXEN1))) { | |||||
| #if ARDUINO >= 100 | |||||
| setWriteError(); | |||||
| return 0; | |||||
| #else | |||||
| return; | |||||
| #endif | |||||
| } | |||||
| 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); | |||||
| sbi(UCSR1B, UDRIE1); | |||||
| #if ARDUINO >= 100 | |||||
| return 1; | |||||
| #endif | |||||
| } | |||||
| ISR(USART1_RX_vect) | |||||
| { | |||||
| uint8_t c, i; | |||||
| c = UDR1; | |||||
| i = rx_buffer_head + 1; | |||||
| if (i >= RX_BUFFER_SIZE) i = 0; | |||||
| if (i != rx_buffer_tail) { | |||||
| rx_buffer[i] = c; | |||||
| rx_buffer_head = i; | |||||
| } | |||||
| } | |||||
| ISR(USART1_UDRE_vect) | |||||
| { | |||||
| uint8_t i; | |||||
| if (tx_buffer_head == tx_buffer_tail) { | |||||
| // buffer is empty, disable transmit interrupt | |||||
| //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; | |||||
| UDR1 = tx_buffer[i]; | |||||
| tx_buffer_tail = i; | |||||
| } | |||||
| } | |||||
| ISR(USART1_TX_vect) | |||||
| { | |||||
| transmitting = 0; | |||||
| if (tx_enable_pin < 255) { | |||||
| digitalWrite(tx_enable_pin, LOW); | |||||
| } | |||||
| } | |||||
| // Preinstantiate Objects ////////////////////////////////////////////////////// | |||||
| HardwareSerial Serial1; | |||||
| #ifndef HardwareSerial_h | |||||
| #define HardwareSerial_h | |||||
| #include <inttypes.h> | |||||
| #include "Stream.h" | |||||
| class HardwareSerial : public Stream | |||||
| { | |||||
| public: | |||||
| inline void begin(uint32_t baud, uint8_t txen_pin=255) { | |||||
| _begin(((F_CPU / 8) + (baud / 2)) / baud, txen_pin); | |||||
| } | |||||
| void _begin(uint16_t baud_count, uint8_t pin); | |||||
| void end(void); | |||||
| void transmitterEnable(uint8_t pin); | |||||
| virtual int available(void); | |||||
| 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); | |||||
| #else | |||||
| virtual void write(uint8_t); | |||||
| #endif | |||||
| using Print::write; | |||||
| }; | |||||
| extern HardwareSerial Serial1; | |||||
| #endif |
| #if ARDUINO >= 100 | |||||
| #include "Arduino.h" | |||||
| #include "IPAddress.h" | |||||
| IPAddress::IPAddress() | |||||
| { | |||||
| _address.dword = 0; | |||||
| } | |||||
| IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t 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) | |||||
| { | |||||
| _address.dword = address; | |||||
| } | |||||
| IPAddress::IPAddress(const uint8_t *address) | |||||
| { | |||||
| memcpy(_address.bytes, address, sizeof(_address)); | |||||
| } | |||||
| IPAddress& IPAddress::operator=(const uint8_t *address) | |||||
| { | |||||
| memcpy(_address.bytes, address, sizeof(_address.bytes)); | |||||
| return *this; | |||||
| } | |||||
| IPAddress& IPAddress::operator=(uint32_t address) | |||||
| { | |||||
| _address.dword = address; | |||||
| return *this; | |||||
| } | |||||
| bool IPAddress::operator==(const uint8_t* addr) | |||||
| { | |||||
| return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0; | |||||
| } | |||||
| size_t IPAddress::printTo(Print& p) const | |||||
| { | |||||
| for (int i= 0; i < 3; i++) { | |||||
| p.print(_address.bytes[i], DEC); | |||||
| p.print('.'); | |||||
| } | |||||
| 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 |
| /* | |||||
| * | |||||
| * MIT License: | |||||
| * Copyright (c) 2011 Adrian McEwen | |||||
| * 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. | |||||
| * | |||||
| * adrianm@mcqn.com 1/1/2011 | |||||
| */ | |||||
| #if ARDUINO >= 100 | |||||
| #ifndef IPAddress_h | |||||
| #define IPAddress_h | |||||
| #include <Printable.h> | |||||
| // A class to make it easier to handle and pass around IP addresses | |||||
| class IPAddress : public Printable { | |||||
| 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.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); | |||||
| 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.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.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); | |||||
| 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; | |||||
| }; | |||||
| const IPAddress INADDR_NONE(0,0,0,0); | |||||
| #endif | |||||
| #endif |
| // empty Keyboard.h file, for compability with Arduino's Keyboard examples |
| #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 |
| // empty Mouse.h file, for compability with Arduino's Mouse examples |
| /* | |||||
| 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 | |||||
| */ | |||||
| #include <stdio.h> | |||||
| #include <string.h> | |||||
| #include <inttypes.h> | |||||
| #include <math.h> | |||||
| #include <avr/pgmspace.h> | |||||
| #include "wiring.h" | |||||
| #include "Print.h" | |||||
| size_t Print::write(const uint8_t *buffer, size_t size) | |||||
| { | |||||
| size_t count = 0; | |||||
| while (size--) count += write(*buffer++); | |||||
| return count; | |||||
| } | |||||
| size_t Print::print(const String &s) | |||||
| { | |||||
| uint8_t buffer[33]; | |||||
| size_t count = 0; | |||||
| unsigned int index = 0; | |||||
| unsigned int len = s.length(); | |||||
| while (len > 0) { | |||||
| s.getBytes(buffer, sizeof(buffer), index); | |||||
| unsigned int nbytes = len; | |||||
| if (nbytes > sizeof(buffer)-1) nbytes = sizeof(buffer)-1; | |||||
| index += nbytes; | |||||
| len -= nbytes; | |||||
| count += write(buffer, nbytes); | |||||
| } | |||||
| return count; | |||||
| } | |||||
| size_t Print::print(const __FlashStringHelper *ifsh) | |||||
| { | |||||
| uint8_t buffer[32]; | |||||
| size_t count = 0; | |||||
| const char *p = (const char *)ifsh; | |||||
| unsigned int len = strlen_P(p); | |||||
| while (len > 0) { | |||||
| unsigned int nbytes = len; | |||||
| if (nbytes > sizeof(buffer)) nbytes = sizeof(buffer); | |||||
| memcpy_P(buffer, p, nbytes); | |||||
| p += nbytes; | |||||
| len -= nbytes; | |||||
| count += write(buffer, nbytes); | |||||
| } | |||||
| return count; | |||||
| } | |||||
| size_t Print::print(long n) | |||||
| { | |||||
| uint8_t sign=0; | |||||
| if (n < 0) { | |||||
| sign = 1; | |||||
| n = -n; | |||||
| } | |||||
| return printNumber(n, sign, 10); | |||||
| } | |||||
| size_t Print::println(void) | |||||
| { | |||||
| uint8_t buf[2]={'\r', '\n'}; | |||||
| return write(buf, 2); | |||||
| } | |||||
| static int printf_putchar(char c, FILE *fp) | |||||
| { | |||||
| ((class Print *)(fdev_get_udata(fp)))->write((uint8_t)c); | |||||
| return 0; | |||||
| } | |||||
| int Print::printf(const char *format, ...) | |||||
| { | |||||
| FILE f; | |||||
| va_list ap; | |||||
| fdev_setup_stream(&f, printf_putchar, NULL, _FDEV_SETUP_WRITE); | |||||
| fdev_set_udata(&f, this); | |||||
| va_start(ap, format); | |||||
| return vfprintf(&f, format, ap); | |||||
| } | |||||
| int Print::printf(const __FlashStringHelper *format, ...) | |||||
| { | |||||
| FILE f; | |||||
| va_list ap; | |||||
| fdev_setup_stream(&f, printf_putchar, NULL, _FDEV_SETUP_WRITE); | |||||
| fdev_set_udata(&f, this); | |||||
| va_start(ap, format); | |||||
| return vfprintf_P(&f, (const char *)format, ap); | |||||
| } | |||||
| //#define USE_HACKER_DELIGHT_OPTIMIZATION | |||||
| #define USE_STIMMER_OPTIMIZATION | |||||
| //#define USE_BENCHMARK_CODE | |||||
| #ifdef USE_HACKER_DELIGHT_OPTIMIZATION | |||||
| // Adapted from Hacker's Delight (Henry Warren, ISBN 0321842685) www.hackersdelight.org | |||||
| // by Rob Tillaart, Tom Carpenter, "genom2" with input from others... | |||||
| // http://forum.arduino.cc/index.php?topic=167414.0 | |||||
| // | |||||
| #define divmod10_asm(in32, tmp32, mod8) \ | |||||
| asm volatile ( \ | |||||
| "mov %2, %A0 \n\t" /* mod = in */ \ | |||||
| "ori %A0, 1 \n\t" /* q = in | 1 */ \ | |||||
| "movw %A1, %A0 \n\t" /* x = q */ \ | |||||
| "movw %C1, %C0 \n\t" \ | |||||
| "lsr %D1 \n\t" /* x = x >> 2 */ \ | |||||
| "ror %C1 \n\t" \ | |||||
| "ror %B1 \n\t" \ | |||||
| "ror %A1 \n\t" \ | |||||
| "lsr %D1 \n\t" \ | |||||
| "ror %C1 \n\t" \ | |||||
| "ror %B1 \n\t" \ | |||||
| "ror %A1 \n\t" \ | |||||
| "sub %A0, %A1 \n\t" /* q = q - x */ \ | |||||
| "sbc %B0, %B1 \n\t" \ | |||||
| "sbc %C0, %C1 \n\t" \ | |||||
| "sbc %D0, %D1 \n\t" \ | |||||
| "movw %A1, %A0 \n\t" /* x = q */ \ | |||||
| "movw %C1, %C0 \n\t" \ | |||||
| "lsr %D1 \n\t" /* x = x >> 4 */ \ | |||||
| "ror %C1 \n\t" \ | |||||
| "ror %B1 \n\t" \ | |||||
| "ror %A1 \n\t" \ | |||||
| "lsr %D1 \n\t" \ | |||||
| "ror %C1 \n\t" \ | |||||
| "ror %B1 \n\t" \ | |||||
| "ror %A1 \n\t" \ | |||||
| "lsr %D1 \n\t" \ | |||||
| "ror %C1 \n\t" \ | |||||
| "ror %B1 \n\t" \ | |||||
| "ror %A1 \n\t" \ | |||||
| "lsr %D1 \n\t" \ | |||||
| "ror %C1 \n\t" \ | |||||
| "ror %B1 \n\t" \ | |||||
| "ror %A1 \n\t" \ | |||||
| "add %A1, %A0 \n\t" /* x = x + q */ \ | |||||
| "adc %B1, %B0 \n\t" \ | |||||
| "adc %C1, %C0 \n\t" \ | |||||
| "adc %D1, %D0 \n\t" \ | |||||
| "movw %A0, %A1 \n\t" /* q = x */ \ | |||||
| "movw %C0, %C1 \n\t" \ | |||||
| "add %A0, %B1 \n\t" /* q = q + (x >> 8) */ \ | |||||
| "adc %B0, %C1 \n\t" \ | |||||
| "adc %C0, %D1 \n\t" \ | |||||
| "adc %D0, r1 \n\t" \ | |||||
| "mov %A0, %B0 \n\t" /* q = q >> 8 */ \ | |||||
| "mov %B0, %C0 \n\t" \ | |||||
| "mov %C0, %D0 \n\t" \ | |||||
| "eor %D0, %D0 \n\t" \ | |||||
| "add %A0, %A1 \n\t" /* q = q + x */ \ | |||||
| "adc %B0, %B1 \n\t" \ | |||||
| "adc %C0, %C1 \n\t" \ | |||||
| "adc %D0, %D1 \n\t" \ | |||||
| "mov %A0, %B0 \n\t" /* q = q >> 8 */ \ | |||||
| "mov %B0, %C0 \n\t" \ | |||||
| "mov %C0, %D0 \n\t" \ | |||||
| "eor %D0, %D0 \n\t" \ | |||||
| "add %A0, %A1 \n\t" /* q = q + x */ \ | |||||
| "adc %B0, %B1 \n\t" \ | |||||
| "adc %C0, %C1 \n\t" \ | |||||
| "adc %D0, %D1 \n\t" \ | |||||
| "mov %A0, %B0 \n\t" /* q = q >> 8 */ \ | |||||
| "mov %B0, %C0 \n\t" \ | |||||
| "mov %C0, %D0 \n\t" \ | |||||
| "eor %D0, %D0 \n\t" \ | |||||
| "add %A0, %A1 \n\t" /* q = q + x */ \ | |||||
| "adc %B0, %B1 \n\t" \ | |||||
| "adc %C0, %C1 \n\t" \ | |||||
| "adc %D0, %D1 \n\t" \ | |||||
| "andi %A0, 0xF8 \n\t" /* q = q & ~0x7 */ \ | |||||
| "sub %2, %A0 \n\t" /* mod = mod - q */ \ | |||||
| "lsr %D0 \n\t" /* q = q >> 2 */ \ | |||||
| "ror %C0 \n\t" \ | |||||
| "ror %B0 \n\t" \ | |||||
| "ror %A0 \n\t" \ | |||||
| "lsr %D0 \n\t" \ | |||||
| "ror %C0 \n\t" \ | |||||
| "ror %B0 \n\t" \ | |||||
| "ror %A0 \n\t" \ | |||||
| "sub %2, %A0 \n\t" /* mod = mod - q */ \ | |||||
| "lsr %D0 \n\t" /* q = q >> 1 */ \ | |||||
| "ror %C0 \n\t" \ | |||||
| "ror %B0 \n\t" \ | |||||
| "ror %A0 \n\t" \ | |||||
| : "+d" (in32), "=r" (tmp32), "=r" (mod8) : : "r0" \ | |||||
| ) | |||||
| #endif // USE_HACKER_DELIGHT_OPTIMIZATION | |||||
| #ifdef USE_STIMMER_OPTIMIZATION | |||||
| // http://forum.arduino.cc/index.php?topic=167414.msg1293679#msg1293679 | |||||
| // http://forum.arduino.cc/index.php?topic=167414.msg1309482#msg1309482 | |||||
| // equivelant code: | |||||
| // mod8 = in32 % 10; | |||||
| // in32 = in32 / 10; | |||||
| // tmp8 = 10; | |||||
| #define divmod10_asm(in32, mod8, tmp8) \ | |||||
| asm volatile ( \ | |||||
| " ldi %2,51 \n\t" \ | |||||
| " mul %A0,%2 \n\t" \ | |||||
| " clr %A0 \n\t" \ | |||||
| " add r0,%2 \n\t" \ | |||||
| " adc %A0,r1 \n\t" \ | |||||
| " mov %1,r0 \n\t" \ | |||||
| " mul %B0,%2 \n\t" \ | |||||
| " clr %B0 \n\t" \ | |||||
| " add %A0,r0 \n\t" \ | |||||
| " adc %B0,r1 \n\t" \ | |||||
| " mul %C0,%2 \n\t" \ | |||||
| " clr %C0 \n\t" \ | |||||
| " add %B0,r0 \n\t" \ | |||||
| " adc %C0,r1 \n\t" \ | |||||
| " mul %D0,%2 \n\t" \ | |||||
| " clr %D0 \n\t" \ | |||||
| " add %C0,r0 \n\t" \ | |||||
| " adc %D0,r1 \n\t" \ | |||||
| " clr r1 \n\t" \ | |||||
| " add %1,%A0 \n\t" \ | |||||
| " adc %A0,%B0 \n\t" \ | |||||
| " adc %B0,%C0 \n\t" \ | |||||
| " adc %C0,%D0 \n\t" \ | |||||
| " adc %D0,r1 \n\t" \ | |||||
| " add %1,%B0 \n\t" \ | |||||
| " adc %A0,%C0 \n\t" \ | |||||
| " adc %B0,%D0 \n\t" \ | |||||
| " adc %C0,r1 \n\t" \ | |||||
| " adc %D0,r1 \n\t" \ | |||||
| " add %1,%D0 \n\t" \ | |||||
| " adc %A0,r1 \n\t" \ | |||||
| " adc %B0,r1 \n\t" \ | |||||
| " adc %C0,r1 \n\t" \ | |||||
| " adc %D0,r1 \n\t" \ | |||||
| " lsr %D0 \n\t" \ | |||||
| " ror %C0 \n\t" \ | |||||
| " ror %B0 \n\t" \ | |||||
| " ror %A0 \n\t" \ | |||||
| " ror %1 \n\t" \ | |||||
| " ldi %2,10 \n\t" \ | |||||
| " mul %1,%2 \n\t" \ | |||||
| " mov %1,r1 \n\t" \ | |||||
| " clr r1 \n\t" \ | |||||
| :"+r"(in32),"=d"(mod8),"=d"(tmp8) : : "r0") | |||||
| #endif // USE_STIMMER_OPTIMIZATION | |||||
| #ifdef USE_BENCHMARK_CODE | |||||
| uint32_t usec_print = 0; | |||||
| #endif | |||||
| size_t Print::printNumberDec(unsigned long n, uint8_t sign) | |||||
| { | |||||
| uint8_t digit, buf[11], *p; | |||||
| #if defined(USE_HACKER_DELIGHT_OPTIMIZATION) | |||||
| uint32_t tmp32; | |||||
| #elif defined(USE_STIMMER_OPTIMIZATION) | |||||
| uint8_t tmp8; | |||||
| #endif | |||||
| #ifdef USE_BENCHMARK_CODE | |||||
| uint32_t usec = micros(); | |||||
| #endif | |||||
| p = buf + (sizeof(buf)); | |||||
| do { | |||||
| #if defined(USE_HACKER_DELIGHT_OPTIMIZATION) | |||||
| divmod10_asm(n, tmp32, digit); | |||||
| #elif defined(USE_STIMMER_OPTIMIZATION) | |||||
| divmod10_asm(n, digit, tmp8); | |||||
| #else | |||||
| tmp32 = n; | |||||
| n = n / 10; | |||||
| digit = tmp32 - n * 10; | |||||
| #endif | |||||
| *--p = digit + '0'; | |||||
| } while (n); | |||||
| if (sign) *--p = '-'; | |||||
| #ifdef USE_BENCHMARK_CODE | |||||
| usec_print += micros() - usec; | |||||
| #endif | |||||
| 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; | |||||
| //uint32_t usec; | |||||
| //usec = micros(); | |||||
| p = buf + sizeof(buf); | |||||
| do { | |||||
| tmp = n; | |||||
| n = n / base; | |||||
| digit = tmp - n * base; | |||||
| *--p = (digit < 10) ? '0' + digit : 'A' + digit - 10; | |||||
| } while (n); | |||||
| //usec_print += micros() - usec; | |||||
| return write(p, sizeof(buf) - (p - buf)); | |||||
| } | |||||
| size_t Print::print(int64_t n) | |||||
| { | |||||
| if (n < 0) return printNumber64(-n, 10, 1); | |||||
| return printNumber64(n, 10, 0); | |||||
| } | |||||
| size_t Print::printNumber64(uint64_t n, uint8_t base, uint8_t sign) | |||||
| { | |||||
| uint8_t buf[66]; | |||||
| uint8_t digit, i; | |||||
| if (base < 2) return 0; | |||||
| if (n == 0) { | |||||
| buf[sizeof(buf) - 1] = '0'; | |||||
| i = sizeof(buf) - 1; | |||||
| } else { | |||||
| i = sizeof(buf) - 1; | |||||
| while (1) { | |||||
| digit = n % base; | |||||
| buf[i] = ((digit < 10) ? '0' + digit : 'A' + digit - 10); | |||||
| n /= base; | |||||
| if (n == 0) break; | |||||
| i--; | |||||
| } | |||||
| } | |||||
| if (sign) { | |||||
| i--; | |||||
| buf[i] = '-'; | |||||
| } | |||||
| return write(buf + i, sizeof(buf) - i); | |||||
| } | |||||
| size_t Print::printFloat(double number, uint8_t digits) | |||||
| { | |||||
| uint8_t sign=0; | |||||
| size_t count=0; | |||||
| // Handle negative numbers | |||||
| if (number < 0.0) { | |||||
| sign = 1; | |||||
| number = -number; | |||||
| } | |||||
| // Round correctly so that print(1.999, 2) prints as "2.00" | |||||
| double rounding = 0.5; | |||||
| for (uint8_t i=0; i<digits; ++i) { | |||||
| rounding *= 0.1; | |||||
| } | |||||
| number += rounding; | |||||
| // Extract the integer part of the number and print it | |||||
| unsigned long int_part = (unsigned long)number; | |||||
| double remainder = number - (double)int_part; | |||||
| count += printNumber(int_part, sign, 10); | |||||
| // Print the decimal point, but only if there are digits beyond | |||||
| if (digits > 0) { | |||||
| uint8_t n, buf[8], count=1; | |||||
| buf[0] = '.'; | |||||
| // Extract digits from the remainder one at a time | |||||
| if (digits > sizeof(buf) - 1) digits = sizeof(buf) - 1; | |||||
| while (digits-- > 0) { | |||||
| remainder *= 10.0; | |||||
| n = (uint8_t)(remainder); | |||||
| buf[count++] = '0' + n; | |||||
| remainder -= n; | |||||
| } | |||||
| count += write(buf, count); | |||||
| } | |||||
| return count; | |||||
| } | |||||
| /* | |||||
| Print.h - Base class that provides print() and println() | |||||
| 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 | |||||
| */ | |||||
| #ifndef Print_h | |||||
| #define Print_h | |||||
| #include <inttypes.h> | |||||
| #include <stdio.h> // for size_t | |||||
| #include <stdarg.h> | |||||
| #include "core_id.h" | |||||
| #include "WString.h" | |||||
| #include "Printable.h" | |||||
| #define DEC 10 | |||||
| #define HEX 16 | |||||
| #define OCT 8 | |||||
| #define BIN 2 | |||||
| // 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: | |||||
| 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); } | |||||
| size_t print(const char s[]) { return write(s); } | |||||
| size_t print(const __FlashStringHelper *f); | |||||
| size_t print(uint8_t b) { return printNumber(b, 0, 10); } | |||||
| size_t print(int n) { return print((long)n); } | |||||
| size_t print(unsigned int n) { return printNumber(n, 0, 10); } | |||||
| size_t print(long n); | |||||
| size_t print(unsigned long n) { return printNumber(n, 0, 10); } | |||||
| size_t print(int64_t n); | |||||
| size_t print(uint64_t n) { return printNumber64(n, 10, 0); } | |||||
| size_t print(unsigned char n, int base) { return printNumber(n, 0, base); } | |||||
| size_t print(int n, int base) { return (base == 10) ? print(n) : printNumber(n, 0, base); } | |||||
| size_t print(unsigned int n, int base) { return printNumber(n, 0, base); } | |||||
| size_t print(long n, int base) { return (base == 10) ? print(n) : printNumber(n, 0, base); } | |||||
| size_t print(unsigned long n, int base) { return printNumber(n, 0, base); } | |||||
| size_t print(int64_t n, int base) { return (base == 10) ? print(n) : printNumber64(n, base, 0); } | |||||
| size_t print(uint64_t n, int base) { return printNumber64(n, base, 0); } | |||||
| size_t print(double n, int digits = 2) { return printFloat(n, digits); } | |||||
| size_t print(const Printable &obj) { return obj.printTo(*this); } | |||||
| size_t println(void); | |||||
| size_t println(const String &s) { return print(s) + println(); } | |||||
| size_t println(char c) { return print(c) + println(); } | |||||
| size_t println(const char s[]) { return print(s) + println(); } | |||||
| size_t println(const __FlashStringHelper *f) { return print(f) + println(); } | |||||
| size_t println(uint8_t b) { return print(b) + println(); } | |||||
| size_t println(int n) { return print(n) + println(); } | |||||
| size_t println(unsigned int n) { return print(n) + println(); } | |||||
| size_t println(long n) { return print(n) + println(); } | |||||
| size_t println(unsigned long n) { return print(n) + println(); } | |||||
| size_t println(int64_t n) { return print(n) + println(); } | |||||
| size_t println(uint64_t n) { return print(n) + println(); } | |||||
| size_t println(unsigned char n, int base) { return print(n, base) + println(); } | |||||
| size_t println(int n, int base) { return print(n, base) + println(); } | |||||
| size_t println(unsigned int n, int base) { return print(n, base) + println(); } | |||||
| size_t println(long n, int base) { return print(n, base) + println(); } | |||||
| size_t println(unsigned long n, int base) { return print(n, base) + println(); } | |||||
| size_t println(int64_t n, int base) { return print(n, base) + println(); } | |||||
| size_t println(uint64_t n, int base) { return print(n, base) + println(); } | |||||
| size_t println(double n, int digits = 2) { return print(n, digits) + println(); } | |||||
| size_t println(const Printable &obj) { return obj.printTo(*this) + println(); } | |||||
| int getWriteError() { return write_error; } | |||||
| void clearWriteError() { setWriteError(0); } | |||||
| int printf(const char *format, ...); | |||||
| int printf(const __FlashStringHelper *format, ...); | |||||
| protected: | |||||
| void setWriteError(int err = 1) { write_error = err; } | |||||
| private: | |||||
| char write_error; | |||||
| 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 sign, uint8_t base) __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 == 10 || base < 2) return printNumberAny(n, 10); // testing only | |||||
| if (base == 16) return printNumberHex(n); | |||||
| if (base == 2) return printNumberBin(n); | |||||
| return printNumberAny(n, base); | |||||
| } | |||||
| size_t printNumber64(uint64_t n, uint8_t base, uint8_t sign); | |||||
| size_t printFloat(double n, uint8_t digits); | |||||
| }; | |||||
| #endif |
| /* | |||||
| Printable.h - Interface class that allows printing of complex types | |||||
| 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 Printable_h | |||||
| #define Printable_h | |||||
| #ifdef __cplusplus | |||||
| #include "new.h" | |||||
| class Print; | |||||
| /** The Printable class provides a way for new classes to allow themselves to be printed. | |||||
| By deriving from Printable and implementing the printTo method, it will then be possible | |||||
| for users to print out instances of this class by passing them into the usual | |||||
| Print::print and Print::println methods. | |||||
| */ | |||||
| class Printable | |||||
| { | |||||
| public: | |||||
| virtual size_t printTo(Print& p) const = 0; | |||||
| }; | |||||
| #endif | |||||
| #endif | |||||
| #endif |
| // Teensy 2.0 does not have SPIFIFO. This file exists so libraries | |||||
| // may use #include "SPIFIFO.h", and then test for HAS_SPIFIFO |
| #if ARDUINO >= 100 | |||||
| #ifndef server_h | |||||
| #define server_h | |||||
| class Server : public Print { | |||||
| public: | |||||
| virtual void begin() =0; | |||||
| }; | |||||
| #endif | |||||
| #endif |
| /* | |||||
| 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" | |||||
| #include "Stream.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; | |||||
| } while(millis() - startMillis < _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; | |||||
| } 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, char *terminator) | |||||
| { | |||||
| return findUntil(target, strlen(target), terminator, strlen(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(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; | |||||
| int c; | |||||
| if( *target == 0) | |||||
| return true; // return true if target is a null string | |||||
| while( (c = timedRead()) > 0){ | |||||
| if( c == target[index]){ | |||||
| //////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1); | |||||
| 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; | |||||
| char 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.1; | |||||
| } | |||||
| 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) | |||||
| { | |||||
| 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 (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 | |||||
| } | |||||
| String Stream::readString(size_t max) | |||||
| { | |||||
| String str; | |||||
| size_t length = str.length(); | |||||
| while (length < max) { | |||||
| int c = timedRead(); | |||||
| if (c < 0) { | |||||
| setReadError(); | |||||
| break; // timeout | |||||
| } | |||||
| if (c == 0) break; | |||||
| str += (char)c; | |||||
| } | |||||
| return str; | |||||
| } | |||||
| String Stream::readStringUntil(char terminator, size_t max) | |||||
| { | |||||
| String str; | |||||
| size_t length = str.length(); | |||||
| while (length < max) { | |||||
| int c = timedRead(); | |||||
| if (c < 0) { | |||||
| setReadError(); | |||||
| break; // timeout | |||||
| } | |||||
| if (c == 0 || c == terminator) break; | |||||
| str += (char)c; | |||||
| } | |||||
| return str; | |||||
| } | |||||
| /* | |||||
| Stream.h - base class for character-based streams. | |||||
| Copyright (c) 2010 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 | |||||
| */ | |||||
| #ifndef Stream_h | |||||
| #define Stream_h | |||||
| #include <inttypes.h> | |||||
| #include "Print.h" | |||||
| 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; | |||||
| 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); } | |||||
| protected: | |||||
| void setReadError(int err = 1) { read_error = err; } | |||||
| unsigned long _timeout; | |||||
| private: | |||||
| char read_error; | |||||
| int timedRead(); | |||||
| int timedPeek(); | |||||
| int peekNextDigit(); | |||||
| }; | |||||
| #endif |
| /* Tone generation for the Teensy and Teensy++ | |||||
| * http://www.pjrc.com/teensy/ | |||||
| * Copyright (c) 2010 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: | |||||
| * | |||||
| * 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/interrupt.h> | |||||
| #include "wiring.h" | |||||
| #include "core_pins.h" | |||||
| #include "pins_arduino.h" | |||||
| static uint8_t timer_acquired = 0; | |||||
| static uint8_t *tone1_reg = (uint8_t *)0; | |||||
| static uint8_t tone1_mask = 0; | |||||
| static uint16_t tone1_inc = 0; | |||||
| static uint32_t tone1_count = 0; | |||||
| static uint8_t *tone2_reg = (uint8_t *)0; | |||||
| static uint8_t tone2_mask = 0; | |||||
| static uint16_t tone2_inc = 0; | |||||
| static uint32_t tone2_count = 0; | |||||
| static uint8_t *tone3_reg = (uint8_t *)0; | |||||
| static uint8_t tone3_mask = 0; | |||||
| static uint16_t tone3_inc = 0; | |||||
| static uint32_t tone3_count = 0; | |||||
| #define MAX_FREQ (F_CPU / 16 / 25) | |||||
| #define MIN_FREQ (F_CPU / 16 / 65535 + 1) | |||||
| #define PIN_REG_AND_MASK_LOOKUP(pin, reg, mask) \ | |||||
| asm volatile( \ | |||||
| "lsl %2" "\n\t" \ | |||||
| "add %A3, %2" "\n\t" \ | |||||
| "adc %B3, __zero_reg__" "\n\n" \ | |||||
| "lpm %1, Z+" "\n\t" \ | |||||
| "lpm %A0, Z" "\n\t" \ | |||||
| "ldi %B0, 0" "\n" \ | |||||
| : "=z" (reg), "=r" (mask), "+r" (pin) \ | |||||
| : "z" (digital_pin_table_PGM), "2" (pin)) | |||||
| #if defined(__AVR_ATmega32U4__) | |||||
| //#define TONE_USE_TIMER1 | |||||
| #define TONE_USE_TIMER3 | |||||
| #elif defined(__AVR_AT90USB1286__) | |||||
| //#define TONE_USE_TIMER1 | |||||
| #define TONE_USE_TIMER3 | |||||
| #elif defined(__AVR_AT90USB162__) | |||||
| #define TONE_USE_TIMER1 | |||||
| #elif defined(__AVR_AT90USB646__) | |||||
| //#define TONE_USE_TIMER1 | |||||
| #define TONE_USE_TIMER3 | |||||
| #endif | |||||
| #ifdef TONE_USE_TIMER3 | |||||
| #define TIMSKx TIMSK3 | |||||
| #define OCIExA OCIE3A | |||||
| #define OCIExB OCIE3B | |||||
| #define OCIExC OCIE3C | |||||
| #define TCCRxA TCCR3A | |||||
| #define WGMx0 WGM30 | |||||
| #define TCCRxB TCCR3B | |||||
| #define CSx1 CS31 | |||||
| #define TCNTx TCNT3 | |||||
| #define OCRxA OCR3A | |||||
| #define OCRxB OCR3B | |||||
| #define OCRxC OCR3C | |||||
| #define TIFRx TIFR3 | |||||
| #define OCFxA OCF3A | |||||
| #define OCFxB OCF3B | |||||
| #define OCFxC OCF3C | |||||
| #define VECTxA TIMER3_COMPA_vect | |||||
| #define VECTxB TIMER3_COMPB_vect | |||||
| #define VECTxC TIMER3_COMPC_vect | |||||
| #endif | |||||
| #ifdef TONE_USE_TIMER1 | |||||
| #define TIMSKx TIMSK1 | |||||
| #define OCIExA OCIE1A | |||||
| #define OCIExB OCIE1B | |||||
| #define OCIExC OCIE1C | |||||
| #define TCCRxA TCCR1A | |||||
| #define WGMx0 WGM10 | |||||
| #define TCCRxB TCCR1B | |||||
| #define CSx1 CS11 | |||||
| #define TCNTx TCNT1 | |||||
| #define OCRxA OCR1A | |||||
| #define OCRxB OCR1B | |||||
| #define OCRxC OCR1C | |||||
| #define TIFRx TIFR1 | |||||
| #define OCFxA OCF1A | |||||
| #define OCFxB OCF1B | |||||
| #define OCFxC OCF1C | |||||
| #define VECTxA TIMER1_COMPA_vect | |||||
| #define VECTxB TIMER1_COMPB_vect | |||||
| #define VECTxC TIMER1_COMPC_vect | |||||
| #endif | |||||
| void tone(uint8_t pin, uint16_t frequency, uint32_t duration) | |||||
| { | |||||
| uint8_t *reg; | |||||
| uint8_t mask; | |||||
| uint16_t inc; | |||||
| uint32_t count; | |||||
| if (pin >= CORE_NUM_TOTAL_PINS) return; | |||||
| if (frequency < MIN_FREQ) { | |||||
| frequency = MIN_FREQ; | |||||
| } else if (frequency > MAX_FREQ) { | |||||
| frequency = MAX_FREQ; | |||||
| } | |||||
| inc = (F_CPU / 16 + frequency / 2) / frequency; | |||||
| if (duration) { | |||||
| count = duration * frequency / 500; | |||||
| } else { | |||||
| count = 0; | |||||
| } | |||||
| if (!timer_acquired) { | |||||
| TIMSKx = 0; // disable all interrupts | |||||
| TCCRxA = 0; | |||||
| TCCRxB = (1<<CSx1); // normal mode, div8 prescale | |||||
| timer_acquired = 1; | |||||
| } | |||||
| PIN_REG_AND_MASK_LOOKUP(pin, reg, mask); | |||||
| if (!tone1_mask || (tone1_mask == mask && tone1_reg == reg)) { | |||||
| TIMSKx &= ~(1<<OCIExA); // disable compare interrupt | |||||
| tone1_reg = reg; | |||||
| tone1_mask = mask; | |||||
| tone1_count = count; | |||||
| tone1_inc = inc; | |||||
| cli(); | |||||
| *(reg + 2) &= ~mask; // clear pin | |||||
| *(reg + 1) |= mask; // output mode | |||||
| OCRxA = TCNTx + inc; | |||||
| TIFRx |= (1<<OCFxA); // clear any pending compare match | |||||
| sei(); | |||||
| TIMSKx |= (1<<OCIExA); // enable compare interrupt | |||||
| return; | |||||
| } | |||||
| if (!tone2_mask || (tone2_mask == mask && tone2_reg == reg)) { | |||||
| TIMSKx &= ~(1<<OCIExB); // disable compare interrupt | |||||
| tone2_reg = reg; | |||||
| tone2_mask = mask; | |||||
| tone2_count = count; | |||||
| tone2_inc = inc; | |||||
| cli(); | |||||
| *(reg + 2) &= ~mask; // clear pin | |||||
| *(reg + 1) |= mask; // output mode | |||||
| OCRxB = TCNTx + inc; | |||||
| TIFRx |= (1<<OCFxB); // clear any pending compare match | |||||
| sei(); | |||||
| TIMSKx |= (1<<OCIExB); // enable compare interrupt | |||||
| return; | |||||
| } | |||||
| if (!tone3_mask || (tone3_mask == mask && tone3_reg == reg)) { | |||||
| TIMSKx &= ~(1<<OCIExC); // disable compare interrupt | |||||
| tone3_reg = reg; | |||||
| tone3_mask = mask; | |||||
| tone3_count = count; | |||||
| tone3_inc = inc; | |||||
| cli(); | |||||
| *(reg + 2) &= ~mask; // clear pin | |||||
| *(reg + 1) |= mask; // output mode | |||||
| OCRxC = TCNTx + inc; | |||||
| TIFRx |= (1<<OCFxC); // clear any pending compare match | |||||
| sei(); | |||||
| TIMSKx |= (1<<OCIExC); // enable compare interrupt | |||||
| return; | |||||
| } | |||||
| } | |||||
| void noTone(uint8_t pin) | |||||
| { | |||||
| uint8_t *reg; | |||||
| uint8_t mask; | |||||
| if (pin >= CORE_NUM_TOTAL_PINS) return; | |||||
| PIN_REG_AND_MASK_LOOKUP(pin, reg, mask); | |||||
| if (tone1_mask == mask && tone1_reg == reg) { | |||||
| TIMSKx &= ~(1<<OCIExA); | |||||
| tone1_mask = 0; | |||||
| } else if (tone2_mask == mask && tone2_reg == reg) { | |||||
| TIMSKx &= ~(1<<OCIExB); | |||||
| tone2_mask = 0; | |||||
| } else if (tone3_mask == mask && tone3_reg == reg) { | |||||
| TIMSKx &= ~(1<<OCIExC); | |||||
| tone3_mask = 0; | |||||
| } | |||||
| if (!tone1_mask && !tone2_mask && !tone3_mask) { | |||||
| TCCRxA = (1<<WGMx0); // restore timer | |||||
| timer_acquired = 0; | |||||
| } | |||||
| } | |||||
| ISR(VECTxA) | |||||
| { | |||||
| OCRxA += tone1_inc; | |||||
| *(tone1_reg) = tone1_mask; | |||||
| if (tone1_count > 0) { | |||||
| if ((--tone1_count) == 0) { | |||||
| *(tone1_reg + 2) &= ~tone1_mask; | |||||
| TIMSKx &= ~(1<<OCIExA); | |||||
| tone1_mask = 0; | |||||
| if (!tone2_mask && !tone3_mask) { | |||||
| TCCRxA = (1<<WGMx0); | |||||
| timer_acquired = 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| ISR(VECTxB) | |||||
| { | |||||
| OCRxB += tone2_inc; | |||||
| *(tone2_reg) = tone2_mask; | |||||
| if (tone2_count > 0) { | |||||
| if ((--tone2_count) == 0) { | |||||
| *(tone2_reg + 2) &= ~tone2_mask; | |||||
| TIMSKx &= ~(1<<OCIExB); | |||||
| tone2_mask = 0; | |||||
| if (!tone1_mask && !tone3_mask) { | |||||
| TCCRxA = (1<<WGMx0); | |||||
| timer_acquired = 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| ISR(VECTxC) | |||||
| { | |||||
| OCRxC += tone3_inc; | |||||
| *(tone3_reg) = tone3_mask; | |||||
| if (tone3_count > 0) { | |||||
| if ((--tone3_count) == 0) { | |||||
| *(tone3_reg + 2) &= ~tone3_mask; | |||||
| TIMSKx &= ~(1<<OCIExC); | |||||
| tone3_mask = 0; | |||||
| if (!tone1_mask && !tone2_mask) { | |||||
| TCCRxA = (1<<WGMx0); | |||||
| timer_acquired = 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| /* | |||||
| * Udp.cpp: Library to send/receive UDP packets. | |||||
| * | |||||
| * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these) | |||||
| * 1) UDP does not guarantee the order in which assembled UDP packets are received. This | |||||
| * might not happen often in practice, but in larger network topologies, a UDP | |||||
| * packet can be received out of sequence. | |||||
| * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being | |||||
| * aware of it. Again, this may not be a concern in practice on small local networks. | |||||
| * For more information, see http://www.cafeaulait.org/course/week12/35.html | |||||
| * | |||||
| * MIT License: | |||||
| * Copyright (c) 2008 Bjoern Hartmann | |||||
| * 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. | |||||
| * | |||||
| * bjoern@cs.stanford.edu 12/30/2008 | |||||
| */ | |||||
| #if ARDUINO >= 100 | |||||
| #ifndef udp_h | |||||
| #define udp_h | |||||
| #include <Stream.h> | |||||
| #include <IPAddress.h> | |||||
| 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 | |||||
| // Start building up a packet to send to the remote host specific in ip and port | |||||
| // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port | |||||
| virtual int beginPacket(IPAddress ip, uint16_t port) =0; | |||||
| // Start building up a packet to send to the remote host specific in host and port | |||||
| // Returns 1 if successful, 0 if there was a problem resolving the hostname or port | |||||
| virtual int beginPacket(const char *host, uint16_t port) =0; | |||||
| // Finish off this packet and send it | |||||
| // Returns 1 if the packet was sent successfully, 0 if there was an error | |||||
| virtual int endPacket() =0; | |||||
| // Write a single byte into the packet | |||||
| virtual size_t write(uint8_t) =0; | |||||
| // Write size bytes from buffer into the packet | |||||
| virtual size_t write(const uint8_t *buffer, size_t size) =0; | |||||
| // Start processing the next available incoming packet | |||||
| // Returns the size of the packet in bytes, or 0 if no packets are available | |||||
| virtual int parsePacket() =0; | |||||
| // Number of bytes remaining in the current packet | |||||
| virtual int available() =0; | |||||
| // Read a single byte from the current packet | |||||
| virtual int read() =0; | |||||
| // Read up to len bytes from the current packet and place them into buffer | |||||
| // Returns the number of bytes read, or 0 if none are available | |||||
| virtual int read(unsigned char* buffer, size_t len) =0; | |||||
| // Read up to len characters from the current packet and place them into buffer | |||||
| // Returns the number of characters read, or 0 if none are available | |||||
| virtual int read(char* buffer, size_t len) =0; | |||||
| // Return the next byte from the current packet without moving on to the next byte | |||||
| virtual int peek() =0; | |||||
| virtual void flush() =0; // Finish reading the current packet | |||||
| // Return the IP address of the host who sent the current incoming packet | |||||
| virtual IPAddress remoteIP() =0; | |||||
| // Return the port of the host who sent the current incoming packet | |||||
| virtual uint16_t remotePort() =0; | |||||
| protected: | |||||
| uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; | |||||
| }; | |||||
| #endif | |||||
| #endif |
| /* | |||||
| 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 | |||||
| */ | |||||
| #ifndef Character_h | |||||
| #define Character_h | |||||
| #include <ctype.h> | |||||
| // WCharacter.h prototypes | |||||
| inline boolean isAlphaNumeric(int c) __attribute__((always_inline)); | |||||
| inline boolean isAlpha(int c) __attribute__((always_inline)); | |||||
| inline boolean isAscii(int c) __attribute__((always_inline)); | |||||
| inline boolean isWhitespace(int c) __attribute__((always_inline)); | |||||
| inline boolean isControl(int c) __attribute__((always_inline)); | |||||
| inline boolean isDigit(int c) __attribute__((always_inline)); | |||||
| inline boolean isGraph(int c) __attribute__((always_inline)); | |||||
| inline boolean isLowerCase(int c) __attribute__((always_inline)); | |||||
| inline boolean isPrintable(int c) __attribute__((always_inline)); | |||||
| inline boolean isPunct(int c) __attribute__((always_inline)); | |||||
| inline boolean isSpace(int c) __attribute__((always_inline)); | |||||
| inline boolean isUpperCase(int c) __attribute__((always_inline)); | |||||
| inline boolean isHexadecimalDigit(int c) __attribute__((always_inline)); | |||||
| inline int toAscii(int c) __attribute__((always_inline)); | |||||
| inline int toLowerCase(int c) __attribute__((always_inline)); | |||||
| inline int toUpperCase(int c)__attribute__((always_inline)); | |||||
| // Checks for an alphanumeric character. | |||||
| // It is equivalent to (isalpha(c) || isdigit(c)). | |||||
| inline boolean isAlphaNumeric(int c) | |||||
| { | |||||
| return ( isalnum(c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for an alphabetic character. | |||||
| // It is equivalent to (isupper(c) || islower(c)). | |||||
| inline boolean isAlpha(int c) | |||||
| { | |||||
| return ( isalpha(c) == 0 ? false : true); | |||||
| } | |||||
| // Checks whether c is a 7-bit unsigned char value | |||||
| // that fits into the ASCII character set. | |||||
| inline boolean isAscii(int c) | |||||
| { | |||||
| return ( isascii (c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for a blank character, that is, a space or a tab. | |||||
| inline boolean isWhitespace(int c) | |||||
| { | |||||
| return ( isblank (c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for a control character. | |||||
| inline boolean isControl(int c) | |||||
| { | |||||
| return ( iscntrl (c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for a digit (0 through 9). | |||||
| inline boolean isDigit(int c) | |||||
| { | |||||
| return ( isdigit (c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for any printable character except space. | |||||
| inline boolean isGraph(int c) | |||||
| { | |||||
| return ( isgraph (c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for a lower-case character. | |||||
| inline boolean isLowerCase(int c) | |||||
| { | |||||
| return (islower (c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for any printable character including space. | |||||
| inline boolean isPrintable(int c) | |||||
| { | |||||
| return ( isprint (c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for any printable character which is not a space | |||||
| // or an alphanumeric character. | |||||
| inline boolean isPunct(int c) | |||||
| { | |||||
| return ( ispunct (c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for white-space characters. For the avr-libc library, | |||||
| // these are: space, formfeed ('\f'), newline ('\n'), carriage | |||||
| // return ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). | |||||
| inline boolean isSpace(int c) | |||||
| { | |||||
| return ( isspace (c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for an uppercase letter. | |||||
| inline boolean isUpperCase(int c) | |||||
| { | |||||
| return ( isupper (c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7 | |||||
| // 8 9 a b c d e f A B C D E F. | |||||
| inline boolean isHexadecimalDigit(int c) | |||||
| { | |||||
| return ( isxdigit (c) == 0 ? false : true); | |||||
| } | |||||
| // Converts c to a 7-bit unsigned char value that fits into the | |||||
| // ASCII character set, by clearing the high-order bits. | |||||
| inline int toAscii(int c) | |||||
| { | |||||
| return toascii (c); | |||||
| } | |||||
| // Warning: | |||||
| // Many people will be unhappy if you use this function. | |||||
| // This function will convert accented letters into random | |||||
| // characters. | |||||
| // Converts the letter c to lower case, if possible. | |||||
| inline int toLowerCase(int c) | |||||
| { | |||||
| return tolower (c); | |||||
| } | |||||
| // Converts the letter c to upper case, if possible. | |||||
| inline int toUpperCase(int c) | |||||
| { | |||||
| return toupper (c); | |||||
| } | |||||
| #endif |
| #include "wiring.h" |
| /* Interrupt functions for the Teensy and Teensy++ | |||||
| * http://www.pjrc.com/teensy/ | |||||
| * Copyright (c) 2008-2010 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: | |||||
| * | |||||
| * 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/io.h> | |||||
| #include <avr/interrupt.h> | |||||
| #include <avr/pgmspace.h> | |||||
| #include <stdint.h> | |||||
| #include "wiring.h" | |||||
| #include "wiring_private.h" | |||||
| #if defined(__AVR_ATmega32U4__) | |||||
| #define NUM_INTERRUPT 4 | |||||
| #else | |||||
| #define NUM_INTERRUPT 8 | |||||
| #endif | |||||
| volatile static voidFuncPtr intFunc[NUM_INTERRUPT]; | |||||
| static const uint8_t PROGMEM interrupt_mode_mask[] = {0xFC, 0xF3, 0xCF, 0x3F}; | |||||
| static uint8_t pin2int(uint8_t pin) | |||||
| { | |||||
| switch (pin) { | |||||
| case CORE_INT0_PIN: return 0; | |||||
| case CORE_INT1_PIN: return 1; | |||||
| case CORE_INT2_PIN: return 2; | |||||
| case CORE_INT3_PIN: return 3; | |||||
| #if !defined(__AVR_ATmega32U4__) | |||||
| case CORE_INT4_PIN: return 4; | |||||
| case CORE_INT5_PIN: return 5; | |||||
| case CORE_INT6_PIN: return 6; | |||||
| case CORE_INT7_PIN: return 7; | |||||
| #endif | |||||
| default: return 255; | |||||
| } | |||||
| } | |||||
| #if defined(__AVR_ATmega32U4__) | |||||
| void attachInterrupt(uint8_t inum, void (*userFunc)(void), uint8_t mode) | |||||
| { | |||||
| uint8_t mask; | |||||
| if (inum >= NUM_INTERRUPT) { | |||||
| inum = pin2int(inum); | |||||
| if (inum >= NUM_INTERRUPT) return; | |||||
| } | |||||
| intFunc[inum] = userFunc; | |||||
| mask = pgm_read_byte(interrupt_mode_mask + inum); | |||||
| mode &= 0x03; | |||||
| EICRA = (EICRA & mask) | (mode << (inum * 2)); | |||||
| EIMSK |= (1 << inum); | |||||
| } | |||||
| #else | |||||
| void attachInterrupt(uint8_t inum, void (*userFunc)(void), uint8_t mode) | |||||
| { | |||||
| uint8_t mask, index; | |||||
| if (inum >= NUM_INTERRUPT) { | |||||
| inum = pin2int(inum); | |||||
| if (inum >= NUM_INTERRUPT) return; | |||||
| } | |||||
| intFunc[inum] = userFunc; | |||||
| index = inum & 3; | |||||
| mask = pgm_read_byte(interrupt_mode_mask + index); | |||||
| mode &= 0x03; | |||||
| if (inum & 4) { | |||||
| EICRB = (EICRB & mask) | (mode << (index * 2)); | |||||
| } else { | |||||
| EICRA = (EICRA & mask) | (mode << (index * 2)); | |||||
| } | |||||
| EIMSK |= (1 << inum); | |||||
| } | |||||
| #endif | |||||
| void detachInterrupt(uint8_t inum) | |||||
| { | |||||
| if (inum >= NUM_INTERRUPT) { | |||||
| inum = pin2int(inum); | |||||
| if (inum >= NUM_INTERRUPT) return; | |||||
| } | |||||
| EIMSK &= ~(1 << inum); | |||||
| intFunc[inum] = 0; | |||||
| } | |||||
| SIGNAL(INT0_vect) { | |||||
| if (intFunc[0]) intFunc[0](); // INT0 is pin 0 (PD0) | |||||
| } | |||||
| SIGNAL(INT1_vect) { | |||||
| if (intFunc[1]) intFunc[1](); // INT1 is pin 1 (PD1) | |||||
| } | |||||
| SIGNAL(INT2_vect) { | |||||
| if (intFunc[2]) intFunc[2](); // INT2 is pin 2 (PD2) (also Serial RX) | |||||
| } | |||||
| SIGNAL(INT3_vect) { | |||||
| if (intFunc[3]) intFunc[3](); // INT3 is pin 3 (PD3) (also Serial TX) | |||||
| } | |||||
| #if !defined(__AVR_ATmega32U4__) | |||||
| SIGNAL(INT4_vect) { | |||||
| if (intFunc[4]) intFunc[4](); // INT4 is pin 20 (PC7) | |||||
| } | |||||
| SIGNAL(INT5_vect) { | |||||
| if (intFunc[5]) intFunc[5](); // INT5 is pin 4 (PD4) | |||||
| } | |||||
| SIGNAL(INT6_vect) { | |||||
| if (intFunc[6]) intFunc[6](); // INT6 is pin 6 (PD6) | |||||
| } | |||||
| SIGNAL(INT7_vect) { | |||||
| if (intFunc[7]) intFunc[7](); // INT7 is pin 7 (PD7) | |||||
| } | |||||
| #endif | |||||
| /* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ | |||||
| /* | |||||
| 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 | |||||
| $Id$ | |||||
| */ | |||||
| extern "C" { | |||||
| #include "stdlib.h" | |||||
| } | |||||
| void randomSeed(unsigned int seed) | |||||
| { | |||||
| if (seed != 0) { | |||||
| srandom(seed); | |||||
| } | |||||
| } | |||||
| long random(long howbig) | |||||
| { | |||||
| if (howbig == 0) { | |||||
| return 0; | |||||
| } | |||||
| return random() % howbig; | |||||
| } | |||||
| long random(long howsmall, long howbig) | |||||
| { | |||||
| if (howsmall >= howbig) { | |||||
| return howsmall; | |||||
| } | |||||
| long diff = howbig - howsmall; | |||||
| 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; } |
| #ifndef WProgram_h | |||||
| #define WProgram_h | |||||
| #include <stdlib.h> | |||||
| #include <string.h> | |||||
| #include <math.h> | |||||
| #ifdef GCC_VERSION | |||||
| #if (GCC_VERSION < 40300) | |||||
| #warning "Your avr-gcc and avr-libc are too old, please upgrade" | |||||
| #endif | |||||
| #if (GCC_VERSION >= 40300) && (GCC_VERSION < 40302) | |||||
| // gcc 4.3.0 fails to save context for some interrupt routines - very ugly | |||||
| #warning "Buggy GCC 4.3.0 compiler, please upgrade!" | |||||
| #endif | |||||
| #endif | |||||
| #include <avr/interrupt.h> | |||||
| #include "wiring.h" | |||||
| #ifdef __cplusplus | |||||
| #include "usb_api.h" | |||||
| #include "WCharacter.h" | |||||
| #include "WString.h" | |||||
| #include "HardwareSerial.h" | |||||
| #include "elapsedMillis.h" | |||||
| uint16_t makeWord(uint16_t w); | |||||
| uint16_t makeWord(byte h, byte l); | |||||
| #define word(...) makeWord(__VA_ARGS__) | |||||
| unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L); | |||||
| void tone(uint8_t pin, uint16_t frequency, uint32_t duration = 0); | |||||
| void noTone(uint8_t pin); | |||||
| // WMath prototypes | |||||
| long random(long); | |||||
| long random(long, long); | |||||
| void randomSeed(unsigned int); | |||||
| long map(long, long, long, long, long); | |||||
| #include "pins_arduino.h" | |||||
| #endif // __cplusplus | |||||
| #endif // WProgram_h |
| /* | |||||
| WString.cpp - String library for Wiring & Arduino | |||||
| ...mostly rewritten by Paul Stoffregen... | |||||
| Copyright (c) 2009-10 Hernando Barragan. All rights reserved. | |||||
| Copyright 2011, 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 | |||||
| */ | |||||
| #include "WString.h" | |||||
| /*********************************************/ | |||||
| /* Constructors */ | |||||
| /*********************************************/ | |||||
| String::String(const char *cstr) | |||||
| { | |||||
| init(); | |||||
| if (cstr) copy(cstr, strlen(cstr)); | |||||
| } | |||||
| String::String(const __FlashStringHelper *pgmstr) | |||||
| { | |||||
| init(); | |||||
| *this = pgmstr; | |||||
| } | |||||
| String::String(const String &value) | |||||
| { | |||||
| init(); | |||||
| *this = value; | |||||
| } | |||||
| #ifdef __GXX_EXPERIMENTAL_CXX0X__ | |||||
| String::String(String &&rval) | |||||
| { | |||||
| init(); | |||||
| move(rval); | |||||
| } | |||||
| String::String(StringSumHelper &&rval) | |||||
| { | |||||
| init(); | |||||
| move(rval); | |||||
| } | |||||
| #endif | |||||
| String::String(char c) | |||||
| { | |||||
| init(); | |||||
| *this = c; | |||||
| } | |||||
| String::String(unsigned char c) | |||||
| { | |||||
| init(); | |||||
| char buf[4]; | |||||
| utoa(c, buf, 10); | |||||
| *this = buf; | |||||
| } | |||||
| String::String(const int value, unsigned char base) | |||||
| { | |||||
| init(); | |||||
| char buf[18]; | |||||
| itoa(value, buf, base); | |||||
| *this = buf; | |||||
| } | |||||
| String::String(unsigned int value, unsigned char base) | |||||
| { | |||||
| init(); | |||||
| char buf[17]; | |||||
| utoa(value, buf, base); | |||||
| *this = buf; | |||||
| } | |||||
| String::String(long value, unsigned char base) | |||||
| { | |||||
| init(); | |||||
| char buf[34]; | |||||
| ltoa(value, buf, base); | |||||
| *this = buf; | |||||
| } | |||||
| String::String(unsigned long value, unsigned char base) | |||||
| { | |||||
| init(); | |||||
| char buf[33]; | |||||
| ultoa(value, buf, base); | |||||
| *this = buf; | |||||
| } | |||||
| String::String(float num, unsigned char digits) | |||||
| { | |||||
| init(); | |||||
| char buf[40]; | |||||
| *this = dtostrf(num, digits + 2, digits, buf); | |||||
| } | |||||
| String::String(double num, unsigned char digits) | |||||
| { | |||||
| init(); | |||||
| char buf[40]; | |||||
| *this = dtostrf(num, digits + 2, digits, buf); | |||||
| } | |||||
| String::~String() | |||||
| { | |||||
| free(buffer); | |||||
| } | |||||
| /*********************************************/ | |||||
| /* Memory Management */ | |||||
| /*********************************************/ | |||||
| inline void String::init(void) | |||||
| { | |||||
| buffer = NULL; | |||||
| capacity = 0; | |||||
| len = 0; | |||||
| flags = 0; | |||||
| } | |||||
| unsigned char String::reserve(unsigned int size) | |||||
| { | |||||
| if (capacity >= size) return 1; | |||||
| if (changeBuffer(size)) { | |||||
| if (len == 0) buffer[0] = 0; | |||||
| return 1; | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| unsigned char String::changeBuffer(unsigned int maxStrLen) | |||||
| { | |||||
| char *newbuffer = (char *)realloc(buffer, maxStrLen + 1); | |||||
| if (newbuffer) { | |||||
| buffer = newbuffer; | |||||
| capacity = maxStrLen; | |||||
| return 1; | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| /*********************************************/ | |||||
| /* Copy and Move */ | |||||
| /*********************************************/ | |||||
| String & String::copy(const char *cstr, unsigned int length) | |||||
| { | |||||
| if (length == 0) { | |||||
| if (buffer) buffer[0] = 0; | |||||
| len = 0; | |||||
| return *this; | |||||
| } | |||||
| if (!reserve(length)) { | |||||
| if (buffer) { | |||||
| free(buffer); | |||||
| buffer = NULL; | |||||
| } | |||||
| len = capacity = 0; | |||||
| return *this; | |||||
| } | |||||
| len = length; | |||||
| strcpy(buffer, cstr); | |||||
| return *this; | |||||
| } | |||||
| String & String::copy(const __FlashStringHelper *pgmstr) | |||||
| { | |||||
| unsigned int length = strlen_P((const char PROGMEM *)pgmstr); | |||||
| if (!reserve(length)) { | |||||
| if (buffer) { | |||||
| free(buffer); | |||||
| buffer = NULL; | |||||
| } | |||||
| len = capacity = 0; | |||||
| return *this; | |||||
| } | |||||
| len = length; | |||||
| strcpy_P(buffer, (const char PROGMEM *)pgmstr); | |||||
| return *this; | |||||
| } | |||||
| void String::move(String &rhs) | |||||
| { | |||||
| if (buffer) { | |||||
| if (capacity >= rhs.len) { | |||||
| strcpy(buffer, rhs.buffer); | |||||
| len = rhs.len; | |||||
| rhs.len = 0; | |||||
| return; | |||||
| } else { | |||||
| free(buffer); | |||||
| } | |||||
| } | |||||
| buffer = rhs.buffer; | |||||
| capacity = rhs.capacity; | |||||
| len = rhs.len; | |||||
| rhs.buffer = NULL; | |||||
| rhs.capacity = 0; | |||||
| rhs.len = 0; | |||||
| } | |||||
| String & String::operator = (const String &rhs) | |||||
| { | |||||
| if (this == &rhs) return *this; | |||||
| return copy(rhs.buffer, rhs.len); | |||||
| } | |||||
| #ifdef __GXX_EXPERIMENTAL_CXX0X__ | |||||
| String & String::operator = (String &&rval) | |||||
| { | |||||
| if (this != &rval) move(rval); | |||||
| return *this; | |||||
| } | |||||
| String & String::operator = (StringSumHelper &&rval) | |||||
| { | |||||
| if (this != &rval) move(rval); | |||||
| return *this; | |||||
| } | |||||
| #endif | |||||
| String & String::operator = (const char *cstr) | |||||
| { | |||||
| if (cstr) { | |||||
| copy(cstr, strlen(cstr)); | |||||
| } else { | |||||
| len = 0; | |||||
| } | |||||
| return *this; | |||||
| } | |||||
| String & String::operator = (const __FlashStringHelper *pgmstr) | |||||
| { | |||||
| copy(pgmstr); | |||||
| return *this; | |||||
| } | |||||
| String & String::operator = (char c) | |||||
| { | |||||
| char buf[2]; | |||||
| buf[0] = c; | |||||
| buf[1] = 0; | |||||
| return copy(buf, 1); | |||||
| } | |||||
| /*********************************************/ | |||||
| /* Append */ | |||||
| /*********************************************/ | |||||
| String & String::append(const String &s) | |||||
| { | |||||
| return append(s.buffer, s.len); | |||||
| } | |||||
| String & String::append(const char *cstr, unsigned int length) | |||||
| { | |||||
| unsigned int newlen = len + length; | |||||
| if (length == 0 || !reserve(newlen)) return *this; | |||||
| strcpy(buffer + len, cstr); | |||||
| len = newlen; | |||||
| return *this; | |||||
| } | |||||
| String & String::append(const char *cstr) | |||||
| { | |||||
| if (cstr) append(cstr, strlen(cstr)); | |||||
| return *this; | |||||
| } | |||||
| String & String::append(const __FlashStringHelper *pgmstr) | |||||
| { | |||||
| unsigned int length = strlen_P((const char PROGMEM *)pgmstr); | |||||
| unsigned int newlen = len + length; | |||||
| if (length == 0 || !reserve(newlen)) return *this; | |||||
| strcpy_P(buffer + len, (const char PROGMEM *)pgmstr); | |||||
| len = newlen; | |||||
| return *this; | |||||
| } | |||||
| String & String::append(char c) | |||||
| { | |||||
| char buf[2]; | |||||
| buf[0] = c; | |||||
| buf[1] = 0; | |||||
| append(buf, 1); | |||||
| return *this; | |||||
| } | |||||
| String & String::append(int num) | |||||
| { | |||||
| char buf[7]; | |||||
| itoa(num, buf, 10); | |||||
| append(buf, strlen(buf)); | |||||
| return *this; | |||||
| } | |||||
| String & String::append(unsigned int num) | |||||
| { | |||||
| char buf[6]; | |||||
| utoa(num, buf, 10); | |||||
| append(buf, strlen(buf)); | |||||
| return *this; | |||||
| } | |||||
| String & String::append(long num) | |||||
| { | |||||
| char buf[12]; | |||||
| ltoa(num, buf, 10); | |||||
| append(buf, strlen(buf)); | |||||
| return *this; | |||||
| } | |||||
| String & String::append(unsigned long num) | |||||
| { | |||||
| char buf[11]; | |||||
| ultoa(num, buf, 10); | |||||
| append(buf, strlen(buf)); | |||||
| return *this; | |||||
| } | |||||
| String & String::append(float num) | |||||
| { | |||||
| char buf[30]; | |||||
| dtostrf(num, 4, 2, buf); | |||||
| append(buf, strlen(buf)); | |||||
| return *this; | |||||
| } | |||||
| /*********************************************/ | |||||
| /* Concatenate */ | |||||
| /*********************************************/ | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append(rhs.buffer, rhs.len); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| if (cstr) a.append(cstr, strlen(cstr)); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *pgmstr) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append(pgmstr); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, char c) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append(c); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char c) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append(c); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, int num) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append(num); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append(num); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, long num) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append(num); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append(num); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, float num) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append(num); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, double num) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append(num); | |||||
| return a; | |||||
| } | |||||
| /*********************************************/ | |||||
| /* Comparison */ | |||||
| /*********************************************/ | |||||
| int String::compareTo(const String &s) const | |||||
| { | |||||
| if (!buffer || !s.buffer) { | |||||
| if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer; | |||||
| if (buffer && len > 0) return *(unsigned char *)buffer; | |||||
| return 0; | |||||
| } | |||||
| return strcmp(buffer, s.buffer); | |||||
| } | |||||
| unsigned char String::equals(const String &s2) const | |||||
| { | |||||
| return (len == s2.len && compareTo(s2) == 0); | |||||
| } | |||||
| unsigned char String::equals(const char *cstr) const | |||||
| { | |||||
| if (len == 0) return (cstr == NULL || *cstr == 0); | |||||
| if (cstr == NULL) return buffer[0] == 0; | |||||
| return strcmp(buffer, cstr) == 0; | |||||
| } | |||||
| unsigned char String::equals(const __FlashStringHelper *pgmstr) const | |||||
| { | |||||
| if (len == 0) return pgm_read_byte(pgmstr) == 0; | |||||
| return strcmp_P(buffer, (const char PROGMEM *)pgmstr) == 0; | |||||
| } | |||||
| unsigned char String::operator<(const String &rhs) const | |||||
| { | |||||
| return compareTo(rhs) < 0; | |||||
| } | |||||
| unsigned char String::operator>(const String &rhs) const | |||||
| { | |||||
| return compareTo(rhs) > 0; | |||||
| } | |||||
| unsigned char String::operator<=(const String &rhs) const | |||||
| { | |||||
| return compareTo(rhs) <= 0; | |||||
| } | |||||
| unsigned char String::operator>=(const String &rhs) const | |||||
| { | |||||
| return compareTo(rhs) >= 0; | |||||
| } | |||||
| unsigned char String::equalsIgnoreCase( const String &s2 ) const | |||||
| { | |||||
| if (this == &s2) return 1; | |||||
| if (len != s2.len) return 0; | |||||
| if (len == 0) return 1; | |||||
| const char *p1 = buffer; | |||||
| const char *p2 = s2.buffer; | |||||
| while (*p1) { | |||||
| if (tolower(*p1++) != tolower(*p2++)) return 0; | |||||
| } | |||||
| return 1; | |||||
| } | |||||
| unsigned char String::startsWith( const String &s2 ) const | |||||
| { | |||||
| if (len < s2.len) return 0; | |||||
| return startsWith(s2, 0); | |||||
| } | |||||
| unsigned char String::startsWith( const String &s2, unsigned int offset ) const | |||||
| { | |||||
| if (offset > len - s2.len || !buffer || !s2.buffer) return 0; | |||||
| return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0; | |||||
| } | |||||
| unsigned char String::endsWith( const String &s2 ) const | |||||
| { | |||||
| if ( len < s2.len || !buffer || !s2.buffer) return 0; | |||||
| return strcmp(&buffer[len - s2.len], s2.buffer) == 0; | |||||
| } | |||||
| /*********************************************/ | |||||
| /* Character Access */ | |||||
| /*********************************************/ | |||||
| char String::charAt(unsigned int loc) const | |||||
| { | |||||
| return operator[](loc); | |||||
| } | |||||
| void String::setCharAt(unsigned int loc, char c) | |||||
| { | |||||
| if (loc < len) buffer[loc] = c; | |||||
| } | |||||
| char & String::operator[](unsigned int index) | |||||
| { | |||||
| static char dummy_writable_char; | |||||
| if (index >= len || !buffer) { | |||||
| dummy_writable_char = 0; | |||||
| return dummy_writable_char; | |||||
| } | |||||
| return buffer[index]; | |||||
| } | |||||
| char String::operator[]( unsigned int index ) const | |||||
| { | |||||
| if (index >= len || !buffer) return 0; | |||||
| return buffer[index]; | |||||
| } | |||||
| void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const | |||||
| { | |||||
| if (!bufsize || !buf) return; | |||||
| if (index >= len) { | |||||
| buf[0] = 0; | |||||
| return; | |||||
| } | |||||
| unsigned int n = bufsize - 1; | |||||
| if (n > len - index) n = len - index; | |||||
| strncpy((char *)buf, buffer + index, n); | |||||
| buf[n] = 0; | |||||
| } | |||||
| /*********************************************/ | |||||
| /* Search */ | |||||
| /*********************************************/ | |||||
| int String::indexOf(char c) const | |||||
| { | |||||
| return indexOf(c, 0); | |||||
| } | |||||
| int String::indexOf( char ch, unsigned int fromIndex ) const | |||||
| { | |||||
| if (fromIndex >= len) return -1; | |||||
| const char* temp = strchr(buffer + fromIndex, ch); | |||||
| if (temp == NULL) return -1; | |||||
| return temp - buffer; | |||||
| } | |||||
| int String::indexOf(const String &s2) const | |||||
| { | |||||
| return indexOf(s2, 0); | |||||
| } | |||||
| int String::indexOf(const String &s2, unsigned int fromIndex) const | |||||
| { | |||||
| if (fromIndex >= len) return -1; | |||||
| const char *found = strstr(buffer + fromIndex, s2.buffer); | |||||
| if (found == NULL) return -1; | |||||
| return found - buffer; | |||||
| } | |||||
| int String::lastIndexOf( char theChar ) const | |||||
| { | |||||
| return lastIndexOf(theChar, len - 1); | |||||
| } | |||||
| int String::lastIndexOf(char ch, unsigned int fromIndex) const | |||||
| { | |||||
| if (fromIndex >= len || fromIndex < 0) return -1; | |||||
| char tempchar = buffer[fromIndex + 1]; | |||||
| buffer[fromIndex + 1] = '\0'; | |||||
| char* temp = strrchr( buffer, ch ); | |||||
| buffer[fromIndex + 1] = tempchar; | |||||
| if (temp == NULL) return -1; | |||||
| return temp - buffer; | |||||
| } | |||||
| int String::lastIndexOf(const String &s2) const | |||||
| { | |||||
| return lastIndexOf(s2, len - s2.len); | |||||
| } | |||||
| int String::lastIndexOf(const String &s2, unsigned int fromIndex) const | |||||
| { | |||||
| if (s2.len == 0 || len == 0 || s2.len > len || fromIndex < 0) return -1; | |||||
| if (fromIndex >= len) fromIndex = len - 1; | |||||
| int found = -1; | |||||
| for (char *p = buffer; p <= buffer + fromIndex; p++) { | |||||
| p = strstr(p, s2.buffer); | |||||
| if (!p) break; | |||||
| if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer; | |||||
| } | |||||
| return found; | |||||
| } | |||||
| String String::substring( unsigned int left ) const | |||||
| { | |||||
| return substring(left, len); | |||||
| } | |||||
| String String::substring(unsigned int left, unsigned int right) const | |||||
| { | |||||
| if (left > right) { | |||||
| unsigned int temp = right; | |||||
| right = left; | |||||
| left = temp; | |||||
| } | |||||
| String out; | |||||
| if (left > len) return out; | |||||
| if (right > len) right = len; | |||||
| char temp = buffer[right]; // save the replaced character | |||||
| buffer[right] = '\0'; | |||||
| out = buffer + left; // pointer arithmetic | |||||
| buffer[right] = temp; //restore character | |||||
| return out; | |||||
| } | |||||
| /*********************************************/ | |||||
| /* Modification */ | |||||
| /*********************************************/ | |||||
| String & String::replace(char find, char replace) | |||||
| { | |||||
| if (!buffer) return *this; | |||||
| for (char *p = buffer; *p; p++) { | |||||
| if (*p == find) *p = replace; | |||||
| } | |||||
| return *this; | |||||
| } | |||||
| String & String::replace(const String& find, const String& replace) | |||||
| { | |||||
| if (len == 0 || find.len == 0) return *this; | |||||
| int diff = replace.len - find.len; | |||||
| char *readFrom = buffer; | |||||
| char *foundAt; | |||||
| if (diff == 0) { | |||||
| while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { | |||||
| memcpy(foundAt, replace.buffer, replace.len); | |||||
| readFrom = foundAt + replace.len; | |||||
| } | |||||
| } else if (diff < 0) { | |||||
| char *writeTo = buffer; | |||||
| while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { | |||||
| unsigned int n = foundAt - readFrom; | |||||
| memcpy(writeTo, readFrom, n); | |||||
| writeTo += n; | |||||
| memcpy(writeTo, replace.buffer, replace.len); | |||||
| writeTo += replace.len; | |||||
| readFrom = foundAt + find.len; | |||||
| len += diff; | |||||
| } | |||||
| strcpy(writeTo, readFrom); | |||||
| } else { | |||||
| unsigned int size = len; // compute size needed for result | |||||
| while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { | |||||
| readFrom = foundAt + find.len; | |||||
| size += diff; | |||||
| } | |||||
| if (size == len) return *this; | |||||
| if (size > capacity && !changeBuffer(size)) return *this; | |||||
| int index = len - 1; | |||||
| while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) { | |||||
| readFrom = buffer + index + find.len; | |||||
| memmove(readFrom + diff, readFrom, len - (readFrom - buffer)); | |||||
| len += diff; | |||||
| buffer[len] = 0; | |||||
| memcpy(buffer + index, replace.buffer, replace.len); | |||||
| index--; | |||||
| } | |||||
| } | |||||
| return *this; | |||||
| } | |||||
| String & String::remove(unsigned int index) | |||||
| { | |||||
| if (index < len) { | |||||
| len = index; | |||||
| buffer[len] = 0; | |||||
| } | |||||
| return *this; | |||||
| } | |||||
| String & String::remove(unsigned int index, unsigned int count) | |||||
| { | |||||
| if (index < len && count > 0) { | |||||
| if (index + count > len) count = len - index; | |||||
| len = len - count; | |||||
| memmove(buffer + index, buffer + index + count, len - index); | |||||
| buffer[len] = 0; | |||||
| } | |||||
| return *this; | |||||
| } | |||||
| String & String::toLowerCase(void) | |||||
| { | |||||
| if (!buffer) return *this; | |||||
| for (char *p = buffer; *p; p++) { | |||||
| *p = tolower(*p); | |||||
| } | |||||
| return *this; | |||||
| } | |||||
| String & String::toUpperCase(void) | |||||
| { | |||||
| if (!buffer) return *this; | |||||
| for (char *p = buffer; *p; p++) { | |||||
| *p = toupper(*p); | |||||
| } | |||||
| return *this; | |||||
| } | |||||
| String & String::trim(void) | |||||
| { | |||||
| if (!buffer || len == 0) return *this; | |||||
| char *begin = buffer; | |||||
| while (isspace(*begin)) begin++; | |||||
| char *end = buffer + len - 1; | |||||
| while (isspace(*end) && end >= begin) end--; | |||||
| len = end + 1 - begin; | |||||
| if (begin > buffer) memcpy(buffer, begin, len); | |||||
| buffer[len] = 0; | |||||
| return *this; | |||||
| } | |||||
| /*********************************************/ | |||||
| /* Parsing / Conversion */ | |||||
| /*********************************************/ | |||||
| long String::toInt(void) const | |||||
| { | |||||
| if (buffer) return atol(buffer); | |||||
| return 0; | |||||
| } | |||||
| float String::toFloat(void) const | |||||
| { | |||||
| if (buffer) return atof(buffer); | |||||
| return 0.0; | |||||
| } | |||||
| /* | |||||
| WString.h - String library for Wiring & Arduino | |||||
| ...mostly rewritten by Paul Stoffregen... | |||||
| Copyright (c) 2009-10 Hernando Barragan. All right reserved. | |||||
| Copyright 2011, 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 | |||||
| */ | |||||
| #ifndef String_class_h | |||||
| #define String_class_h | |||||
| #ifdef __cplusplus | |||||
| #include <stdlib.h> | |||||
| #include <string.h> | |||||
| #include <ctype.h> | |||||
| #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. | |||||
| // -felide-constructors | |||||
| // -std=c++0x | |||||
| // Brian Cook's "no overhead" Flash String type (message on Dec 14, 2010) | |||||
| // modified by Mikal Hart for his FlashString library | |||||
| class __FlashStringHelper; | |||||
| #ifndef F | |||||
| #define F(string_literal) ((const __FlashStringHelper *)(PSTR(string_literal))) | |||||
| #endif | |||||
| // An inherited class for holding the result of a concatenation. These | |||||
| // result objects are assumed to be writable by subsequent concatenations. | |||||
| class StringSumHelper; | |||||
| // The string class | |||||
| class String | |||||
| { | |||||
| public: | |||||
| // constructors | |||||
| String(const char *cstr = NULL); | |||||
| String(const __FlashStringHelper *pgmstr); | |||||
| String(const String &str); | |||||
| #ifdef __GXX_EXPERIMENTAL_CXX0X__ | |||||
| String(String &&rval); | |||||
| String(StringSumHelper &&rval); | |||||
| #endif | |||||
| String(char c); | |||||
| String(unsigned char c); | |||||
| String(int, unsigned char base=10); | |||||
| String(unsigned int, unsigned char base=10); | |||||
| String(long, unsigned char base=10); | |||||
| String(unsigned long, unsigned char base=10); | |||||
| String(float num, unsigned char digits=2); | |||||
| String(double num, unsigned char digits=2); | |||||
| ~String(void); | |||||
| // memory management | |||||
| unsigned char reserve(unsigned int size); | |||||
| inline unsigned int length(void) const {return len;} | |||||
| // copy and move | |||||
| String & copy(const char *cstr, unsigned int length); | |||||
| String & copy(const __FlashStringHelper *pgmstr); | |||||
| void move(String &rhs); | |||||
| String & operator = (const String &rhs); | |||||
| String & operator = (const char *cstr); | |||||
| String & operator = (const __FlashStringHelper *pgmstr); | |||||
| #ifdef __GXX_EXPERIMENTAL_CXX0X__ | |||||
| String & operator = (String &&rval); | |||||
| String & operator = (StringSumHelper &&rval); | |||||
| #endif | |||||
| String & operator = (char c); | |||||
| // append | |||||
| String & append(const String &str); | |||||
| String & append(const char *cstr); | |||||
| String & append(const __FlashStringHelper *pgmstr); | |||||
| String & append(char c); | |||||
| String & append(unsigned char c) {return append((int)c);} | |||||
| String & append(int num); | |||||
| String & append(unsigned int num); | |||||
| String & append(long num); | |||||
| String & append(unsigned long num); | |||||
| String & append(float num); | |||||
| String & append(double num) {return append((float)num);} | |||||
| String & operator += (const String &rhs) {return append(rhs);} | |||||
| String & operator += (const char *cstr) {return append(cstr);} | |||||
| String & operator += (const __FlashStringHelper *pgmstr) {return append(pgmstr);} | |||||
| String & operator += (char c) {return append(c);} | |||||
| String & operator += (unsigned char c) {return append((int)c);} | |||||
| String & operator += (int num) {return append(num);} | |||||
| String & operator += (unsigned int num) {return append(num);} | |||||
| String & operator += (long num) {return append(num);} | |||||
| String & operator += (unsigned long num) {return append(num);} | |||||
| String & operator += (float num) {return append(num);} | |||||
| String & operator += (double num) {return append(num);} | |||||
| // concatenate | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *pgmstr); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, char c); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char c); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, int num); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, long num); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, float num); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, double num); | |||||
| String & concat(const String &str) {return append(str);} | |||||
| String & concat(const char *cstr) {return append(cstr);} | |||||
| String & concat(const __FlashStringHelper *pgmstr) {return append(pgmstr);} | |||||
| String & concat(char c) {return append(c);} | |||||
| String & concat(unsigned char c) {return append((int)c);} | |||||
| String & concat(int num) {return append(num);} | |||||
| String & concat(unsigned int num) {return append(num);} | |||||
| String & concat(long num) {return append(num);} | |||||
| String & concat(unsigned long num) {return append(num);} | |||||
| String & concat(float num) {return append(num);} | |||||
| String & concat(double num) {return append(num);} | |||||
| // comparison | |||||
| int compareTo(const String &s) const; | |||||
| unsigned char equals(const String &s) const; | |||||
| unsigned char equals(const char *cstr) const; | |||||
| unsigned char equals(const __FlashStringHelper *pgmstr) const; | |||||
| unsigned char operator == (const String &rhs) const {return equals(rhs);} | |||||
| unsigned char operator == (const char *cstr) const {return equals(cstr);} | |||||
| unsigned char operator == (const __FlashStringHelper *pgmstr) const {return equals(pgmstr);} | |||||
| unsigned char operator != (const String &rhs) const {return !equals(rhs);} | |||||
| unsigned char operator != (const char *cstr) const {return !equals(cstr);} | |||||
| unsigned char operator != (const __FlashStringHelper *pgmstr) const {return !equals(pgmstr);} | |||||
| unsigned char operator < (const String &rhs) const; | |||||
| unsigned char operator > (const String &rhs) const; | |||||
| unsigned char operator <= (const String &rhs) const; | |||||
| unsigned char operator >= (const String &rhs) const; | |||||
| unsigned char equalsIgnoreCase(const String &s) const; | |||||
| unsigned char startsWith( const String &prefix) const; | |||||
| unsigned char startsWith(const String &prefix, unsigned int offset) const; | |||||
| unsigned char endsWith(const String &suffix) const; | |||||
| // character acccess | |||||
| char charAt(unsigned int index) const; | |||||
| void setCharAt(unsigned int index, char c); | |||||
| char operator [] (unsigned int index) const; | |||||
| char& operator [] (unsigned int index); | |||||
| void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const; | |||||
| void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const | |||||
| {getBytes((unsigned char *)buf, bufsize, index);} | |||||
| const char * c_str() const { return buffer; } | |||||
| // search | |||||
| int indexOf( char ch ) const; | |||||
| int indexOf( char ch, unsigned int fromIndex ) const; | |||||
| int indexOf( const String &str ) const; | |||||
| int indexOf( const String &str, unsigned int fromIndex ) const; | |||||
| int lastIndexOf( char ch ) const; | |||||
| int lastIndexOf( char ch, unsigned int fromIndex ) const; | |||||
| int lastIndexOf( const String &str ) const; | |||||
| int lastIndexOf( const String &str, unsigned int fromIndex ) const; | |||||
| String substring( unsigned int beginIndex ) const; | |||||
| String substring( unsigned int beginIndex, unsigned int endIndex ) const; | |||||
| // modification | |||||
| String & replace(char find, char replace); | |||||
| String & replace(const String& find, const String& replace); | |||||
| String & remove(unsigned int index); | |||||
| String & remove(unsigned int index, unsigned int count); | |||||
| String & toLowerCase(void); | |||||
| String & toUpperCase(void); | |||||
| String & trim(void); | |||||
| // parsing/conversion | |||||
| long toInt(void) const; | |||||
| float toFloat(void) const; | |||||
| protected: | |||||
| char *buffer; // the actual char array | |||||
| unsigned int capacity; // the array length minus one (for the '\0') | |||||
| unsigned int len; // the String length (not counting the '\0') | |||||
| unsigned char flags; // unused, for future features | |||||
| protected: | |||||
| void init(void); | |||||
| unsigned char changeBuffer(unsigned int maxStrLen); | |||||
| String & append(const char *cstr, unsigned int length); | |||||
| }; | |||||
| class StringSumHelper : public String | |||||
| { | |||||
| public: | |||||
| StringSumHelper(const String &s) : String(s) {} | |||||
| StringSumHelper(const char *p) : String(p) {} | |||||
| StringSumHelper(const __FlashStringHelper *pgmstr) : String(pgmstr) {} | |||||
| StringSumHelper(char c) : String(c) {} | |||||
| StringSumHelper(unsigned char c) : String(c) {} | |||||
| StringSumHelper(int num) : String(num, 10) {} | |||||
| StringSumHelper(unsigned int num) : String(num, 10) {} | |||||
| StringSumHelper(long num) : String(num, 10) {} | |||||
| StringSumHelper(unsigned long num) : String(num, 10) {} | |||||
| }; | |||||
| #endif // __cplusplus | |||||
| #endif // String_class_h |
| #ifndef Binary_h | |||||
| #define Binary_h | |||||
| #define B0 0 | |||||
| #define B00 0 | |||||
| #define B000 0 | |||||
| #define B0000 0 | |||||
| #define B00000 0 | |||||
| #define B000000 0 | |||||
| #define B0000000 0 | |||||
| #define B00000000 0 | |||||
| #define B1 1 | |||||
| #define B01 1 | |||||
| #define B001 1 | |||||
| #define B0001 1 | |||||
| #define B00001 1 | |||||
| #define B000001 1 | |||||
| #define B0000001 1 | |||||
| #define B00000001 1 | |||||
| #define B10 2 | |||||
| #define B010 2 | |||||
| #define B0010 2 | |||||
| #define B00010 2 | |||||
| #define B000010 2 | |||||
| #define B0000010 2 | |||||
| #define B00000010 2 | |||||
| #define B11 3 | |||||
| #define B011 3 | |||||
| #define B0011 3 | |||||
| #define B00011 3 | |||||
| #define B000011 3 | |||||
| #define B0000011 3 | |||||
| #define B00000011 3 | |||||
| #define B100 4 | |||||
| #define B0100 4 | |||||
| #define B00100 4 | |||||
| #define B000100 4 | |||||
| #define B0000100 4 | |||||
| #define B00000100 4 | |||||
| #define B101 5 | |||||
| #define B0101 5 | |||||
| #define B00101 5 | |||||
| #define B000101 5 | |||||
| #define B0000101 5 | |||||
| #define B00000101 5 | |||||
| #define B110 6 | |||||
| #define B0110 6 | |||||
| #define B00110 6 | |||||
| #define B000110 6 | |||||
| #define B0000110 6 | |||||
| #define B00000110 6 | |||||
| #define B111 7 | |||||
| #define B0111 7 | |||||
| #define B00111 7 | |||||
| #define B000111 7 | |||||
| #define B0000111 7 | |||||
| #define B00000111 7 | |||||
| #define B1000 8 | |||||
| #define B01000 8 | |||||
| #define B001000 8 | |||||
| #define B0001000 8 | |||||
| #define B00001000 8 | |||||
| #define B1001 9 | |||||
| #define B01001 9 | |||||
| #define B001001 9 | |||||
| #define B0001001 9 | |||||
| #define B00001001 9 | |||||
| #define B1010 10 | |||||
| #define B01010 10 | |||||
| #define B001010 10 | |||||
| #define B0001010 10 | |||||
| #define B00001010 10 | |||||
| #define B1011 11 | |||||
| #define B01011 11 | |||||
| #define B001011 11 | |||||
| #define B0001011 11 | |||||
| #define B00001011 11 | |||||
| #define B1100 12 | |||||
| #define B01100 12 | |||||
| #define B001100 12 | |||||
| #define B0001100 12 | |||||
| #define B00001100 12 | |||||
| #define B1101 13 | |||||
| #define B01101 13 | |||||
| #define B001101 13 | |||||
| #define B0001101 13 | |||||
| #define B00001101 13 | |||||
| #define B1110 14 | |||||
| #define B01110 14 | |||||
| #define B001110 14 | |||||
| #define B0001110 14 | |||||
| #define B00001110 14 | |||||
| #define B1111 15 | |||||
| #define B01111 15 | |||||
| #define B001111 15 | |||||
| #define B0001111 15 | |||||
| #define B00001111 15 | |||||
| #define B10000 16 | |||||
| #define B010000 16 | |||||
| #define B0010000 16 | |||||
| #define B00010000 16 | |||||
| #define B10001 17 | |||||
| #define B010001 17 | |||||
| #define B0010001 17 | |||||
| #define B00010001 17 | |||||
| #define B10010 18 | |||||
| #define B010010 18 | |||||
| #define B0010010 18 | |||||
| #define B00010010 18 | |||||
| #define B10011 19 | |||||
| #define B010011 19 | |||||
| #define B0010011 19 | |||||
| #define B00010011 19 | |||||
| #define B10100 20 | |||||
| #define B010100 20 | |||||
| #define B0010100 20 | |||||
| #define B00010100 20 | |||||
| #define B10101 21 | |||||
| #define B010101 21 | |||||
| #define B0010101 21 | |||||
| #define B00010101 21 | |||||
| #define B10110 22 | |||||
| #define B010110 22 | |||||
| #define B0010110 22 | |||||
| #define B00010110 22 | |||||
| #define B10111 23 | |||||
| #define B010111 23 | |||||
| #define B0010111 23 | |||||
| #define B00010111 23 | |||||
| #define B11000 24 | |||||
| #define B011000 24 | |||||
| #define B0011000 24 | |||||
| #define B00011000 24 | |||||
| #define B11001 25 | |||||
| #define B011001 25 | |||||
| #define B0011001 25 | |||||
| #define B00011001 25 | |||||
| #define B11010 26 | |||||
| #define B011010 26 | |||||
| #define B0011010 26 | |||||
| #define B00011010 26 | |||||
| #define B11011 27 | |||||
| #define B011011 27 | |||||
| #define B0011011 27 | |||||
| #define B00011011 27 | |||||
| #define B11100 28 | |||||
| #define B011100 28 | |||||
| #define B0011100 28 | |||||
| #define B00011100 28 | |||||
| #define B11101 29 | |||||
| #define B011101 29 | |||||
| #define B0011101 29 | |||||
| #define B00011101 29 | |||||
| #define B11110 30 | |||||
| #define B011110 30 | |||||
| #define B0011110 30 | |||||
| #define B00011110 30 | |||||
| #define B11111 31 | |||||
| #define B011111 31 | |||||
| #define B0011111 31 | |||||
| #define B00011111 31 | |||||
| #define B100000 32 | |||||
| #define B0100000 32 | |||||
| #define B00100000 32 | |||||
| #define B100001 33 | |||||
| #define B0100001 33 | |||||
| #define B00100001 33 | |||||
| #define B100010 34 | |||||
| #define B0100010 34 | |||||
| #define B00100010 34 | |||||
| #define B100011 35 | |||||
| #define B0100011 35 | |||||
| #define B00100011 35 | |||||
| #define B100100 36 | |||||
| #define B0100100 36 | |||||
| #define B00100100 36 | |||||
| #define B100101 37 | |||||
| #define B0100101 37 | |||||
| #define B00100101 37 | |||||
| #define B100110 38 | |||||
| #define B0100110 38 | |||||
| #define B00100110 38 | |||||
| #define B100111 39 | |||||
| #define B0100111 39 | |||||
| #define B00100111 39 | |||||
| #define B101000 40 | |||||
| #define B0101000 40 | |||||
| #define B00101000 40 | |||||
| #define B101001 41 | |||||
| #define B0101001 41 | |||||
| #define B00101001 41 | |||||
| #define B101010 42 | |||||
| #define B0101010 42 | |||||
| #define B00101010 42 | |||||
| #define B101011 43 | |||||
| #define B0101011 43 | |||||
| #define B00101011 43 | |||||
| #define B101100 44 | |||||
| #define B0101100 44 | |||||
| #define B00101100 44 | |||||
| #define B101101 45 | |||||
| #define B0101101 45 | |||||
| #define B00101101 45 | |||||
| #define B101110 46 | |||||
| #define B0101110 46 | |||||
| #define B00101110 46 | |||||
| #define B101111 47 | |||||
| #define B0101111 47 | |||||
| #define B00101111 47 | |||||
| #define B110000 48 | |||||
| #define B0110000 48 | |||||
| #define B00110000 48 | |||||
| #define B110001 49 | |||||
| #define B0110001 49 | |||||
| #define B00110001 49 | |||||
| #define B110010 50 | |||||
| #define B0110010 50 | |||||
| #define B00110010 50 | |||||
| #define B110011 51 | |||||
| #define B0110011 51 | |||||
| #define B00110011 51 | |||||
| #define B110100 52 | |||||
| #define B0110100 52 | |||||
| #define B00110100 52 | |||||
| #define B110101 53 | |||||
| #define B0110101 53 | |||||
| #define B00110101 53 | |||||
| #define B110110 54 | |||||
| #define B0110110 54 | |||||
| #define B00110110 54 | |||||
| #define B110111 55 | |||||
| #define B0110111 55 | |||||
| #define B00110111 55 | |||||
| #define B111000 56 | |||||
| #define B0111000 56 | |||||
| #define B00111000 56 | |||||
| #define B111001 57 | |||||
| #define B0111001 57 | |||||
| #define B00111001 57 | |||||
| #define B111010 58 | |||||
| #define B0111010 58 | |||||
| #define B00111010 58 | |||||
| #define B111011 59 | |||||
| #define B0111011 59 | |||||
| #define B00111011 59 | |||||
| #define B111100 60 | |||||
| #define B0111100 60 | |||||
| #define B00111100 60 | |||||
| #define B111101 61 | |||||
| #define B0111101 61 | |||||
| #define B00111101 61 | |||||
| #define B111110 62 | |||||
| #define B0111110 62 | |||||
| #define B00111110 62 | |||||
| #define B111111 63 | |||||
| #define B0111111 63 | |||||
| #define B00111111 63 | |||||
| #define B1000000 64 | |||||
| #define B01000000 64 | |||||
| #define B1000001 65 | |||||
| #define B01000001 65 | |||||
| #define B1000010 66 | |||||
| #define B01000010 66 | |||||
| #define B1000011 67 | |||||
| #define B01000011 67 | |||||
| #define B1000100 68 | |||||
| #define B01000100 68 | |||||
| #define B1000101 69 | |||||
| #define B01000101 69 | |||||
| #define B1000110 70 | |||||
| #define B01000110 70 | |||||
| #define B1000111 71 | |||||
| #define B01000111 71 | |||||
| #define B1001000 72 | |||||
| #define B01001000 72 | |||||
| #define B1001001 73 | |||||
| #define B01001001 73 | |||||
| #define B1001010 74 | |||||
| #define B01001010 74 | |||||
| #define B1001011 75 | |||||
| #define B01001011 75 | |||||
| #define B1001100 76 | |||||
| #define B01001100 76 | |||||
| #define B1001101 77 | |||||
| #define B01001101 77 | |||||
| #define B1001110 78 | |||||
| #define B01001110 78 | |||||
| #define B1001111 79 | |||||
| #define B01001111 79 | |||||
| #define B1010000 80 | |||||
| #define B01010000 80 | |||||
| #define B1010001 81 | |||||
| #define B01010001 81 | |||||
| #define B1010010 82 | |||||
| #define B01010010 82 | |||||
| #define B1010011 83 | |||||
| #define B01010011 83 | |||||
| #define B1010100 84 | |||||
| #define B01010100 84 | |||||
| #define B1010101 85 | |||||
| #define B01010101 85 | |||||
| #define B1010110 86 | |||||
| #define B01010110 86 | |||||
| #define B1010111 87 | |||||
| #define B01010111 87 | |||||
| #define B1011000 88 | |||||
| #define B01011000 88 | |||||
| #define B1011001 89 | |||||
| #define B01011001 89 | |||||
| #define B1011010 90 | |||||
| #define B01011010 90 | |||||
| #define B1011011 91 | |||||
| #define B01011011 91 | |||||
| #define B1011100 92 | |||||
| #define B01011100 92 | |||||
| #define B1011101 93 | |||||
| #define B01011101 93 | |||||
| #define B1011110 94 | |||||
| #define B01011110 94 | |||||
| #define B1011111 95 | |||||
| #define B01011111 95 | |||||
| #define B1100000 96 | |||||
| #define B01100000 96 | |||||
| #define B1100001 97 | |||||
| #define B01100001 97 | |||||
| #define B1100010 98 | |||||
| #define B01100010 98 | |||||
| #define B1100011 99 | |||||
| #define B01100011 99 | |||||
| #define B1100100 100 | |||||
| #define B01100100 100 | |||||
| #define B1100101 101 | |||||
| #define B01100101 101 | |||||
| #define B1100110 102 | |||||
| #define B01100110 102 | |||||
| #define B1100111 103 | |||||
| #define B01100111 103 | |||||
| #define B1101000 104 | |||||
| #define B01101000 104 | |||||
| #define B1101001 105 | |||||
| #define B01101001 105 | |||||
| #define B1101010 106 | |||||
| #define B01101010 106 | |||||
| #define B1101011 107 | |||||
| #define B01101011 107 | |||||
| #define B1101100 108 | |||||
| #define B01101100 108 | |||||
| #define B1101101 109 | |||||
| #define B01101101 109 | |||||
| #define B1101110 110 | |||||
| #define B01101110 110 | |||||
| #define B1101111 111 | |||||
| #define B01101111 111 | |||||
| #define B1110000 112 | |||||
| #define B01110000 112 | |||||
| #define B1110001 113 | |||||
| #define B01110001 113 | |||||
| #define B1110010 114 | |||||
| #define B01110010 114 | |||||
| #define B1110011 115 | |||||
| #define B01110011 115 | |||||
| #define B1110100 116 | |||||
| #define B01110100 116 | |||||
| #define B1110101 117 | |||||
| #define B01110101 117 | |||||
| #define B1110110 118 | |||||
| #define B01110110 118 | |||||
| #define B1110111 119 | |||||
| #define B01110111 119 | |||||
| #define B1111000 120 | |||||
| #define B01111000 120 | |||||
| #define B1111001 121 | |||||
| #define B01111001 121 | |||||
| #define B1111010 122 | |||||
| #define B01111010 122 | |||||
| #define B1111011 123 | |||||
| #define B01111011 123 | |||||
| #define B1111100 124 | |||||
| #define B01111100 124 | |||||
| #define B1111101 125 | |||||
| #define B01111101 125 | |||||
| #define B1111110 126 | |||||
| #define B01111110 126 | |||||
| #define B1111111 127 | |||||
| #define B01111111 127 | |||||
| #define B10000000 128 | |||||
| #define B10000001 129 | |||||
| #define B10000010 130 | |||||
| #define B10000011 131 | |||||
| #define B10000100 132 | |||||
| #define B10000101 133 | |||||
| #define B10000110 134 | |||||
| #define B10000111 135 | |||||
| #define B10001000 136 | |||||
| #define B10001001 137 | |||||
| #define B10001010 138 | |||||
| #define B10001011 139 | |||||
| #define B10001100 140 | |||||
| #define B10001101 141 | |||||
| #define B10001110 142 | |||||
| #define B10001111 143 | |||||
| #define B10010000 144 | |||||
| #define B10010001 145 | |||||
| #define B10010010 146 | |||||
| #define B10010011 147 | |||||
| #define B10010100 148 | |||||
| #define B10010101 149 | |||||
| #define B10010110 150 | |||||
| #define B10010111 151 | |||||
| #define B10011000 152 | |||||
| #define B10011001 153 | |||||
| #define B10011010 154 | |||||
| #define B10011011 155 | |||||
| #define B10011100 156 | |||||
| #define B10011101 157 | |||||
| #define B10011110 158 | |||||
| #define B10011111 159 | |||||
| #define B10100000 160 | |||||
| #define B10100001 161 | |||||
| #define B10100010 162 | |||||
| #define B10100011 163 | |||||
| #define B10100100 164 | |||||
| #define B10100101 165 | |||||
| #define B10100110 166 | |||||
| #define B10100111 167 | |||||
| #define B10101000 168 | |||||
| #define B10101001 169 | |||||
| #define B10101010 170 | |||||
| #define B10101011 171 | |||||
| #define B10101100 172 | |||||
| #define B10101101 173 | |||||
| #define B10101110 174 | |||||
| #define B10101111 175 | |||||
| #define B10110000 176 | |||||
| #define B10110001 177 | |||||
| #define B10110010 178 | |||||
| #define B10110011 179 | |||||
| #define B10110100 180 | |||||
| #define B10110101 181 | |||||
| #define B10110110 182 | |||||
| #define B10110111 183 | |||||
| #define B10111000 184 | |||||
| #define B10111001 185 | |||||
| #define B10111010 186 | |||||
| #define B10111011 187 | |||||
| #define B10111100 188 | |||||
| #define B10111101 189 | |||||
| #define B10111110 190 | |||||
| #define B10111111 191 | |||||
| #define B11000000 192 | |||||
| #define B11000001 193 | |||||
| #define B11000010 194 | |||||
| #define B11000011 195 | |||||
| #define B11000100 196 | |||||
| #define B11000101 197 | |||||
| #define B11000110 198 | |||||
| #define B11000111 199 | |||||
| #define B11001000 200 | |||||
| #define B11001001 201 | |||||
| #define B11001010 202 | |||||
| #define B11001011 203 | |||||
| #define B11001100 204 | |||||
| #define B11001101 205 | |||||
| #define B11001110 206 | |||||
| #define B11001111 207 | |||||
| #define B11010000 208 | |||||
| #define B11010001 209 | |||||
| #define B11010010 210 | |||||
| #define B11010011 211 | |||||
| #define B11010100 212 | |||||
| #define B11010101 213 | |||||
| #define B11010110 214 | |||||
| #define B11010111 215 | |||||
| #define B11011000 216 | |||||
| #define B11011001 217 | |||||
| #define B11011010 218 | |||||
| #define B11011011 219 | |||||
| #define B11011100 220 | |||||
| #define B11011101 221 | |||||
| #define B11011110 222 | |||||
| #define B11011111 223 | |||||
| #define B11100000 224 | |||||
| #define B11100001 225 | |||||
| #define B11100010 226 | |||||
| #define B11100011 227 | |||||
| #define B11100100 228 | |||||
| #define B11100101 229 | |||||
| #define B11100110 230 | |||||
| #define B11100111 231 | |||||
| #define B11101000 232 | |||||
| #define B11101001 233 | |||||
| #define B11101010 234 | |||||
| #define B11101011 235 | |||||
| #define B11101100 236 | |||||
| #define B11101101 237 | |||||
| #define B11101110 238 | |||||
| #define B11101111 239 | |||||
| #define B11110000 240 | |||||
| #define B11110001 241 | |||||
| #define B11110010 242 | |||||
| #define B11110011 243 | |||||
| #define B11110100 244 | |||||
| #define B11110101 245 | |||||
| #define B11110110 246 | |||||
| #define B11110111 247 | |||||
| #define B11111000 248 | |||||
| #define B11111001 249 | |||||
| #define B11111010 250 | |||||
| #define B11111011 251 | |||||
| #define B11111100 252 | |||||
| #define B11111101 253 | |||||
| #define B11111110 254 | |||||
| #define B11111111 255 | |||||
| #endif |
| #ifndef CORE_TEENSY | |||||
| #define CORE_TEENSY | |||||
| #if defined(USB_SERIAL) | |||||
| #include "../usb_serial/core_id.h" | |||||
| #elif defined(USB_HID) | |||||
| #include "../usb_hid/core_id.h" | |||||
| #elif defined(USB_SERIAL_HID) | |||||
| #include "../usb_serial_hid/core_id.h" | |||||
| #elif defined(USB_DISK) || defined(USB_DISK_SDFLASH) | |||||
| #include "../usb_disk/core_id.h" | |||||
| #elif defined(USB_MIDI) | |||||
| #include "../usb_midi/core_id.h" | |||||
| #elif defined(USB_RAWHID) | |||||
| #include "../usb_rawhid/core_id.h" | |||||
| #elif defined(USB_FLIGHTSIM) | |||||
| #include "../usb_flightsim/core_id.h" | |||||
| #endif | |||||
| #endif |
| /* Elapsed time types - for easy-to-use measurements of elapsed time | |||||
| * http://www.pjrc.com/teensy/ | |||||
| * Copyright (c) 2011 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: | |||||
| * | |||||
| * 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 elapsedMillis_h | |||||
| #define elapsedMillis_h | |||||
| #ifdef __cplusplus | |||||
| #if ARDUINO >= 100 | |||||
| #include "Arduino.h" | |||||
| #else | |||||
| #include "WProgram.h" | |||||
| #endif | |||||
| class elapsedMillis | |||||
| { | |||||
| private: | |||||
| unsigned long ms; | |||||
| public: | |||||
| elapsedMillis(void) { ms = millis(); } | |||||
| elapsedMillis(unsigned long val) { ms = millis() - val; } | |||||
| elapsedMillis(const elapsedMillis &orig) { ms = orig.ms; } | |||||
| operator unsigned long () const { return millis() - ms; } | |||||
| elapsedMillis & operator = (const elapsedMillis &rhs) { ms = rhs.ms; return *this; } | |||||
| elapsedMillis & operator = (unsigned long val) { ms = millis() - val; return *this; } | |||||
| elapsedMillis & operator -= (unsigned long val) { ms += val ; return *this; } | |||||
| elapsedMillis & operator += (unsigned long val) { ms -= val ; return *this; } | |||||
| elapsedMillis operator - (int val) const { elapsedMillis r(*this); r.ms += val; return r; } | |||||
| elapsedMillis operator - (unsigned int val) const { elapsedMillis r(*this); r.ms += val; return r; } | |||||
| elapsedMillis operator - (long val) const { elapsedMillis r(*this); r.ms += val; return r; } | |||||
| elapsedMillis operator - (unsigned long val) const { elapsedMillis r(*this); r.ms += val; return r; } | |||||
| elapsedMillis operator + (int val) const { elapsedMillis r(*this); r.ms -= val; return r; } | |||||
| elapsedMillis operator + (unsigned int val) const { elapsedMillis r(*this); r.ms -= val; return r; } | |||||
| elapsedMillis operator + (long val) const { elapsedMillis r(*this); r.ms -= val; return r; } | |||||
| elapsedMillis operator + (unsigned long val) const { elapsedMillis r(*this); r.ms -= val; return r; } | |||||
| }; | |||||
| class elapsedMicros | |||||
| { | |||||
| private: | |||||
| unsigned long us; | |||||
| public: | |||||
| elapsedMicros(void) { us = micros(); } | |||||
| elapsedMicros(unsigned long val) { us = micros() - val; } | |||||
| elapsedMicros(const elapsedMicros &orig) { us = orig.us; } | |||||
| operator unsigned long () const { return micros() - us; } | |||||
| elapsedMicros & operator = (const elapsedMicros &rhs) { us = rhs.us; return *this; } | |||||
| elapsedMicros & operator = (unsigned long val) { us = micros() - val; return *this; } | |||||
| elapsedMicros & operator -= (unsigned long val) { us += val ; return *this; } | |||||
| elapsedMicros & operator += (unsigned long val) { us -= val ; return *this; } | |||||
| elapsedMicros operator - (int val) const { elapsedMicros r(*this); r.us += val; return r; } | |||||
| elapsedMicros operator - (unsigned int val) const { elapsedMicros r(*this); r.us += val; return r; } | |||||
| elapsedMicros operator - (long val) const { elapsedMicros r(*this); r.us += val; return r; } | |||||
| elapsedMicros operator - (unsigned long val) const { elapsedMicros r(*this); r.us += val; return r; } | |||||
| elapsedMicros operator + (int val) const { elapsedMicros r(*this); r.us -= val; return r; } | |||||
| elapsedMicros operator + (unsigned int val) const { elapsedMicros r(*this); r.us -= val; return r; } | |||||
| elapsedMicros operator + (long val) const { elapsedMicros r(*this); r.us -= val; return r; } | |||||
| elapsedMicros operator + (unsigned long val) const { elapsedMicros r(*this); r.us -= val; return r; } | |||||
| }; | |||||
| #endif // __cplusplus | |||||
| #endif // elapsedMillis_h |
| #include <avr/pgmspace.h> | |||||
| #include <stdint.h> | |||||
| #include "keylayouts.h" | |||||
| #ifdef M | |||||
| #undef M | |||||
| #endif | |||||
| #define M(n) ((n) & KEYCODE_MASK) | |||||
| const KEYCODE_TYPE PROGMEM keycodes_ascii[] = { | |||||
| M(ASCII_20), M(ASCII_21), M(ASCII_22), M(ASCII_23), | |||||
| M(ASCII_24), M(ASCII_25), M(ASCII_26), M(ASCII_27), | |||||
| M(ASCII_28), M(ASCII_29), M(ASCII_2A), M(ASCII_2B), | |||||
| M(ASCII_2C), M(ASCII_2D), M(ASCII_2E), M(ASCII_2F), | |||||
| M(ASCII_30), M(ASCII_31), M(ASCII_32), M(ASCII_33), | |||||
| M(ASCII_34), M(ASCII_35), M(ASCII_36), M(ASCII_37), | |||||
| M(ASCII_38), M(ASCII_39), M(ASCII_3A), M(ASCII_3B), | |||||
| M(ASCII_3C), M(ASCII_3D), M(ASCII_3E), M(ASCII_3F), | |||||
| M(ASCII_40), M(ASCII_41), M(ASCII_42), M(ASCII_43), | |||||
| M(ASCII_44), M(ASCII_45), M(ASCII_46), M(ASCII_47), | |||||
| M(ASCII_48), M(ASCII_49), M(ASCII_4A), M(ASCII_4B), | |||||
| M(ASCII_4C), M(ASCII_4D), M(ASCII_4E), M(ASCII_4F), | |||||
| M(ASCII_50), M(ASCII_51), M(ASCII_52), M(ASCII_53), | |||||
| M(ASCII_54), M(ASCII_55), M(ASCII_56), M(ASCII_57), | |||||
| M(ASCII_58), M(ASCII_59), M(ASCII_5A), M(ASCII_5B), | |||||
| M(ASCII_5C), M(ASCII_5D), M(ASCII_5E), M(ASCII_5F), | |||||
| M(ASCII_60), M(ASCII_61), M(ASCII_62), M(ASCII_63), | |||||
| M(ASCII_64), M(ASCII_65), M(ASCII_66), M(ASCII_67), | |||||
| M(ASCII_68), M(ASCII_69), M(ASCII_6A), M(ASCII_6B), | |||||
| M(ASCII_6C), M(ASCII_6D), M(ASCII_6E), M(ASCII_6F), | |||||
| M(ASCII_70), M(ASCII_71), M(ASCII_72), M(ASCII_73), | |||||
| M(ASCII_74), M(ASCII_75), M(ASCII_76), M(ASCII_77), | |||||
| M(ASCII_78), M(ASCII_79), M(ASCII_7A), M(ASCII_7B), | |||||
| M(ASCII_7C), M(ASCII_7D), M(ASCII_7E), M(ASCII_7F) | |||||
| }; | |||||
| #ifdef ISO_8859_1_A0 | |||||
| const KEYCODE_TYPE PROGMEM keycodes_iso_8859_1[] = { | |||||
| M(ISO_8859_1_A0), M(ISO_8859_1_A1), M(ISO_8859_1_A2), M(ISO_8859_1_A3), | |||||
| M(ISO_8859_1_A4), M(ISO_8859_1_A5), M(ISO_8859_1_A6), M(ISO_8859_1_A7), | |||||
| M(ISO_8859_1_A8), M(ISO_8859_1_A9), M(ISO_8859_1_AA), M(ISO_8859_1_AB), | |||||
| M(ISO_8859_1_AC), M(ISO_8859_1_AD), M(ISO_8859_1_AE), M(ISO_8859_1_AF), | |||||
| M(ISO_8859_1_B0), M(ISO_8859_1_B1), M(ISO_8859_1_B2), M(ISO_8859_1_B3), | |||||
| M(ISO_8859_1_B4), M(ISO_8859_1_B5), M(ISO_8859_1_B6), M(ISO_8859_1_B7), | |||||
| M(ISO_8859_1_B8), M(ISO_8859_1_B9), M(ISO_8859_1_BA), M(ISO_8859_1_BB), | |||||
| M(ISO_8859_1_BC), M(ISO_8859_1_BD), M(ISO_8859_1_BE), M(ISO_8859_1_BF), | |||||
| M(ISO_8859_1_C0), M(ISO_8859_1_C1), M(ISO_8859_1_C2), M(ISO_8859_1_C3), | |||||
| M(ISO_8859_1_C4), M(ISO_8859_1_C5), M(ISO_8859_1_C6), M(ISO_8859_1_C7), | |||||
| M(ISO_8859_1_C8), M(ISO_8859_1_C9), M(ISO_8859_1_CA), M(ISO_8859_1_CB), | |||||
| M(ISO_8859_1_CC), M(ISO_8859_1_CD), M(ISO_8859_1_CE), M(ISO_8859_1_CF), | |||||
| M(ISO_8859_1_D0), M(ISO_8859_1_D1), M(ISO_8859_1_D2), M(ISO_8859_1_D3), | |||||
| M(ISO_8859_1_D4), M(ISO_8859_1_D5), M(ISO_8859_1_D6), M(ISO_8859_1_D7), | |||||
| M(ISO_8859_1_D8), M(ISO_8859_1_D9), M(ISO_8859_1_DA), M(ISO_8859_1_DB), | |||||
| M(ISO_8859_1_DC), M(ISO_8859_1_DD), M(ISO_8859_1_DE), M(ISO_8859_1_DF), | |||||
| M(ISO_8859_1_E0), M(ISO_8859_1_E1), M(ISO_8859_1_E2), M(ISO_8859_1_E3), | |||||
| M(ISO_8859_1_E4), M(ISO_8859_1_E5), M(ISO_8859_1_E6), M(ISO_8859_1_E7), | |||||
| M(ISO_8859_1_E8), M(ISO_8859_1_E9), M(ISO_8859_1_EA), M(ISO_8859_1_EB), | |||||
| M(ISO_8859_1_EC), M(ISO_8859_1_ED), M(ISO_8859_1_EE), M(ISO_8859_1_EF), | |||||
| M(ISO_8859_1_F0), M(ISO_8859_1_F1), M(ISO_8859_1_F2), M(ISO_8859_1_F3), | |||||
| M(ISO_8859_1_F4), M(ISO_8859_1_F5), M(ISO_8859_1_F6), M(ISO_8859_1_F7), | |||||
| M(ISO_8859_1_F8), M(ISO_8859_1_F9), M(ISO_8859_1_FA), M(ISO_8859_1_FB), | |||||
| M(ISO_8859_1_FC), M(ISO_8859_1_FD), M(ISO_8859_1_FE), M(ISO_8859_1_FF) | |||||
| }; | |||||
| #endif // ISO_8859_1_A0 | |||||
| #include <WProgram.h> | |||||
| //int main(void) __attribute__((noreturn)); | |||||
| int main(void) | |||||
| { | |||||
| _init_Teensyduino_internal_(); | |||||
| setup(); | |||||
| while (1) { | |||||
| loop(); | |||||
| } | |||||
| } | |||||
| // the main function is now built into core.a and linked into the final executable |
| /* Copyright (c) 2002, 2004, 2010 Joerg Wunsch | |||||
| Copyright (c) 2010 Gerben van den Broeke | |||||
| All rights reserved. | |||||
| malloc, free, realloc from avr-libc 1.7.0 | |||||
| with minor modifications, by Paul Stoffregen | |||||
| Redistribution and use in source and binary forms, with or without | |||||
| modification, are permitted provided that the following conditions are met: | |||||
| * Redistributions of source code must retain the above copyright | |||||
| notice, this list of conditions and the following disclaimer. | |||||
| * 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. | |||||
| * Neither the name of the copyright holders nor the names of | |||||
| contributors may be used to endorse or promote products derived | |||||
| from this software without specific prior written permission. | |||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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. | |||||
| */ | |||||
| #include <stdlib.h> | |||||
| #include <inttypes.h> | |||||
| #include <string.h> | |||||
| #include <avr/io.h> | |||||
| extern char __heap_start; | |||||
| extern char __heap_end; | |||||
| #define STACK_POINTER() ((char *)AVR_STACK_POINTER_REG) | |||||
| struct __freelist { | |||||
| size_t sz; | |||||
| struct __freelist *nx; | |||||
| }; | |||||
| /* | |||||
| * Exported interface: | |||||
| * | |||||
| * When extending the data segment, the allocator will not try to go | |||||
| * beyond the current stack limit, decreased by __malloc_margin bytes. | |||||
| * Thus, all possible stack frames of interrupt routines that could | |||||
| * interrupt the current function, plus all further nested function | |||||
| * calls must not require more stack space, or they'll risk to collide | |||||
| * with the data segment. | |||||
| */ | |||||
| size_t __malloc_margin = 128; | |||||
| char *__malloc_heap_start = &__heap_start; | |||||
| char *__malloc_heap_end = &__heap_end; | |||||
| char *__brkval = NULL; // first location not yet allocated | |||||
| struct __freelist *__flp; // freelist pointer (head of freelist) | |||||
| // this is useful for tracking the worst case memory allocation | |||||
| //char *__brkval_maximum = 0; | |||||
| void * | |||||
| malloc(size_t len) | |||||
| { | |||||
| struct __freelist *fp1, *fp2, *sfp1=NULL, *sfp2=NULL; | |||||
| char *cp; | |||||
| size_t s, avail; | |||||
| /* | |||||
| * Our minimum chunk size is the size of a pointer (plus the | |||||
| * size of the "sz" field, but we don't need to account for | |||||
| * this), otherwise we could not possibly fit a freelist entry | |||||
| * into the chunk later. | |||||
| */ | |||||
| if (len < sizeof(struct __freelist) - sizeof(size_t)) | |||||
| len = sizeof(struct __freelist) - sizeof(size_t); | |||||
| /* | |||||
| * First, walk the free list and try finding a chunk that | |||||
| * would match exactly. If we found one, we are done. While | |||||
| * walking, note down the smallest chunk we found that would | |||||
| * still fit the request -- we need it for step 2. | |||||
| * | |||||
| */ | |||||
| for (s = 0, fp1 = __flp, fp2 = 0; | |||||
| fp1; | |||||
| fp2 = fp1, fp1 = fp1->nx) { | |||||
| if (fp1->sz < len) | |||||
| continue; | |||||
| if (fp1->sz == len) { | |||||
| /* | |||||
| * Found it. Disconnect the chunk from the | |||||
| * freelist, and return it. | |||||
| */ | |||||
| if (fp2) | |||||
| fp2->nx = fp1->nx; | |||||
| else | |||||
| __flp = fp1->nx; | |||||
| return &(fp1->nx); | |||||
| } | |||||
| else { | |||||
| if (s == 0 || fp1->sz < s) { | |||||
| /* this is the smallest chunk found so far */ | |||||
| s = fp1->sz; | |||||
| sfp1 = fp1; | |||||
| sfp2 = fp2; | |||||
| } | |||||
| } | |||||
| } | |||||
| /* | |||||
| * Step 2: If we found a chunk on the freelist that would fit | |||||
| * (but was too large), look it up again and use it, since it | |||||
| * is our closest match now. Since the freelist entry needs | |||||
| * to be split into two entries then, watch out that the | |||||
| * difference between the requested size and the size of the | |||||
| * chunk found is large enough for another freelist entry; if | |||||
| * not, just enlarge the request size to what we have found, | |||||
| * and use the entire chunk. | |||||
| */ | |||||
| if (s) { | |||||
| if (s - len < sizeof(struct __freelist)) { | |||||
| /* Disconnect it from freelist and return it. */ | |||||
| if (sfp2) | |||||
| sfp2->nx = sfp1->nx; | |||||
| else | |||||
| __flp = sfp1->nx; | |||||
| return &(sfp1->nx); | |||||
| } | |||||
| /* | |||||
| * Split them up. Note that we leave the first part | |||||
| * as the new (smaller) freelist entry, and return the | |||||
| * upper portion to the caller. This saves us the | |||||
| * work to fix up the freelist chain; we just need to | |||||
| * fixup the size of the current entry, and note down | |||||
| * the size of the new chunk before returning it to | |||||
| * the caller. | |||||
| */ | |||||
| cp = (char *)sfp1; | |||||
| s -= len; | |||||
| cp += s; | |||||
| sfp2 = (struct __freelist *)cp; | |||||
| sfp2->sz = len; | |||||
| sfp1->sz = s - sizeof(size_t); | |||||
| return &(sfp2->nx); | |||||
| } | |||||
| /* | |||||
| * Step 3: If the request could not be satisfied from a | |||||
| * freelist entry, just prepare a new chunk. This means we | |||||
| * need to obtain more memory first. The largest address just | |||||
| * not allocated so far is remembered in the brkval variable. | |||||
| * Under Unix, the "break value" was the end of the data | |||||
| * segment as dynamically requested from the operating system. | |||||
| * Since we don't have an operating system, just make sure | |||||
| * that we don't collide with the stack. | |||||
| */ | |||||
| if (__brkval == 0) | |||||
| __brkval = __malloc_heap_start; | |||||
| cp = __malloc_heap_end; | |||||
| if (cp == 0) | |||||
| cp = STACK_POINTER() - __malloc_margin; | |||||
| if (cp <= __brkval) | |||||
| /* | |||||
| * Memory exhausted. | |||||
| */ | |||||
| return 0; | |||||
| avail = cp - __brkval; | |||||
| /* | |||||
| * Both tests below are needed to catch the case len >= 0xfffe. | |||||
| */ | |||||
| if (avail >= len && avail >= len + sizeof(size_t)) { | |||||
| fp1 = (struct __freelist *)__brkval; | |||||
| __brkval += len + sizeof(size_t); | |||||
| //__brkval_maximum = __brkval; | |||||
| fp1->sz = len; | |||||
| return &(fp1->nx); | |||||
| } | |||||
| /* | |||||
| * Step 4: There's no help, just fail. :-/ | |||||
| */ | |||||
| return 0; | |||||
| } | |||||
| void | |||||
| free(void *p) | |||||
| { | |||||
| struct __freelist *fp1, *fp2, *fpnew; | |||||
| char *cp1, *cp2, *cpnew; | |||||
| /* ISO C says free(NULL) must be a no-op */ | |||||
| if (p == 0) | |||||
| return; | |||||
| cpnew = p; | |||||
| cpnew -= sizeof(size_t); | |||||
| fpnew = (struct __freelist *)cpnew; | |||||
| fpnew->nx = 0; | |||||
| /* | |||||
| * Trivial case first: if there's no freelist yet, our entry | |||||
| * will be the only one on it. If this is the last entry, we | |||||
| * can reduce __brkval instead. | |||||
| */ | |||||
| if (__flp == 0) { | |||||
| if ((char *)p + fpnew->sz == __brkval) | |||||
| __brkval = cpnew; | |||||
| else | |||||
| __flp = fpnew; | |||||
| return; | |||||
| } | |||||
| /* | |||||
| * Now, find the position where our new entry belongs onto the | |||||
| * freelist. Try to aggregate the chunk with adjacent chunks | |||||
| * if possible. | |||||
| */ | |||||
| for (fp1 = __flp, fp2 = 0; | |||||
| fp1; | |||||
| fp2 = fp1, fp1 = fp1->nx) { | |||||
| if (fp1 < fpnew) | |||||
| continue; | |||||
| cp1 = (char *)fp1; | |||||
| fpnew->nx = fp1; | |||||
| if ((char *)&(fpnew->nx) + fpnew->sz == cp1) { | |||||
| /* upper chunk adjacent, assimilate it */ | |||||
| fpnew->sz += fp1->sz + sizeof(size_t); | |||||
| fpnew->nx = fp1->nx; | |||||
| } | |||||
| if (fp2 == 0) { | |||||
| /* new head of freelist */ | |||||
| __flp = fpnew; | |||||
| return; | |||||
| } | |||||
| break; | |||||
| } | |||||
| /* | |||||
| * Note that we get here either if we hit the "break" above, | |||||
| * or if we fell off the end of the loop. The latter means | |||||
| * we've got a new topmost chunk. Either way, try aggregating | |||||
| * with the lower chunk if possible. | |||||
| */ | |||||
| fp2->nx = fpnew; | |||||
| cp2 = (char *)&(fp2->nx); | |||||
| if (cp2 + fp2->sz == cpnew) { | |||||
| /* lower junk adjacent, merge */ | |||||
| fp2->sz += fpnew->sz + sizeof(size_t); | |||||
| fp2->nx = fpnew->nx; | |||||
| } | |||||
| /* | |||||
| * If there's a new topmost chunk, lower __brkval instead. | |||||
| */ | |||||
| for (fp1 = __flp, fp2 = 0; | |||||
| fp1->nx != 0; | |||||
| fp2 = fp1, fp1 = fp1->nx) | |||||
| /* advance to entry just before end of list */; | |||||
| cp2 = (char *)&(fp1->nx); | |||||
| if (cp2 + fp1->sz == __brkval) { | |||||
| if (fp2 == NULL) | |||||
| /* Freelist is empty now. */ | |||||
| __flp = NULL; | |||||
| else | |||||
| fp2->nx = NULL; | |||||
| __brkval = cp2 - sizeof(size_t); | |||||
| } | |||||
| } | |||||
| void * | |||||
| realloc(void *ptr, size_t len) | |||||
| { | |||||
| struct __freelist *fp1, *fp2, *fp3, *ofp3; | |||||
| char *cp, *cp1; | |||||
| void *memp; | |||||
| size_t s, incr; | |||||
| /* Trivial case, required by C standard. */ | |||||
| if (ptr == 0) | |||||
| return malloc(len); | |||||
| cp1 = (char *)ptr; | |||||
| cp1 -= sizeof(size_t); | |||||
| fp1 = (struct __freelist *)cp1; | |||||
| cp = (char *)ptr + len; /* new next pointer */ | |||||
| if (cp < cp1) | |||||
| /* Pointer wrapped across top of RAM, fail. */ | |||||
| return 0; | |||||
| /* | |||||
| * See whether we are growing or shrinking. When shrinking, | |||||
| * we split off a chunk for the released portion, and call | |||||
| * free() on it. Therefore, we can only shrink if the new | |||||
| * size is at least sizeof(struct __freelist) smaller than the | |||||
| * previous size. | |||||
| */ | |||||
| if (len <= fp1->sz) { | |||||
| /* The first test catches a possible unsigned int | |||||
| * rollover condition. */ | |||||
| if (fp1->sz <= sizeof(struct __freelist) || | |||||
| len > fp1->sz - sizeof(struct __freelist)) | |||||
| return ptr; | |||||
| fp2 = (struct __freelist *)cp; | |||||
| fp2->sz = fp1->sz - len - sizeof(size_t); | |||||
| fp1->sz = len; | |||||
| free(&(fp2->nx)); | |||||
| return ptr; | |||||
| } | |||||
| /* | |||||
| * If we get here, we are growing. First, see whether there | |||||
| * is space in the free list on top of our current chunk. | |||||
| */ | |||||
| incr = len - fp1->sz; | |||||
| cp = (char *)ptr + fp1->sz; | |||||
| fp2 = (struct __freelist *)cp; | |||||
| for (s = 0, ofp3 = 0, fp3 = __flp; | |||||
| fp3; | |||||
| ofp3 = fp3, fp3 = fp3->nx) { | |||||
| if (fp3 == fp2 && fp3->sz + sizeof(size_t) >= incr) { | |||||
| /* found something that fits */ | |||||
| if (fp3->sz + sizeof(size_t) - incr > sizeof(struct __freelist)) { | |||||
| /* split off a new freelist entry */ | |||||
| cp = (char *)ptr + len; | |||||
| fp2 = (struct __freelist *)cp; | |||||
| fp2->nx = fp3->nx; | |||||
| fp2->sz = fp3->sz - incr; | |||||
| fp1->sz = len; | |||||
| } else { | |||||
| /* it just fits, so use it entirely */ | |||||
| fp1->sz += fp3->sz + sizeof(size_t); | |||||
| fp2 = fp3->nx; | |||||
| } | |||||
| if (ofp3) | |||||
| ofp3->nx = fp2; | |||||
| else | |||||
| __flp = fp2; | |||||
| return ptr; | |||||
| } | |||||
| /* | |||||
| * Find the largest chunk on the freelist while | |||||
| * walking it. | |||||
| */ | |||||
| if (fp3->sz > s) | |||||
| s = fp3->sz; | |||||
| } | |||||
| /* | |||||
| * If we are the topmost chunk in memory, and there was no | |||||
| * large enough chunk on the freelist that could be re-used | |||||
| * (by a call to malloc() below), quickly extend the | |||||
| * allocation area if possible, without need to copy the old | |||||
| * data. | |||||
| */ | |||||
| if (__brkval == (char *)ptr + fp1->sz && len > s) { | |||||
| cp = (char *)ptr + len; | |||||
| cp1 = STACK_POINTER() - __malloc_margin; | |||||
| if (cp < cp1) { | |||||
| __brkval = cp; | |||||
| //__brkval_maximum = cp; | |||||
| fp1->sz = len; | |||||
| return ptr; | |||||
| } | |||||
| /* If that failed, we are out of luck. */ | |||||
| return 0; | |||||
| } | |||||
| /* | |||||
| * Call malloc() for a new chunk, then copy over the data, and | |||||
| * release the old region. | |||||
| */ | |||||
| if ((memp = malloc(len)) == 0) | |||||
| return 0; | |||||
| memcpy(memp, ptr, fp1->sz); | |||||
| free(ptr); | |||||
| return memp; | |||||
| } | |||||
| #include "new.h" | |||||
| void * operator new(size_t size) | |||||
| { | |||||
| return malloc(size); | |||||
| } | |||||
| void * operator new[](size_t size) | |||||
| { | |||||
| return malloc(size); | |||||
| } | |||||
| void operator delete(void * ptr) | |||||
| { | |||||
| free(ptr); | |||||
| } | |||||
| void operator delete[](void * ptr) | |||||
| { | |||||
| 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 *) {}; | |||||
| void __cxa_pure_virtual(void) {}; | |||||
| /* 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 | |||||
| */ | |||||
| #ifndef NEW_H | |||||
| #define NEW_H | |||||
| #ifdef __cplusplus | |||||
| #include <stdlib.h> | |||||
| void * operator new(size_t size); | |||||
| void * operator new[](size_t size); | |||||
| void operator delete(void * ptr); | |||||
| void operator delete[](void * ptr); | |||||
| __extension__ typedef int __guard __attribute__((mode (__DI__))); | |||||
| extern "C" int __cxa_guard_acquire(__guard *); | |||||
| extern "C" void __cxa_guard_release (__guard *); | |||||
| extern "C" void __cxa_guard_abort (__guard *); | |||||
| extern "C" void __cxa_pure_virtual(void); | |||||
| #endif // __cplusplus | |||||
| #endif |
| // For compatibility with some ESP8266 programs | |||||
| #include <avr/pgmspace.h> |
| #ifndef pins_macros_for_arduino_compatibility_h | |||||
| #define pins_macros_for_arduino_compatibility_h | |||||
| #include <avr/pgmspace.h> | |||||
| #include "core_pins.h" | |||||
| #if defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) | |||||
| const static uint8_t A0 = CORE_ANALOG0_PIN; | |||||
| const static uint8_t A1 = CORE_ANALOG1_PIN; | |||||
| const static uint8_t A2 = CORE_ANALOG2_PIN; | |||||
| const static uint8_t A3 = CORE_ANALOG3_PIN; | |||||
| const static uint8_t A4 = CORE_ANALOG4_PIN; | |||||
| const static uint8_t A5 = CORE_ANALOG5_PIN; | |||||
| const static uint8_t A6 = CORE_ANALOG6_PIN; | |||||
| const static uint8_t A7 = CORE_ANALOG7_PIN; | |||||
| #if defined(__AVR_ATmega32U4__) | |||||
| const static uint8_t A8 = CORE_ANALOG8_PIN; | |||||
| const static uint8_t A9 = CORE_ANALOG9_PIN; | |||||
| const static uint8_t A10 = 10; | |||||
| const static uint8_t A11 = CORE_ANALOG11_PIN; | |||||
| #endif | |||||
| #endif | |||||
| const static uint8_t SS = CORE_SS0_PIN; | |||||
| const static uint8_t MOSI = CORE_MOSI0_PIN; | |||||
| const static uint8_t MISO = CORE_MISO0_PIN; | |||||
| const static uint8_t SCK = CORE_SCLK0_PIN; | |||||
| const static uint8_t LED_BUILTIN = CORE_LED0_PIN; | |||||
| #if defined(CORE_SDA0_PIN) | |||||
| const static uint8_t SDA = CORE_SDA0_PIN; | |||||
| #endif | |||||
| #if defined(CORE_SCL0_PIN) | |||||
| const static uint8_t SCL = CORE_SCL0_PIN; | |||||
| #endif | |||||
| #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? | |||||
| #define NOT_A_PORT 127 | |||||
| #define NOT_A_PIN 127 | |||||
| #define NOT_AN_INTERRUPT -1 | |||||
| #define digitalPinToPort(P) (P) | |||||
| #define portInputRegister(P) ((volatile uint8_t *)((int)pgm_read_byte(digital_pin_table_PGM+(P)*2+1))) | |||||
| #define portModeRegister(P) (portInputRegister(P) + 1) | |||||
| #define portOutputRegister(P) (portInputRegister(P) + 2) | |||||
| #define digitalPinToBitMask(P) (pgm_read_byte(digital_pin_table_PGM+(P)*2)) | |||||
| extern const uint8_t PROGMEM digital_pin_table_PGM[]; | |||||
| #if defined(__AVR_AT90USB162__) | |||||
| #define analogInputToDigitalPin(ch) (-1) | |||||
| #define digitalPinHasPWM(p) ((p) == 0 || (p) == 15 || (p) == 17 || (p) == 18) | |||||
| #define digitalPinToInterrupt(p) (((p) <= 3 || (p) == 6 || (p) == 8) ? (p) : ((p) == 4 ? 5 : ((p) == 16 ? 4 : -1))) | |||||
| #elif defined(__AVR_ATmega32U4__) | |||||
| #define analogInputToDigitalPin(ch) ((ch) <= 10 ? 21 - (ch) : ((ch) == 11 ? 22 : -1)) | |||||
| #define digitalPinHasPWM(p) ((p) == 4 || (p) == 5 || (p) == 9 || (p) == 10 || (p) == 12 || (p) == 14 || (p) == 15) | |||||
| #define digitalPinToInterrupt(p) (((p) >= 5 && (p) <= 8) ? (p) - 5 : -1) | |||||
| #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) | |||||
| #define analogInputToDigitalPin(ch) ((ch) <= 7 ? (ch) + 38 : -1) | |||||
| #define digitalPinHasPWM(p) (((p) >= 14 && (p) <= 16) || ((p) >= 24 && (p) <= 27) || (p) == 0 || (p) == 1) | |||||
| #define digitalPinToInterrupt(p) ((p) <= 3 ? (p) : (((p) == 36 || (p) == 37) ? (p) - 32 : (((p) == 18 || (p) == 19) ? (p) - 12 : -1))) | |||||
| #endif | |||||
| #if defined(__AVR_AT90USB162__) | |||||
| #define digitalPinToPortReg(p) (((p) <= 7) ? &PORTD : (((p) <= 15) ? &PORTB : &PORTC)) | |||||
| #define digitalPinToBit(p) \ | |||||
| (((p) <= 7) ? (p) : (((p) <= 15) ? (p) - 8 : (((p) <= 19) ? 23 - (p) : 2))) | |||||
| #define digitalPinToPCICR(p) \ | |||||
| ((((p) >= 8 && (p) <= 15) || ((p) >= 17 && (p) <= 20) || (p) == 5) ? &PCICR : NULL) | |||||
| #define digitalPinToPCICRbit(p) (((p) >= 8 && (p) <= 15) ? 0 : 1) | |||||
| #define digitalPinToPCIFR(p) \ | |||||
| ((((p) >= 8 && (p) <= 15) || ((p) >= 17 && (p) <= 20) || (p) == 5) ? &PCIFR : NULL) | |||||
| #define digitalPinToPCIFRbit(p) (((p) >= 8 && (p) <= 15) ? 0 : 1) | |||||
| #define digitalPinToPCMSK(p) \ | |||||
| (((p) >= 8 && (p) <= 15) ? &PCMSK0 : ((((p) >= 17 && (p) <= 20) || (p) == 5) ? &PCMSK1 : NULL)) | |||||
| #define digitalPinToPCMSKbit(p) \ | |||||
| (((p) >= 8 && (p) <= 15) ? (p) - 8 : (((p) >= 17 && (p) <= 20) ? (p) - 17 : 4)) | |||||
| #elif defined(__AVR_ATmega32U4__) | |||||
| #define digitalPinToPortReg(p) \ | |||||
| (((p) <= 4) ? &PORTB : (((p) <= 8) ? &PORTD : (((p) <= 10) ? &PORTC : (((p) <= 12) ? &PORTD : \ | |||||
| (((p) <= 15) ? &PORTB : (((p) <= 21) ? &PORTF : (((p) <= 23) ? &PORTD : &PORTE))))))) | |||||
| #define digitalPinToBit(p) \ | |||||
| (((p) <= 3) ? (p) : (((p) == 4) ? 7 : (((p) <= 8) ? (p) - 5 : (((p) <= 10) ? (p) - 3 : \ | |||||
| (((p) <= 12) ? (p) - 5 : (((p) <= 15) ? (p) - 9 : (((p) <= 19) ? 23 - (p) : \ | |||||
| (((p) <= 21) ? 21 - (p) : (((p) <= 23) ? (p) - 18 : 6))))))))) | |||||
| #define digitalPinToPCICR(p) ((((p) >= 0 && (p) <= 4) || ((p) >= 13 && (p) <= 15)) ? &PCICR : NULL) | |||||
| #define digitalPinToPCICRbit(p) (0) | |||||
| #define digitalPinToPCIFR(p) ((((p) >= 0 && (p) <= 4) || ((p) >= 13 && (p) <= 15)) ? &PCIFR : NULL) | |||||
| #define digitalPinToPCIFRbit(p) (0) | |||||
| #define digitalPinToPCMSK(p) ((((p) >= 0 && (p) <= 4) || ((p) >= 13 && (p) <= 15)) ? &PCMSK0 : NULL) | |||||
| #define digitalPinToPCMSKbit(p) \ | |||||
| (((p) >= 0 && (p) <= 3) ? (p) : (((p) >= 13 && (p) <= 15) ? (p) - 9 : 7)) | |||||
| #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) | |||||
| #define digitalPinToPortReg(p) \ | |||||
| (((p) >= 0 && (p) <= 7) ? &PORTD : (((p) >= 10 && (p) <= 17) ? &PORTC : \ | |||||
| (((p) >= 20 && (p) <= 27) ? &PORTB : (((p) >= 28 && (p) <= 35) ? &PORTA : \ | |||||
| (((p) >= 38 && (p) <= 45) ? &PORTF : &PORTE))))) | |||||
| #define digitalPinToBit(p) \ | |||||
| (((p) <= 7) ? (p) : (((p) <= 9) ? (p) - 8 : (((p) <= 17) ? (p) - 10 : \ | |||||
| (((p) <= 19) ? (p) - 12 : (((p) <= 27) ? (p) - 20 : (((p) <= 35) ? (p) - 28 : \ | |||||
| (((p) <= 37) ? (p) - 32 : (((p) <= 45) ? (p) - 38 : 2)))))))) | |||||
| #define digitalPinToPCICR(p) (((p) >= 20 && (p) <= 27) ? &PCICR : NULL) | |||||
| #define digitalPinToPCICRbit(p) (0) | |||||
| #define digitalPinToPCIFR(p) (((p) >= 20 && (p) <= 27) ? &PCIFR : NULL) | |||||
| #define digitalPinToPCIFRbit(p) (0) | |||||
| #define digitalPinToPCMSK(p) (((p) >= 20 && (p) <= 27) ? &PCMSK0 : NULL) | |||||
| #define digitalPinToPCMSKbit(p) (((p) - 20) & 7) | |||||
| #endif | |||||
| #define NOT_ON_TIMER 0 | |||||
| static inline uint8_t digitalPinToTimer(uint8_t) __attribute__((always_inline, unused)); | |||||
| static inline uint8_t digitalPinToTimer(uint8_t pin) | |||||
| { | |||||
| switch (pin) { | |||||
| #ifdef CORE_PWM0_PIN | |||||
| case CORE_PWM0_PIN: return 1; | |||||
| #endif | |||||
| #ifdef CORE_PWM1_PIN | |||||
| case CORE_PWM1_PIN: return 2; | |||||
| #endif | |||||
| #ifdef CORE_PWM2_PIN | |||||
| case CORE_PWM2_PIN: return 3; | |||||
| #endif | |||||
| #ifdef CORE_PWM3_PIN | |||||
| case CORE_PWM3_PIN: return 4; | |||||
| #endif | |||||
| #ifdef CORE_PWM4_PIN | |||||
| case CORE_PWM4_PIN: return 5; | |||||
| #endif | |||||
| #ifdef CORE_PWM5_PIN | |||||
| case CORE_PWM5_PIN: return 6; | |||||
| #endif | |||||
| #ifdef CORE_PWM6_PIN | |||||
| case CORE_PWM6_PIN: return 7; | |||||
| #endif | |||||
| #ifdef CORE_PWM7_PIN | |||||
| case CORE_PWM7_PIN: return 8; | |||||
| #endif | |||||
| #ifdef CORE_PWM8_PIN | |||||
| case CORE_PWM8_PIN: return 9; | |||||
| #endif | |||||
| default: return NOT_ON_TIMER; | |||||
| } | |||||
| } | |||||
| #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 |
| #if defined(USB_SERIAL) | |||||
| #include "../usb_serial/usb.c" | |||||
| #elif defined(USB_HID) | |||||
| #include "../usb_hid/usb.c" | |||||
| #elif defined(USB_SERIAL_HID) | |||||
| #include "../usb_serial_hid/usb.c" | |||||
| #elif defined(USB_DISK) || defined(USB_DISK_SDFLASH) | |||||
| #include "../usb_disk/usb.c" | |||||
| #elif defined(USB_MIDI) | |||||
| #include "../usb_midi/usb.c" | |||||
| #elif defined(USB_RAWHID) | |||||
| #include "../usb_rawhid/usb.c" | |||||
| #elif defined(USB_FLIGHTSIM) | |||||
| #include "../usb_flightsim/usb.c" | |||||
| #endif |
| #if defined(USB_SERIAL) | |||||
| #include "../usb_serial/usb_api.cpp" | |||||
| #elif defined(USB_HID) | |||||
| #include "../usb_hid/usb_api.cpp" | |||||
| #elif defined(USB_SERIAL_HID) | |||||
| #include "../usb_serial_hid/usb_api.cpp" | |||||
| #elif defined(USB_DISK) || defined(USB_DISK_SDFLASH) | |||||
| #include "../usb_disk/usb_api.cpp" | |||||
| #elif defined(USB_MIDI) | |||||
| #include "../usb_midi/usb_api.cpp" | |||||
| #elif defined(USB_RAWHID) | |||||
| #include "../usb_rawhid/usb_api.cpp" | |||||
| #elif defined(USB_FLIGHTSIM) | |||||
| #include "../usb_flightsim/usb_api.cpp" | |||||
| #endif |
| #if defined(USB_SERIAL) | |||||
| #include "../usb_serial/usb_api.h" | |||||
| #elif defined(USB_HID) | |||||
| #include "../usb_hid/usb_api.h" | |||||
| #elif defined(USB_SERIAL_HID) | |||||
| #include "../usb_serial_hid/usb_api.h" | |||||
| #elif defined(USB_DISK) || defined(USB_DISK_SDFLASH) | |||||
| #include "../usb_disk/usb_api.h" | |||||
| #elif defined(USB_MIDI) | |||||
| #include "../usb_midi/usb_api.h" | |||||
| #elif defined(USB_RAWHID) | |||||
| #include "../usb_rawhid/usb_api.h" | |||||
| #elif defined(USB_FLIGHTSIM) | |||||
| #include "../usb_flightsim/usb_api.h" | |||||
| #endif |
| #ifndef usb_common_h__ | |||||
| #define usb_common_h__ | |||||
| #include <stdint.h> | |||||
| #include <avr/io.h> | |||||
| #include <avr/pgmspace.h> | |||||
| #include <avr/interrupt.h> | |||||
| #ifdef __cplusplus | |||||
| extern "C"{ | |||||
| #endif | |||||
| #define MAX_ENDPOINT 6 | |||||
| #define LSB(n) (n & 255) | |||||
| #define MSB(n) ((n >> 8) & 255) | |||||
| // constants corresponding to the various serial parameters | |||||
| #define USB_SERIAL_DTR 0x01 | |||||
| #define USB_SERIAL_RTS 0x02 | |||||
| #define USB_SERIAL_1_STOP 0 | |||||
| #define USB_SERIAL_1_5_STOP 1 | |||||
| #define USB_SERIAL_2_STOP 2 | |||||
| #define USB_SERIAL_PARITY_NONE 0 | |||||
| #define USB_SERIAL_PARITY_ODD 1 | |||||
| #define USB_SERIAL_PARITY_EVEN 2 | |||||
| #define USB_SERIAL_PARITY_MARK 3 | |||||
| #define USB_SERIAL_PARITY_SPACE 4 | |||||
| #define USB_SERIAL_DCD 0x01 | |||||
| #define USB_SERIAL_DSR 0x02 | |||||
| #define USB_SERIAL_BREAK 0x04 | |||||
| #define USB_SERIAL_RI 0x08 | |||||
| #define USB_SERIAL_FRAME_ERR 0x10 | |||||
| #define USB_SERIAL_PARITY_ERR 0x20 | |||||
| #define USB_SERIAL_OVERRUN_ERR 0x40 | |||||
| #define EP_TYPE_CONTROL 0x00 | |||||
| #define EP_TYPE_BULK_IN 0x81 | |||||
| #define EP_TYPE_BULK_OUT 0x80 | |||||
| #define EP_TYPE_INTERRUPT_IN 0xC1 | |||||
| #define EP_TYPE_INTERRUPT_OUT 0xC0 | |||||
| #define EP_TYPE_ISOCHRONOUS_IN 0x41 | |||||
| #define EP_TYPE_ISOCHRONOUS_OUT 0x40 | |||||
| #define EP_SINGLE_BUFFER 0x02 | |||||
| #define EP_DOUBLE_BUFFER 0x06 | |||||
| #define EP_SIZE(s) ((s) == 64 ? 0x30 : \ | |||||
| ((s) == 32 ? 0x20 : \ | |||||
| ((s) == 16 ? 0x10 : \ | |||||
| 0x00))) | |||||
| #if defined(__AVR_AT90USB162__) | |||||
| #define HW_CONFIG() | |||||
| #define PLL_CONFIG() (PLLCSR = ((1<<PLLE)|(1<<PLLP0))) | |||||
| #define USB_CONFIG() (USBCON = (1<<USBE)) | |||||
| #define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) | |||||
| #elif defined(__AVR_ATmega32U4__) | |||||
| #define HW_CONFIG() (UHWCON = 0x01) | |||||
| #define PLL_CONFIG() (PLLCSR = 0x12) | |||||
| #define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE))) | |||||
| #define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) | |||||
| #elif defined(__AVR_AT90USB646__) | |||||
| #define HW_CONFIG() (UHWCON = 0x81) | |||||
| #define PLL_CONFIG() (PLLCSR = 0x1A) | |||||
| #define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE))) | |||||
| #define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) | |||||
| #elif defined(__AVR_AT90USB1286__) | |||||
| #define HW_CONFIG() (UHWCON = 0x81) | |||||
| #define PLL_CONFIG() (PLLCSR = 0x16) | |||||
| #define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE))) | |||||
| #define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) | |||||
| #endif | |||||
| // standard control endpoint request types | |||||
| #define GET_STATUS 0 | |||||
| #define CLEAR_FEATURE 1 | |||||
| #define SET_FEATURE 3 | |||||
| #define SET_ADDRESS 5 | |||||
| #define GET_DESCRIPTOR 6 | |||||
| #define GET_CONFIGURATION 8 | |||||
| #define SET_CONFIGURATION 9 | |||||
| #define GET_INTERFACE 10 | |||||
| #define SET_INTERFACE 11 | |||||
| // CDC (communication class device) | |||||
| #define CDC_SET_LINE_CODING 0x20 | |||||
| #define CDC_GET_LINE_CODING 0x21 | |||||
| #define CDC_SET_CONTROL_LINE_STATE 0x22 | |||||
| #define CDC_SEND_BREAK 0x23 | |||||
| // HID (human interface device) | |||||
| #define HID_GET_REPORT 1 | |||||
| #define HID_GET_IDLE 2 | |||||
| #define HID_GET_PROTOCOL 3 | |||||
| #define HID_SET_REPORT 9 | |||||
| #define HID_SET_IDLE 10 | |||||
| #define HID_SET_PROTOCOL 11 | |||||
| // Mass Storage | |||||
| #define MS_BULK_ONLY_RESET 0xFF | |||||
| #define MS_GET_MAX_LUN 0xFE /* stall = 0 */ | |||||
| #define pgm_read_byte_postinc(val, addr) \ | |||||
| asm ("lpm %0, Z+\n" : "=r" (val), "+z" (addr) : ) | |||||
| #define pgm_read_word_postinc(val, addr) \ | |||||
| asm ("lpm %A0, Z+\n\tlpm %B0, Z+\n" : "=r" (val), "+z" (addr) : ) | |||||
| #define read_word_lsbfirst(val, reg) \ | |||||
| asm volatile( \ | |||||
| "lds %A0, %1\n\tlds %B0, %1\n" \ | |||||
| : "=r" (val) : "M" ((int)(®)) ) | |||||
| #define read_word_msbfirst(val, reg) \ | |||||
| asm volatile( \ | |||||
| "lds %B0, %1\n\tlds %A0, %1\n" \ | |||||
| : "=r" (val) : "M" ((int)(®)) ) | |||||
| #define read_dword_lsbfirst(val, reg) \ | |||||
| asm volatile( \ | |||||
| "lds %A0, %1\n\tlds %B0, %1\n\t" \ | |||||
| "lds %C0, %1\n\tlds %D0, %1\n" \ | |||||
| : "=r" (val) : "M" ((int)(®)) ) | |||||
| #define read_dword_msbfirst(val, reg) \ | |||||
| asm volatile( \ | |||||
| "lds %D0, %1\n\tlds %C0, %1\n\t" \ | |||||
| "lds %B0, %1\n\tlds %A0, %1\n" \ | |||||
| : "=r" (val) : "M" ((int)(®)) ) | |||||
| #define write_word_lsbfirst(val, reg) \ | |||||
| asm volatile( \ | |||||
| "sts %1, %A0\n\tsts %1, %B0\n" \ | |||||
| : : "r" (val) , "M" ((int)(®)) ) | |||||
| #define write_word_msbfirst(val, reg) \ | |||||
| asm volatile( \ | |||||
| "sts %1, %B0\n\tsts %1, %A0\n" \ | |||||
| : : "r" (val) , "M" ((int)(®)) ) | |||||
| #define write_dword_lsbfirst(val, reg) \ | |||||
| asm volatile( \ | |||||
| "sts %1, %A0\n\tsts %1, %B0\n\t" \ | |||||
| "sts %1, %C0\n\tsts %1, %D0\n" \ | |||||
| : : "r" (val) , "M" ((int)(®)) ) | |||||
| #define write_dword_msbfirst(val, reg) \ | |||||
| asm volatile( \ | |||||
| "sts %1, %D0\n\tsts %1, %C0\n\t" \ | |||||
| "sts %1, %B0\n\tsts %1, %A0\n" \ | |||||
| : : "r" (val) , "M" ((int)(®)) ) | |||||
| #define USBSTATE __attribute__ ((section (".noinit"))) | |||||
| extern void _reboot_Teensyduino_(void) __attribute__((noreturn)); | |||||
| extern void _restart_Teensyduino_(void) __attribute__((noreturn)); | |||||
| #ifdef __cplusplus | |||||
| } // extern "C" | |||||
| #endif | |||||
| #endif | |||||
| #if defined(USB_SERIAL) | |||||
| #include "../usb_serial/usb_private.h" | |||||
| #elif defined(USB_HID) | |||||
| #include "../usb_hid/usb_private.h" | |||||
| #elif defined(USB_SERIAL_HID) | |||||
| #include "../usb_serial_hid/usb_private.h" | |||||
| #elif defined(USB_DISK) || defined(USB_DISK_SDFLASH) | |||||
| #include "../usb_disk/usb_private.h" | |||||
| #elif defined(USB_MIDI) | |||||
| #include "../usb_midi/usb_private.h" | |||||
| #elif defined(USB_RAWHID) | |||||
| #include "../usb_rawhid/usb_private.h" | |||||
| #elif defined(USB_FLIGHTSIM) | |||||
| #include "../usb_flightsim/usb_private.h" | |||||
| #endif |
| /* | |||||
| wiring.c - Partial implementation of the Wiring API for the ATmega8. | |||||
| Part of Arduino - http://www.arduino.cc/ | |||||
| Copyright (c) 2005-2006 David A. Mellis | |||||
| Modified for Teensyduino by Paul Stoffregen, paul@pjrc.com | |||||
| http://www.pjrc.com/teensy/teensyduino.html | |||||
| 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 "wiring_private.h" | |||||
| #include "pins_arduino.h" | |||||
| #include "core_pins.h" | |||||
| #define PULSEIN_CYCLES_PER_LOOP 21 | |||||
| #define PULSEIN_CYCLES_LATENCY 11 | |||||
| /* Measures the length (in microseconds) of a pulse on the pin; state is HIGH | |||||
| * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds | |||||
| * to 3 minutes in length, but must be called at least a few dozen microseconds | |||||
| * before the start of the pulse. */ | |||||
| unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) | |||||
| { | |||||
| // cache the port and bit of the pin in order to speed up the | |||||
| // pulse width measuring loop and achieve finer resolution. calling | |||||
| // digitalRead() instead yields much coarser resolution. | |||||
| uint8_t bit = digitalPinToBitMask(pin); | |||||
| volatile uint8_t *reg = portInputRegister(digitalPinToPort(pin)); | |||||
| uint8_t stateMask = (state ? bit : 0); | |||||
| unsigned long width = 0; // keep initialization out of time critical area | |||||
| // convert the timeout from microseconds to a number of times through | |||||
| // the initial loop | |||||
| unsigned long numloops = 0; | |||||
| //unsigned long maxloops = microsecondsToClockCycles(timeout) / PULSEIN_CYCLES_PER_LOOP; | |||||
| unsigned long maxloops = timeout * clockCyclesPerMicrosecond() / PULSEIN_CYCLES_PER_LOOP; | |||||
| // wait for any previous pulse to end | |||||
| while ((*reg & bit) == stateMask) | |||||
| if (numloops++ == maxloops) | |||||
| return 0; | |||||
| // wait for the pulse to start | |||||
| while ((*reg & bit) != stateMask) | |||||
| if (numloops++ == maxloops) | |||||
| return 0; | |||||
| // wait for the pulse to stop | |||||
| while ((*reg & bit) == stateMask) { | |||||
| width++; | |||||
| if (numloops++ == maxloops) | |||||
| return 0; | |||||
| } | |||||
| // convert the reading to microseconds. The loop has been determined | |||||
| // to be PULSEIN_CYCLES_LATENCY clock cycles long and have about | |||||
| // PULSEIN_CYCLES_PER_LOOP clocks between the edge and the start of | |||||
| // the loop. There will be some error introduced by the interrupt | |||||
| // handlers. | |||||
| //return clockCyclesToMicroseconds(PULSEIN_CYCLES_PER_LOOP * width + PULSEIN_CYCLES_LATENCY); | |||||
| return (width * PULSEIN_CYCLES_PER_LOOP + PULSEIN_CYCLES_LATENCY + (clockCyclesPerMicrosecond() / 2)) / clockCyclesPerMicrosecond(); | |||||
| } | |||||
| /* | |||||
| wiring.h - Partial implementation of the Wiring API for the ATmega8. | |||||
| Part of Arduino - http://www.arduino.cc/ | |||||
| Copyright (c) 2005-2006 David A. Mellis | |||||
| 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 | |||||
| $Id: wiring.h 387 2008-03-08 21:30:00Z mellis $ | |||||
| */ | |||||
| #ifndef Wiring_h | |||||
| #define Wiring_h | |||||
| #include <avr/io.h> | |||||
| #include <stdlib.h> | |||||
| #include <stdbool.h> | |||||
| #include <math.h> | |||||
| #include "binary.h" | |||||
| #include "core_id.h" | |||||
| #include "core_pins.h" | |||||
| #ifdef ID | |||||
| #undef ID // ID bit in USBSTA conflicts with user's code | |||||
| #endif | |||||
| #ifdef __cplusplus | |||||
| extern "C"{ | |||||
| #endif | |||||
| #define PI 3.1415926535897932384626433832795 | |||||
| #define HALF_PI 1.5707963267948966192313216916398 | |||||
| #define TWO_PI 6.283185307179586476925286766559 | |||||
| #define DEG_TO_RAD 0.017453292519943295769236907684886 | |||||
| #define RAD_TO_DEG 57.295779513082320876798154814105 | |||||
| #define SERIAL 0 | |||||
| #define DISPLAY 1 | |||||
| #define CHANGE 1 | |||||
| #define FALLING 2 | |||||
| #define RISING 3 | |||||
| #define INTERNAL 3 | |||||
| #define INTERNAL2V56 3 | |||||
| #define DEFAULT 1 | |||||
| #define EXTERNAL 0 | |||||
| // undefine stdlib's abs if encountered | |||||
| #ifdef abs | |||||
| #undef abs | |||||
| #endif | |||||
| #define min(a,b) ((a)<(b)?(a):(b)) | |||||
| #define max(a,b) ((a)>(b)?(a):(b)) | |||||
| #define abs(x) ((x)>0?(x):-(x)) | |||||
| #define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) | |||||
| #define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) | |||||
| #define radians(deg) ((deg)*DEG_TO_RAD) | |||||
| #define degrees(rad) ((rad)*RAD_TO_DEG) | |||||
| #define sq(x) ((x)*(x)) | |||||
| #define interrupts() sei() | |||||
| #define noInterrupts() cli() | |||||
| #define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) | |||||
| #define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) | |||||
| #define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() ) | |||||
| #define lowByte(w) ((uint8_t)((w) & 0xFF)) | |||||
| #define highByte(w) ((uint8_t)((w) >> 8)) | |||||
| #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))) | |||||
| typedef unsigned int word; | |||||
| #define bit(b) (1UL << (b)) | |||||
| typedef bool boolean; | |||||
| typedef uint8_t byte; | |||||
| unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout); | |||||
| void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, byte val); | |||||
| void attachInterrupt(uint8_t, void (*)(void), uint8_t mode); | |||||
| void detachInterrupt(uint8_t); | |||||
| void setup(void); | |||||
| void loop(void); | |||||
| #ifdef __cplusplus | |||||
| } // extern "C" | |||||
| #endif | |||||
| #endif |
| /* | |||||
| wiring_private.h - Internal header file. | |||||
| Part of Arduino - http://www.arduino.cc/ | |||||
| Copyright (c) 2005-2006 David A. Mellis | |||||
| 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 | |||||
| $Id: wiring.h 239 2007-01-12 17:58:39Z mellis $ | |||||
| */ | |||||
| #ifndef WiringPrivate_h | |||||
| #define WiringPrivate_h | |||||
| #include <avr/io.h> | |||||
| #include <avr/interrupt.h> | |||||
| #include <stdio.h> | |||||
| #include <stdarg.h> | |||||
| #include "wiring.h" | |||||
| #if F_CPU == 16000000L | |||||
| #define ADC_PRESCALER 0x07 | |||||
| #define CPU_PRESCALER 0x00 | |||||
| #elif F_CPU == 8000000L | |||||
| #define ADC_PRESCALER 0x06 | |||||
| #define CPU_PRESCALER 0x01 | |||||
| #elif F_CPU == 4000000L | |||||
| #define ADC_PRESCALER 0x05 | |||||
| #define CPU_PRESCALER 0x02 | |||||
| #elif F_CPU == 2000000L | |||||
| #define ADC_PRESCALER 0x04 | |||||
| #define CPU_PRESCALER 0x03 | |||||
| #elif F_CPU == 1000000L | |||||
| #define ADC_PRESCALER 0x03 | |||||
| #define CPU_PRESCALER 0x04 | |||||
| #else | |||||
| #error "Teensyduino only supports 16, 8, 4, 2, 1 MHz. Please edit boards.txt" | |||||
| #endif | |||||
| #ifdef __cplusplus | |||||
| extern "C"{ | |||||
| #endif | |||||
| #ifndef cbi | |||||
| #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) | |||||
| #endif | |||||
| #ifndef sbi | |||||
| #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) | |||||
| #endif | |||||
| typedef void (*voidFuncPtr)(void); | |||||
| #ifdef __cplusplus | |||||
| } // extern "C" | |||||
| #endif | |||||
| #endif |
| /* Teensyduino Core Library | |||||
| * http://www.pjrc.com/teensy/ | |||||
| * Copyright (c) 2014 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 "core_pins.h" | |||||
| //#include "HardwareSerial.h" | |||||
| void yield(void) __attribute__ ((weak)); | |||||
| void yield(void) | |||||
| { | |||||
| //static uint8_t running=0; | |||||
| //if (running) return; // TODO: does this need to be atomic? | |||||
| //running = 1; | |||||
| //if (Serial.available()) serialEvent(); | |||||
| //if (Serial1.available()) serialEvent1(); | |||||
| //if (Serial2.available()) serialEvent2(); | |||||
| //if (Serial3.available()) serialEvent3(); | |||||
| //running = 0; | |||||
| }; |
| // This header file is in the public domain. | |||||
| #ifndef Arduino_h | |||||
| #define Arduino_h | |||||
| #include "WProgram.h" | |||||
| #include "pins_arduino.h" | |||||
| #endif |
| /* Teensyduino Core Library | |||||
| * http://www.pjrc.com/teensy/ | |||||
| * Copyright (c) 2017 PJRC.COM, LLC. | |||||
| * | |||||
| * Permission is hereby granted, free of charge, to any person obtaining | |||||
| * a copy of this software and associated documentation files (the | |||||
| * "Software"), to deal in the Software without restriction, including | |||||
| * without limitation the rights to use, copy, modify, merge, publish, | |||||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||||
| * permit persons to whom the Software is furnished to do so, subject to | |||||
| * the following conditions: | |||||
| * | |||||
| * 1. The above copyright notice and this permission notice shall be | |||||
| * included in all copies or substantial portions of the Software. | |||||
| * | |||||
| * 2. If the Software is incorporated into a build system that allows | |||||
| * selection among a list of target devices, then similar target | |||||
| * devices manufactured by PJRC.COM must be included in the list of | |||||
| * target devices and selectable in the same manner. | |||||
| * | |||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
| * SOFTWARE. | |||||
| */ | |||||
| #include <Arduino.h> | |||||
| #include "AudioStream.h" | |||||
| #if defined(__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[NUM_MASKS]; | |||||
| uint16_t AudioStream::memory_pool_first_mask; | |||||
| uint16_t AudioStream::cpu_cycles_total = 0; | |||||
| uint16_t AudioStream::cpu_cycles_total_max = 0; | |||||
| uint16_t AudioStream::memory_used = 0; | |||||
| uint16_t AudioStream::memory_used_max = 0; | |||||
| // Set up the pool of audio data blocks | |||||
| // placing them all onto the free list | |||||
| void AudioStream::initialize_memory(audio_block_t *data, unsigned int num) | |||||
| { | |||||
| unsigned int i; | |||||
| unsigned int maxnum = MAX_AUDIO_MEMORY / AUDIO_BLOCK_SAMPLES / 2; | |||||
| //Serial.println("AudioStream initialize_memory"); | |||||
| //delay(10); | |||||
| if (num > maxnum) num = maxnum; | |||||
| __disable_irq(); | |||||
| memory_pool = data; | |||||
| memory_pool_first_mask = 0; | |||||
| for (i=0; i < NUM_MASKS; i++) { | |||||
| memory_pool_available_mask[i] = 0; | |||||
| } | |||||
| for (i=0; i < num; i++) { | |||||
| memory_pool_available_mask[i >> 5] |= (1 << (i & 0x1F)); | |||||
| } | |||||
| for (i=0; i < num; i++) { | |||||
| data[i].memory_pool_index = i; | |||||
| } | |||||
| __enable_irq(); | |||||
| } | |||||
| // Allocate 1 audio data block. If successful | |||||
| // the caller is the only owner of this new block | |||||
| audio_block_t * AudioStream::allocate(void) | |||||
| { | |||||
| uint32_t n, index, avail; | |||||
| uint32_t *p, *end; | |||||
| audio_block_t *block; | |||||
| uint32_t used; | |||||
| p = memory_pool_available_mask; | |||||
| end = p + NUM_MASKS; | |||||
| __disable_irq(); | |||||
| index = memory_pool_first_mask; | |||||
| p += index; | |||||
| while (1) { | |||||
| if (p >= end) { | |||||
| __enable_irq(); | |||||
| //Serial.println("alloc:null"); | |||||
| return NULL; | |||||
| } | |||||
| avail = *p; | |||||
| if (avail) break; | |||||
| index++; | |||||
| p++; | |||||
| } | |||||
| n = __builtin_clz(avail); | |||||
| avail &= ~(0x80000000 >> n); | |||||
| *p = avail; | |||||
| if (!avail) index++; | |||||
| memory_pool_first_mask = index; | |||||
| used = memory_used + 1; | |||||
| memory_used = used; | |||||
| __enable_irq(); | |||||
| index = p - memory_pool_available_mask; | |||||
| block = memory_pool + ((index << 5) + (31 - n)); | |||||
| block->ref_count = 1; | |||||
| if (used > memory_used_max) memory_used_max = used; | |||||
| //Serial.print("alloc:"); | |||||
| //Serial.println((uint32_t)block, HEX); | |||||
| return block; | |||||
| } | |||||
| // Release ownership of a data block. If no | |||||
| // other streams have ownership, the block is | |||||
| // returned to the free pool | |||||
| void AudioStream::release(audio_block_t *block) | |||||
| { | |||||
| //if (block == NULL) return; | |||||
| uint32_t mask = (0x80000000 >> (31 - (block->memory_pool_index & 0x1F))); | |||||
| uint32_t index = block->memory_pool_index >> 5; | |||||
| __disable_irq(); | |||||
| if (block->ref_count > 1) { | |||||
| block->ref_count--; | |||||
| } else { | |||||
| //Serial.print("reles:"); | |||||
| //Serial.println((uint32_t)block, HEX); | |||||
| memory_pool_available_mask[index] |= mask; | |||||
| if (index < memory_pool_first_mask) memory_pool_first_mask = index; | |||||
| memory_used--; | |||||
| } | |||||
| __enable_irq(); | |||||
| } | |||||
| // Transmit an audio data block | |||||
| // to all streams that connect to an output. The block | |||||
| // becomes owned by all the recepients, but also is still | |||||
| // owned by this object. Normally, a block must be released | |||||
| // by the caller after it's transmitted. This allows the | |||||
| // caller to transmit to same block to more than 1 output, | |||||
| // and then release it once after all transmit calls. | |||||
| void AudioStream::transmit(audio_block_t *block, unsigned char index) | |||||
| { | |||||
| for (AudioConnection *c = destination_list; c != NULL; c = c->next_dest) { | |||||
| if (c->src_index == index) { | |||||
| if (c->dst.inputQueue[c->dest_index] == NULL) { | |||||
| c->dst.inputQueue[c->dest_index] = block; | |||||
| block->ref_count++; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| // Receive block from an input. The block's data | |||||
| // may be shared with other streams, so it must not be written | |||||
| audio_block_t * AudioStream::receiveReadOnly(unsigned int index) | |||||
| { | |||||
| audio_block_t *in; | |||||
| if (index >= num_inputs) return NULL; | |||||
| in = inputQueue[index]; | |||||
| inputQueue[index] = NULL; | |||||
| return in; | |||||
| } | |||||
| // Receive block from an input. The block will not | |||||
| // be shared, so its contents may be changed. | |||||
| audio_block_t * AudioStream::receiveWritable(unsigned int index) | |||||
| { | |||||
| audio_block_t *in, *p; | |||||
| if (index >= num_inputs) return NULL; | |||||
| in = inputQueue[index]; | |||||
| inputQueue[index] = NULL; | |||||
| if (in && in->ref_count > 1) { | |||||
| p = allocate(); | |||||
| if (p) memcpy(p->data, in->data, sizeof(p->data)); | |||||
| in->ref_count--; | |||||
| in = p; | |||||
| } | |||||
| return in; | |||||
| } | |||||
| void AudioConnection::connect(void) | |||||
| { | |||||
| AudioConnection *p; | |||||
| if (isConnected) return; | |||||
| if (dest_index > dst.num_inputs) return; | |||||
| __disable_irq(); | |||||
| p = src.destination_list; | |||||
| if (p == NULL) { | |||||
| src.destination_list = this; | |||||
| } else { | |||||
| while (p->next_dest) { | |||||
| if (&p->src == &this->src && &p->dst == &this->dst | |||||
| && p->src_index == this->src_index && p->dest_index == this->dest_index) { | |||||
| //Source and destination already connected through another connection, abort | |||||
| __enable_irq(); | |||||
| return; | |||||
| } | |||||
| p = p->next_dest; | |||||
| } | |||||
| p->next_dest = this; | |||||
| } | |||||
| this->next_dest = NULL; | |||||
| src.numConnections++; | |||||
| src.active = true; | |||||
| dst.numConnections++; | |||||
| dst.active = true; | |||||
| isConnected = true; | |||||
| __enable_irq(); | |||||
| } | |||||
| void AudioConnection::disconnect(void) | |||||
| { | |||||
| AudioConnection *p; | |||||
| if (!isConnected) return; | |||||
| if (dest_index > dst.num_inputs) return; | |||||
| __disable_irq(); | |||||
| // Remove destination from source list | |||||
| p = src.destination_list; | |||||
| if (p == NULL) { | |||||
| //>>> PAH re-enable the IRQ | |||||
| __enable_irq(); | |||||
| return; | |||||
| } else if (p == this) { | |||||
| if (p->next_dest) { | |||||
| src.destination_list = next_dest; | |||||
| } else { | |||||
| src.destination_list = NULL; | |||||
| } | |||||
| } else { | |||||
| while (p) { | |||||
| if (p == this) { | |||||
| if (p->next_dest) { | |||||
| p = next_dest; | |||||
| break; | |||||
| } else { | |||||
| p = NULL; | |||||
| break; | |||||
| } | |||||
| } | |||||
| p = p->next_dest; | |||||
| } | |||||
| } | |||||
| //>>> PAH release the audio buffer properly | |||||
| //Remove possible pending src block from destination | |||||
| if(dst.inputQueue[dest_index] != NULL) { | |||||
| AudioStream::release(dst.inputQueue[dest_index]); | |||||
| // release() re-enables the IRQ. Need it to be disabled a little longer | |||||
| __disable_irq(); | |||||
| dst.inputQueue[dest_index] = NULL; | |||||
| } | |||||
| //Check if the disconnected AudioStream objects should still be active | |||||
| src.numConnections--; | |||||
| if (src.numConnections == 0) { | |||||
| src.active = false; | |||||
| } | |||||
| dst.numConnections--; | |||||
| if (dst.numConnections == 0) { | |||||
| dst.active = false; | |||||
| } | |||||
| isConnected = false; | |||||
| __enable_irq(); | |||||
| } | |||||
| // When an object has taken responsibility for calling update_all() | |||||
| // at each block interval (approx 2.9ms), this variable is set to | |||||
| // true. Objects that are capable of calling update_all(), typically | |||||
| // input and output based on interrupts, must check this variable in | |||||
| // their constructors. | |||||
| bool AudioStream::update_scheduled = false; | |||||
| bool AudioStream::update_setup(void) | |||||
| { | |||||
| if (update_scheduled) return false; | |||||
| NVIC_SET_PRIORITY(IRQ_SOFTWARE, 208); // 255 = lowest priority | |||||
| NVIC_ENABLE_IRQ(IRQ_SOFTWARE); | |||||
| update_scheduled = true; | |||||
| return true; | |||||
| } | |||||
| void AudioStream::update_stop(void) | |||||
| { | |||||
| NVIC_DISABLE_IRQ(IRQ_SOFTWARE); | |||||
| update_scheduled = false; | |||||
| } | |||||
| AudioStream * AudioStream::first_update = NULL; | |||||
| void software_isr(void) // AudioStream::update_all() | |||||
| { | |||||
| AudioStream *p; | |||||
| #if defined(KINETISK) | |||||
| ARM_DEMCR |= ARM_DEMCR_TRCENA; | |||||
| ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; | |||||
| uint32_t totalcycles = ARM_DWT_CYCCNT; | |||||
| #elif defined(KINETISL) | |||||
| uint32_t totalcycles = micros(); | |||||
| #endif | |||||
| //digitalWriteFast(2, HIGH); | |||||
| for (p = AudioStream::first_update; p; p = p->next_update) { | |||||
| if (p->active) { | |||||
| uint32_t cycles = ARM_DWT_CYCCNT; | |||||
| p->update(); | |||||
| // TODO: traverse inputQueueArray and release | |||||
| // any input blocks that weren't consumed? | |||||
| cycles = (ARM_DWT_CYCCNT - cycles) >> 4; | |||||
| p->cpu_cycles = cycles; | |||||
| if (cycles > p->cpu_cycles_max) p->cpu_cycles_max = cycles; | |||||
| } | |||||
| } | |||||
| //digitalWriteFast(2, LOW); | |||||
| #if defined(KINETISK) | |||||
| totalcycles = (ARM_DWT_CYCCNT - totalcycles) >> 4; | |||||
| #elif defined(KINETISL) | |||||
| totalcycles = micros() - totalcycles; | |||||
| #endif | |||||
| AudioStream::cpu_cycles_total = totalcycles; | |||||
| if (totalcycles > AudioStream::cpu_cycles_total_max) | |||||
| AudioStream::cpu_cycles_total_max = totalcycles; | |||||
| } | |||||
| /* 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 AudioStream_h | |||||
| #define AudioStream_h | |||||
| #ifndef __ASSEMBLER__ | |||||
| #include <stdio.h> // for NULL | |||||
| #include <string.h> // for memcpy | |||||
| #include "kinetis.h" | |||||
| #endif | |||||
| // AUDIO_BLOCK_SAMPLES determines how many samples the audio library processes | |||||
| // per update. It may be reduced to achieve lower latency response to events, | |||||
| // at the expense of higher interrupt and DMA setup overhead. | |||||
| // | |||||
| // Less than 32 may not work with some input & output objects. Multiples of 16 | |||||
| // should be used, since some synthesis objects generate 16 samples per loop. | |||||
| // | |||||
| // Some parts of the audio library may have hard-coded dependency on 128 samples. | |||||
| // Please report these on the forum with reproducible test cases. | |||||
| #ifndef AUDIO_BLOCK_SAMPLES | |||||
| #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) | |||||
| #define AUDIO_BLOCK_SAMPLES 128 | |||||
| #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 | |||||
| #define AUDIO_SAMPLE_RATE_EXACT 44117.64706 | |||||
| #endif | |||||
| #endif | |||||
| #define AUDIO_SAMPLE_RATE AUDIO_SAMPLE_RATE_EXACT | |||||
| #ifndef __ASSEMBLER__ | |||||
| class AudioStream; | |||||
| class AudioConnection; | |||||
| typedef struct audio_block_struct { | |||||
| uint8_t ref_count; | |||||
| uint8_t reserved1; | |||||
| uint16_t memory_pool_index; | |||||
| int16_t data[AUDIO_BLOCK_SAMPLES]; | |||||
| } audio_block_t; | |||||
| class AudioConnection | |||||
| { | |||||
| public: | |||||
| AudioConnection(AudioStream &source, AudioStream &destination) : | |||||
| src(source), dst(destination), src_index(0), dest_index(0), | |||||
| next_dest(NULL) | |||||
| { 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) | |||||
| { isConnected = false; | |||||
| connect(); } | |||||
| friend class AudioStream; | |||||
| ~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; | |||||
| }; | |||||
| #define AudioMemory(num) ({ \ | |||||
| static DMAMEM audio_block_t data[num]; \ | |||||
| AudioStream::initialize_memory(data, num); \ | |||||
| }) | |||||
| #if defined(KINETISK) | |||||
| #define CYCLE_COUNTER_APPROX_PERCENT(n) (((n) + (F_CPU / 32 / AUDIO_SAMPLE_RATE * AUDIO_BLOCK_SAMPLES / 100)) / (F_CPU / 16 / AUDIO_SAMPLE_RATE * AUDIO_BLOCK_SAMPLES / 100)) | |||||
| #elif defined(KINETISL) | |||||
| #define CYCLE_COUNTER_APPROX_PERCENT(n) ((n) * (int)(AUDIO_SAMPLE_RATE) + (int)(AUDIO_SAMPLE_RATE/2)) / (AUDIO_BLOCK_SAMPLES * 10000) | |||||
| #endif | |||||
| #define AudioProcessorUsage() (CYCLE_COUNTER_APPROX_PERCENT(AudioStream::cpu_cycles_total)) | |||||
| #define AudioProcessorUsageMax() (CYCLE_COUNTER_APPROX_PERCENT(AudioStream::cpu_cycles_total_max)) | |||||
| #define AudioProcessorUsageMaxReset() (AudioStream::cpu_cycles_total_max = AudioStream::cpu_cycles_total) | |||||
| #define AudioMemoryUsage() (AudioStream::memory_used) | |||||
| #define AudioMemoryUsageMax() (AudioStream::memory_used_max) | |||||
| #define AudioMemoryUsageMaxReset() (AudioStream::memory_used_max = AudioStream::memory_used) | |||||
| class AudioStream | |||||
| { | |||||
| public: | |||||
| AudioStream(unsigned char ninput, audio_block_t **iqueue) : | |||||
| num_inputs(ninput), inputQueue(iqueue) { | |||||
| active = false; | |||||
| destination_list = NULL; | |||||
| for (int i=0; i < num_inputs; i++) { | |||||
| inputQueue[i] = NULL; | |||||
| } | |||||
| // add to a simple list, for update_all | |||||
| // TODO: replace with a proper data flow analysis in update_all | |||||
| if (first_update == NULL) { | |||||
| first_update = this; | |||||
| } else { | |||||
| AudioStream *p; | |||||
| for (p=first_update; p->next_update; p = p->next_update) ; | |||||
| p->next_update = this; | |||||
| } | |||||
| 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 uint16_t memory_used; | |||||
| static uint16_t memory_used_max; | |||||
| protected: | |||||
| bool active; | |||||
| unsigned char num_inputs; | |||||
| static audio_block_t * allocate(void); | |||||
| static void release(audio_block_t * block); | |||||
| void transmit(audio_block_t *block, unsigned char index = 0); | |||||
| audio_block_t * receiveReadOnly(unsigned int index = 0); | |||||
| audio_block_t * receiveWritable(unsigned int index = 0); | |||||
| static bool update_setup(void); | |||||
| static void update_stop(void); | |||||
| 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; | |||||
| static bool update_scheduled; | |||||
| virtual void update(void) = 0; | |||||
| 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[]; | |||||
| static uint16_t memory_pool_first_mask; | |||||
| }; | |||||
| #endif | |||||
| #endif |
| /* | |||||
| 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 | |||||
| #define client_h | |||||
| #include "Print.h" | |||||
| #include "Stream.h" | |||||
| #include "IPAddress.h" | |||||
| class Client : public Stream { | |||||
| public: | |||||
| virtual int connect(IPAddress ip, uint16_t port) =0; | |||||
| virtual int connect(const char *host, uint16_t port) =0; | |||||
| virtual size_t write(uint8_t) =0; | |||||
| virtual size_t write(const uint8_t *buf, size_t size) =0; | |||||
| virtual int available() = 0; | |||||
| virtual int read() = 0; | |||||
| virtual int read(uint8_t *buf, size_t size) = 0; | |||||
| virtual int peek() = 0; | |||||
| virtual void flush() = 0; | |||||
| virtual void stop() = 0; | |||||
| virtual uint8_t connected() = 0; | |||||
| virtual operator bool() = 0; | |||||
| protected: | |||||
| uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; | |||||
| }; | |||||
| #endif | |||||
| #endif |
| /* 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_MAX_CHANNELS | |||||
| && (dma_channel_allocated_mask & (1 << channel)) | |||||
| && (uint32_t)TCD == (uint32_t)(0x40009000 + channel * 32)) { | |||||
| // 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(); | |||||
| TCD = (TCD_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; | |||||
| #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; | |||||
| DMA_CINT = ch; | |||||
| TCD = (TCD_t *)(0x40009000 + ch * 32); | |||||
| uint32_t *p = (uint32_t *)TCD; | |||||
| *p++ = 0; | |||||
| *p++ = 0; | |||||
| *p++ = 0; | |||||
| *p++ = 0; | |||||
| *p++ = 0; | |||||
| *p++ = 0; | |||||
| *p++ = 0; | |||||
| *p++ = 0; | |||||
| } | |||||
| void DMAChannel::release(void) | |||||
| { | |||||
| if (channel >= DMA_MAX_CHANNELS) return; | |||||
| DMA_CERQ = channel; | |||||
| __disable_irq(); | |||||
| dma_channel_allocated_mask &= ~(1 << channel); | |||||
| __enable_irq(); | |||||
| channel = DMA_MAX_CHANNELS; | |||||
| TCD = (TCD_t *)0; | |||||
| } | |||||
| static uint32_t priority(const DMAChannel &c) | |||||
| { | |||||
| uint32_t n; | |||||
| n = *(uint32_t *)((uint32_t)&DMA_DCHPRI3 + (c.channel & 0xFC)); | |||||
| n = __builtin_bswap32(n); | |||||
| return (n >> ((c.channel & 0x03) << 3)) & 0x0F; | |||||
| } | |||||
| static void swap(DMAChannel &c1, DMAChannel &c2) | |||||
| { | |||||
| uint8_t c; | |||||
| DMABaseClass::TCD_t *t; | |||||
| c = c1.channel; | |||||
| c1.channel = c2.channel; | |||||
| c2.channel = c; | |||||
| t = c1.TCD; | |||||
| c1.TCD = c2.TCD; | |||||
| 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); | |||||
| } | |||||
| void DMAPriorityOrder(DMAChannel &ch1, DMAChannel &ch2, DMAChannel &ch3) | |||||
| { | |||||
| if (priority(ch2) < priority(ch3)) swap(ch2, ch3); | |||||
| if (priority(ch1) < priority(ch2)) swap(ch1, ch2); | |||||
| if (priority(ch2) < priority(ch3)) swap(ch2, ch3); | |||||
| } | |||||
| void DMAPriorityOrder(DMAChannel &ch1, DMAChannel &ch2, DMAChannel &ch3, DMAChannel &ch4) | |||||
| { | |||||
| if (priority(ch3) < priority(ch4)) swap(ch3, ch4); | |||||
| if (priority(ch2) < priority(ch3)) swap(ch2, ch3); | |||||
| if (priority(ch1) < priority(ch2)) swap(ch1, ch2); | |||||
| if (priority(ch3) < priority(ch4)) swap(ch2, ch3); | |||||
| if (priority(ch2) < priority(ch3)) swap(ch1, ch2); | |||||
| if (priority(ch3) < priority(ch4)) swap(ch2, ch3); | |||||
| } | |||||
| /* 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!!! | |||||
| // BUGBUG: See if file name order makes difference? | |||||
| uint8_t _serialEvent_default __attribute__((weak)) PROGMEM = 0 ; | |||||
| uint8_t _serialEventUSB1_default __attribute__((weak)) PROGMEM = 0 ; | |||||
| uint8_t _serialEventUSB2_default __attribute__((weak)) PROGMEM = 0 ; | |||||
| void EventResponder::triggerEventNotImmediate() | |||||
| { | |||||
| 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++; | |||||
| } | |||||
| extern "C" void systick_isr_with_timer_events(void) | |||||
| { | |||||
| systick_millis_count++; | |||||
| MillisTimer::runFromTimer(); | |||||
| } | |||||
| /* 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. | |||||
| */ | |||||
| extern "C" void systick_isr_with_timer_events(void); | |||||
| 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; | |||||
| yield_active_check_flags |= YIELD_CHECK_EVENT_RESPONDER; // user setup a yield type... | |||||
| 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 | |||||
| // Make sure we are using the systic ISR that process this | |||||
| _VectorsRam[15] = systick_isr_with_timer_events; | |||||
| 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() { | |||||
| if (!firstYield) return; | |||||
| // 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 |
| /* Teensyduino Core Library - File base class | |||||
| * http://www.pjrc.com/teensy/ | |||||
| * Copyright (c) 2020 PJRC.COM, LLC. | |||||
| * | |||||
| * Permission is hereby granted, free of charge, to any person obtaining | |||||
| * a copy of this software and associated documentation files (the | |||||
| * "Software"), to deal in the Software without restriction, including | |||||
| * without limitation the rights to use, copy, modify, merge, publish, | |||||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||||
| * permit persons to whom the Software is furnished to do so, subject to | |||||
| * the following conditions: | |||||
| * | |||||
| * 1. The above copyright notice and this permission notice shall be | |||||
| * included in all copies or substantial portions of the Software. | |||||
| * | |||||
| * 2. If the Software is incorporated into a build system that allows | |||||
| * selection among a list of target devices, then similar target | |||||
| * devices manufactured by PJRC.COM must be included in the list of | |||||
| * target devices and selectable in the same manner. | |||||
| * | |||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
| * SOFTWARE. | |||||
| */ | |||||
| #ifndef FS_H | |||||
| #define FS_H | |||||
| #ifdef __cplusplus | |||||
| #include <Arduino.h> | |||||
| #define FILE_READ 0 | |||||
| #define FILE_WRITE 1 | |||||
| #define FILE_WRITE_BEGIN 2 | |||||
| enum SeekMode { | |||||
| SeekSet = 0, | |||||
| SeekCur = 1, | |||||
| SeekEnd = 2 | |||||
| }; | |||||
| #define FILE_WHOAMI | |||||
| class File : public Stream { | |||||
| public: | |||||
| constexpr File() : f(nullptr) { } | |||||
| File(File *file) { | |||||
| // "file" must only be a class derived from File | |||||
| // can we use is_same or is_polymorphic with static_assert? | |||||
| // or is_base_of | |||||
| //static_assert(std::is_same<decltype(*file),File>::value, | |||||
| //"File(File *file) constructor only accepts pointers " | |||||
| //"to derived classes, not File itself"); | |||||
| f = file; | |||||
| if (f) f->refcount++; | |||||
| } | |||||
| File(const File &file) { | |||||
| //Serial.println("File copy constructor"); | |||||
| //static int copycount=0; | |||||
| //if (++copycount > 20) while (1) ; | |||||
| f = file.f; | |||||
| if (f) f->refcount++; | |||||
| } | |||||
| File& operator = (const File &file) { | |||||
| //Serial.println("File assignment"); | |||||
| //static int assigncount=0; | |||||
| //if (++assigncount > 20) while (1) ; | |||||
| invalidate(); | |||||
| f = file.f; | |||||
| if (f) f->refcount++; | |||||
| return *this; | |||||
| } | |||||
| virtual ~File() { | |||||
| invalidate(); | |||||
| } | |||||
| #ifdef FILE_WHOAMI | |||||
| virtual void whoami() { // testing only | |||||
| Serial.printf(" File this=%x, f=%x\n", (int)this, (int)f); | |||||
| if (f) f->whoami(); | |||||
| } | |||||
| unsigned int getRefcount() { // testing only | |||||
| return refcount; | |||||
| } | |||||
| #endif | |||||
| virtual size_t read(void *buf, size_t nbyte) { | |||||
| return (f) ? f->read(buf, nbyte) : 0; | |||||
| } | |||||
| virtual size_t write(const void *buf, size_t size) { | |||||
| return (f) ? f->write(buf, size) : 0; | |||||
| } | |||||
| virtual int available() { | |||||
| return (f) ? f->available() : 0; | |||||
| } | |||||
| virtual int peek() { | |||||
| return (f) ? f->peek() : -1; | |||||
| } | |||||
| virtual void flush() { | |||||
| if (f) f->flush(); | |||||
| } | |||||
| virtual bool truncate(uint64_t size=0) { | |||||
| return (f) ? f->truncate(size) : false; | |||||
| } | |||||
| virtual bool seek(uint64_t pos, int mode) { | |||||
| return (f) ? f->seek(pos, mode) : false; | |||||
| } | |||||
| virtual uint64_t position() { | |||||
| return (f) ? f->position() : 0; | |||||
| } | |||||
| virtual uint64_t size() { | |||||
| return (f) ? f->size() : 0; | |||||
| } | |||||
| virtual void close() { | |||||
| if (f) f->close(); | |||||
| } | |||||
| virtual operator bool() { | |||||
| return (f) ? (bool)*f : false; | |||||
| } | |||||
| virtual const char* name() { | |||||
| return (f) ? f->name() : ""; | |||||
| } | |||||
| virtual bool isDirectory() { | |||||
| return (f) ? f->isDirectory() : false; | |||||
| } | |||||
| virtual File openNextFile(uint8_t mode=0) { | |||||
| return (f) ? f->openNextFile(mode) : *this; | |||||
| } | |||||
| virtual void rewindDirectory(void) { | |||||
| if (f) f->rewindDirectory(); | |||||
| } | |||||
| bool seek(uint64_t pos) { | |||||
| return seek(pos, SeekSet); | |||||
| } | |||||
| int read() { | |||||
| if (!f) return -1; | |||||
| unsigned char b; | |||||
| if (f->read(&b, 1) < 1) return -1; | |||||
| return b; | |||||
| } | |||||
| size_t write(uint8_t b) { | |||||
| return write(&b, 1); | |||||
| } | |||||
| size_t write(const char *str) { | |||||
| return write(str, strlen(str)); | |||||
| } | |||||
| size_t readBytes(char *buffer, size_t length) { | |||||
| return read(buffer, length); | |||||
| } | |||||
| private: | |||||
| void invalidate() { | |||||
| if (f && --(f->refcount) == 0) delete f; | |||||
| } | |||||
| union { | |||||
| // instances of base File class use this pointer | |||||
| File *f; | |||||
| // instances of derived classes (which actually access media) | |||||
| // use this reference count which is managed by the base class | |||||
| unsigned int refcount; | |||||
| }; | |||||
| }; | |||||
| class FS | |||||
| { | |||||
| public: | |||||
| FS() {} | |||||
| virtual File open(const char *filename, uint8_t mode = FILE_READ) = 0; | |||||
| virtual bool exists(const char *filepath) = 0; | |||||
| virtual bool mkdir(const char *filepath) = 0; | |||||
| virtual bool rename(const char *oldfilepath, const char *newfilepath) = 0; | |||||
| virtual bool remove(const char *filepath) = 0; | |||||
| virtual bool rmdir(const char *filepath) = 0; | |||||
| virtual uint64_t usedSize() = 0; | |||||
| virtual uint64_t totalSize() = 0; | |||||
| }; | |||||
| #endif // __cplusplus | |||||
| #endif // FS_H |
| /* Teensyduino Core Library | |||||
| * http://www.pjrc.com/teensy/ | |||||
| * Copyright (c) 2019 PJRC.COM, LLC. | |||||
| * | |||||
| * Permission is hereby granted, free of charge, to any person obtaining | |||||
| * a copy of this software and associated documentation files (the | |||||
| * "Software"), to deal in the Software without restriction, including | |||||
| * without limitation the rights to use, copy, modify, merge, publish, | |||||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||||
| * permit persons to whom the Software is furnished to do so, subject to | |||||
| * the following conditions: | |||||
| * | |||||
| * 1. The above copyright notice and this permission notice shall be | |||||
| * included in all copies or substantial portions of the Software. | |||||
| * | |||||
| * 2. If the Software is incorporated into a build system that allows | |||||
| * selection among a list of target devices, then similar target | |||||
| * devices manufactured by PJRC.COM must be included in the list of | |||||
| * target devices and selectable in the same manner. | |||||
| * | |||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
| * SOFTWARE. | |||||
| */ | |||||
| #include "HardwareSerial.h" | |||||
| #include "core_pins.h" | |||||
| #include "Arduino.h" | |||||
| // define our static objects | |||||
| HardwareSerial *HardwareSerial::s_serials_with_serial_events[CNT_HARDWARE_SERIAL]; | |||||
| uint8_t HardwareSerial::s_count_serials_with_serial_events = 0; | |||||
| // simple helper function that add us to the list of Serial ports that have | |||||
| // their own serialEvent code defined that needs to be called at yield. | |||||
| void HardwareSerial::addToSerialEventsList() { | |||||
| for (uint8_t i = 0; i < s_count_serials_with_serial_events; i++) { | |||||
| if (s_serials_with_serial_events[i] == this) return; // already in the list. | |||||
| } | |||||
| s_serials_with_serial_events[s_count_serials_with_serial_events++] = this; | |||||
| yield_active_check_flags |= YIELD_CHECK_HARDWARE_SERIAL; | |||||
| } | |||||
| /* 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 HardwareSerial_h | |||||
| #define HardwareSerial_h | |||||
| #include "kinetis.h" | |||||
| #include <stddef.h> | |||||
| // 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_8E1 0x06 | |||||
| #define SERIAL_8O1 0x07 | |||||
| #define SERIAL_7E1_RXINV 0x12 | |||||
| #define SERIAL_7O1_RXINV 0x13 | |||||
| #define SERIAL_8N1_RXINV 0x10 | |||||
| #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_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_8E1_RXINV_TXINV 0x36 | |||||
| #define SERIAL_8O1_RXINV_TXINV 0x37 | |||||
| #ifdef SERIAL_9BIT_SUPPORT | |||||
| #define SERIAL_9N1 0x84 | |||||
| #define SERIAL_9E1 0x8E | |||||
| #define SERIAL_9O1 0x8F | |||||
| #define SERIAL_9N1_RXINV 0x94 | |||||
| #define SERIAL_9E1_RXINV 0x9E | |||||
| #define SERIAL_9O1_RXINV 0x9F | |||||
| #define SERIAL_9N1_TXINV 0xA4 | |||||
| #define SERIAL_9E1_TXINV 0xAE | |||||
| #define SERIAL_9O1_TXINV 0xAF | |||||
| #define SERIAL_9N1_RXINV_TXINV 0xB4 | |||||
| #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 | |||||
| // Half duplex support | |||||
| #define SERIAL_HALF_DUPLEX 0x200 | |||||
| #define SERIAL_7E1_HALF_DUPLEX (SERIAL_7E1 | SERIAL_HALF_DUPLEX) | |||||
| #define SERIAL_7O1_HALF_DUPLEX (SERIAL_7O1 | SERIAL_HALF_DUPLEX) | |||||
| #define SERIAL_8N1_HALF_DUPLEX (SERIAL_8N1 | SERIAL_HALF_DUPLEX) | |||||
| // bit0: parity, 0=even, 1=odd | |||||
| // bit1: parity, 0=disable, 1=enable | |||||
| // bit2: mode, 1=9bit, 0=8bit | |||||
| // bit3: mode10: 1=10bit, 0=8bit | |||||
| // bit4: rxinv, 0=normal, 1=inverted | |||||
| // bit5: txinv, 0=normal, 1=inverted | |||||
| // bit6: unused | |||||
| // bit7: actual data goes into 9th bit | |||||
| // bit8: 2 stop bits (T3.5/3.6 and LC) | |||||
| // bit9: Half duplex | |||||
| #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 | |||||
| // | |||||
| #ifdef __cplusplus | |||||
| extern "C" { | |||||
| #endif | |||||
| 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); | |||||
| int serial_write_buffer_free(void); | |||||
| void serial_add_memory_for_read(void *buffer, size_t length); | |||||
| void serial_add_memory_for_write(void *buffer, size_t length); | |||||
| int serial_available(void); | |||||
| int serial_getchar(void); | |||||
| int serial_peek(void); | |||||
| void serial_clear(void); | |||||
| void serial_print(const char *p); | |||||
| void serial_phex(uint32_t n); | |||||
| void serial_phex16(uint32_t n); | |||||
| void serial_phex32(uint32_t n); | |||||
| 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); | |||||
| int serial2_write_buffer_free(void); | |||||
| void serial2_add_memory_for_read(void *buffer, size_t length); | |||||
| void serial2_add_memory_for_write(void *buffer, size_t length); | |||||
| int serial2_available(void); | |||||
| int serial2_getchar(void); | |||||
| int serial2_peek(void); | |||||
| void serial2_clear(void); | |||||
| 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); | |||||
| int serial3_write_buffer_free(void); | |||||
| void serial3_add_memory_for_read(void *buffer, size_t length); | |||||
| void serial3_add_memory_for_write(void *buffer, size_t length); | |||||
| int serial3_available(void); | |||||
| 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); | |||||
| void serial4_add_memory_for_read(void *buffer, size_t length); | |||||
| void serial4_add_memory_for_write(void *buffer, size_t length); | |||||
| 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); | |||||
| void serial5_add_memory_for_read(void *buffer, size_t length); | |||||
| void serial5_add_memory_for_write(void *buffer, size_t length); | |||||
| 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); | |||||
| void serial6_add_memory_for_read(void *buffer, size_t length); | |||||
| void serial6_add_memory_for_write(void *buffer, size_t length); | |||||
| int serial6_available(void); | |||||
| int serial6_getchar(void); | |||||
| int serial6_peek(void); | |||||
| void serial6_clear(void); | |||||
| #ifdef __cplusplus | |||||
| } | |||||
| #endif | |||||
| // C++ interface | |||||
| // | |||||
| #ifdef __cplusplus | |||||
| #include "Stream.h" | |||||
| class HardwareSerial : public Stream | |||||
| { | |||||
| public: | |||||
| constexpr HardwareSerial(void (* const se)()) : _serialEvent(se) {} | |||||
| #if defined(__MK64FX512__) || defined(__MK66FX1M0__) | |||||
| enum {CNT_HARDWARE_SERIAL = 6}; | |||||
| #else //(__MK64FX512__) || defined(__MK66FX1M0__) | |||||
| enum {CNT_HARDWARE_SERIAL = 3}; | |||||
| #endif | |||||
| virtual void begin(uint32_t baud); | |||||
| virtual void begin(uint32_t baud, uint32_t format) { | |||||
| serial_begin(BAUD2DIV(baud)); | |||||
| serial_format(format); } | |||||
| 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(); } | |||||
| virtual void addMemoryForRead(void *buffer, size_t length) {serial_add_memory_for_read(buffer, length);} | |||||
| virtual void addMemoryForWrite(void *buffer, size_t length){serial_add_memory_for_write(buffer, length);} | |||||
| 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); } | |||||
| 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) | |||||
| { serial_write(buffer, size); return size; } | |||||
| virtual size_t write(const char *str) { size_t len = strlen(str); | |||||
| 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; } | |||||
| static inline void processSerialEventsList() { | |||||
| for (uint8_t i = 0; i < s_count_serials_with_serial_events; i++) { | |||||
| s_serials_with_serial_events[i]->doYieldCode(); | |||||
| } | |||||
| } | |||||
| protected: | |||||
| static HardwareSerial *s_serials_with_serial_events[CNT_HARDWARE_SERIAL]; | |||||
| static uint8_t s_count_serials_with_serial_events; | |||||
| void (* const _serialEvent)(); | |||||
| void addToSerialEventsList(); | |||||
| inline void doYieldCode() { | |||||
| if (available()) (*_serialEvent)(); | |||||
| } | |||||
| }; | |||||
| extern HardwareSerial Serial1; | |||||
| extern void serialEvent1(void); | |||||
| class HardwareSerial2 : public HardwareSerial | |||||
| { | |||||
| public: | |||||
| constexpr HardwareSerial2(void (* const se)()) : HardwareSerial(se) {} | |||||
| virtual void begin(uint32_t baud); | |||||
| virtual void begin(uint32_t baud, uint32_t format) { | |||||
| serial2_begin(BAUD2DIV2(baud)); | |||||
| serial2_format(format); } | |||||
| 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(); } | |||||
| virtual void addMemoryForRead(void *buffer, size_t length) {serial2_add_memory_for_read(buffer, length);} | |||||
| virtual void addMemoryForWrite(void *buffer, size_t length){serial2_add_memory_for_write(buffer, length);} | |||||
| 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); } | |||||
| 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) | |||||
| { serial2_write(buffer, size); return size; } | |||||
| virtual size_t write(const char *str) { size_t len = strlen(str); | |||||
| 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); | |||||
| class HardwareSerial3 : public HardwareSerial | |||||
| { | |||||
| public: | |||||
| constexpr HardwareSerial3(void (* const se)()) : HardwareSerial(se) {} | |||||
| virtual void begin(uint32_t baud); | |||||
| virtual void begin(uint32_t baud, uint32_t format) { | |||||
| serial3_begin(BAUD2DIV3(baud)); | |||||
| serial3_format(format); } | |||||
| 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(); } | |||||
| virtual void addMemoryForRead(void *buffer, size_t length) {serial3_add_memory_for_read(buffer, length);} | |||||
| virtual void addMemoryForWrite(void *buffer, size_t length){serial3_add_memory_for_write(buffer, length);} | |||||
| 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); } | |||||
| 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) | |||||
| { serial3_write(buffer, size); return size; } | |||||
| virtual size_t write(const char *str) { size_t len = strlen(str); | |||||
| 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(void (* const se)()) : HardwareSerial(se) {} | |||||
| virtual void begin(uint32_t baud); | |||||
| virtual void begin(uint32_t baud, uint32_t format) { | |||||
| serial4_begin(BAUD2DIV3(baud)); | |||||
| serial4_format(format); } | |||||
| 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(); } | |||||
| virtual void addMemoryForRead(void *buffer, size_t length) {serial4_add_memory_for_read(buffer, length);} | |||||
| virtual void addMemoryForWrite(void *buffer, size_t length){serial4_add_memory_for_write(buffer, length);} | |||||
| 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(void (* const se)()) : HardwareSerial(se) {} | |||||
| virtual void begin(uint32_t baud); | |||||
| virtual void begin(uint32_t baud, uint32_t format) { | |||||
| serial5_begin(BAUD2DIV3(baud)); | |||||
| serial5_format(format); } | |||||
| 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(); } | |||||
| virtual void addMemoryForRead(void *buffer, size_t length) {serial5_add_memory_for_read(buffer, length);} | |||||
| virtual void addMemoryForWrite(void *buffer, size_t length){serial5_add_memory_for_write(buffer, length);} | |||||
| 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(void (* const se)()) : HardwareSerial(se) {} | |||||
| #if defined(__MK66FX1M0__) // For LPUART just pass baud straight in. | |||||
| virtual void begin(uint32_t baud); | |||||
| virtual void begin(uint32_t baud, uint32_t format) { | |||||
| serial6_begin(baud); | |||||
| serial6_format(format); } | |||||
| #else | |||||
| virtual void begin(uint32_t baud); | |||||
| 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(); } | |||||
| virtual void addMemoryForRead(void *buffer, size_t length) {serial6_add_memory_for_read(buffer, length);} | |||||
| virtual void addMemoryForWrite(void *buffer, size_t length){serial6_add_memory_for_write(buffer, length);} | |||||
| 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 |
| /* 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" | |||||
| uint8_t _serialEvent1_default __attribute__((weak)) PROGMEM = 0 ; | |||||
| HardwareSerial Serial1(&serialEvent1); | |||||
| void HardwareSerial::begin(uint32_t baud) { | |||||
| serial_begin(BAUD2DIV(baud)); | |||||
| if (!_serialEvent1_default) addToSerialEventsList(); | |||||
| } | |||||
| /* 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(&serialEvent2); | |||||
| uint8_t _serialEvent2_default __attribute__((weak)) PROGMEM = 0 ; | |||||
| void HardwareSerial2::begin(uint32_t baud) { | |||||
| serial2_begin(BAUD2DIV2(baud)); | |||||
| if (!_serialEvent2_default) addToSerialEventsList(); | |||||
| } |
| /* 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(&serialEvent3); | |||||
| uint8_t _serialEvent3_default __attribute__((weak)) PROGMEM = 0 ; | |||||
| void HardwareSerial3::begin(uint32_t baud) { | |||||
| serial3_begin(BAUD2DIV3(baud)); | |||||
| if (!_serialEvent3_default) addToSerialEventsList(); | |||||
| } |
| /* 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(&serialEvent4); | |||||
| uint8_t _serialEvent4_default __attribute__((weak)) PROGMEM = 0 ; | |||||
| void HardwareSerial4::begin(uint32_t baud) { | |||||
| serial4_begin(BAUD2DIV3(baud)); | |||||
| if (!_serialEvent4_default) addToSerialEventsList(); | |||||
| } | |||||
| #endif |
| /* 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(&serialEvent5); | |||||
| uint8_t _serialEvent5_default __attribute__((weak)) PROGMEM = 0 ; | |||||
| void HardwareSerial5::begin(uint32_t baud) { | |||||
| serial5_begin(BAUD2DIV3(baud)); | |||||
| if (!_serialEvent5_default) addToSerialEventsList(); | |||||
| } | |||||
| #endif |
| /* 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(&serialEvent6); | |||||
| uint8_t _serialEvent6_default __attribute__((weak)) PROGMEM = 0 ; | |||||
| void HardwareSerial6::begin(uint32_t baud) { | |||||
| #if defined(__MK66FX1M0__) // For LPUART just pass baud straight in. | |||||
| serial6_begin(baud); | |||||
| #else | |||||
| serial6_begin(BAUD2DIV3(baud)); | |||||
| #endif | |||||
| if (!_serialEvent6_default) addToSerialEventsList(); | |||||
| } | |||||
| #endif |
| /* | |||||
| IPAddress.cpp - Base class that provides IPAddress | |||||
| Copyright (c) 2011 Adrian McEwen. All right reserved. | |||||
| This library is free software; you can redistribute it and/or | |||||
| modify it under the terms of the GNU Lesser General Public | |||||
| License as published by the Free Software Foundation; either | |||||
| version 2.1 of the License, or (at your option) any later version. | |||||
| This library is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||||
| Lesser General Public License for more details. | |||||
| You should have received a copy of the GNU Lesser General Public | |||||
| License along with this library; if not, write to the Free Software | |||||
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |||||
| */ | |||||
| #include <Arduino.h> | |||||
| #include "IPAddress.h" | |||||
| size_t IPAddress::printTo(Print& p) const | |||||
| { | |||||
| int i=0; | |||||
| while (1) { | |||||
| p.print(_address.bytes[i], DEC); | |||||
| if (++i >= 4) return 4; | |||||
| p.write('.'); | |||||
| } | |||||
| } | |||||
| bool IPAddress::fromString(const char *address) | |||||
| { | |||||
| unsigned int acc = 0; // Accumulator | |||||
| unsigned int 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; | |||||
| } | |||||
| /* | |||||
| * | |||||
| * MIT License: | |||||
| * Copyright (c) 2011 Adrian McEwen | |||||
| * 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. | |||||
| * | |||||
| * adrianm@mcqn.com 1/1/2011 | |||||
| */ | |||||
| #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: | |||||
| 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() { | |||||
| _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.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.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) { | |||||
| // 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; | |||||
| friend class EthernetClass; | |||||
| friend class UDP; | |||||
| friend class Client; | |||||
| friend class Server; | |||||
| friend class DhcpClass; | |||||
| friend class DNSClient; | |||||
| }; | |||||
| const IPAddress INADDR_NONE((uint32_t)0); | |||||
| #endif |
| /* Teensyduino Core Library | |||||
| * http://www.pjrc.com/teensy/ | |||||
| * Copyright (c) 2017 PJRC.COM, LLC. | |||||
| * | |||||
| * Permission is hereby granted, free of charge, to any person obtaining | |||||
| * a copy of this software and associated documentation files (the | |||||
| * "Software"), to deal in the Software without restriction, including | |||||
| * without limitation the rights to use, copy, modify, merge, publish, | |||||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||||
| * permit persons to whom the Software is furnished to do so, subject to | |||||
| * the following conditions: | |||||
| * | |||||
| * 1. The above copyright notice and this permission notice shall be | |||||
| * included in all copies or substantial portions of the Software. | |||||
| * | |||||
| * 2. If the Software is incorporated into a build system that allows | |||||
| * selection among a list of target devices, then similar target | |||||
| * devices manufactured by PJRC.COM must be included in the list of | |||||
| * target devices and selectable in the same manner. | |||||
| * | |||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||||
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||||
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||||
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||||
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
| * SOFTWARE. | |||||
| */ | |||||
| #include "IntervalTimer.h" | |||||
| static void dummy_funct(void); | |||||
| #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; | |||||
| } | |||||
| void IntervalTimer::end() { | |||||
| 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; | |||||
| } | |||||
| } | |||||
| #if defined(KINETISK) | |||||
| void pit0_isr() | |||||
| { | |||||
| PIT_TFLG0 = 1; | |||||
| funct_table[0](); | |||||
| } | |||||
| void pit1_isr() { | |||||
| PIT_TFLG1 = 1; | |||||
| funct_table[1](); | |||||
| } | |||||
| void pit2_isr() { | |||||
| PIT_TFLG2 = 1; | |||||
| funct_table[2](); | |||||
| } | |||||
| void pit3_isr() { | |||||
| PIT_TFLG3 = 1; | |||||
| funct_table[3](); | |||||
| } | |||||
| #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) | |||||
| { | |||||
| } | |||||
| /* 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__ | |||||
| #include "kinetis.h" | |||||
| #ifdef __cplusplus | |||||
| extern "C" { | |||||
| #endif | |||||
| class IntervalTimer { | |||||
| 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); | |||||
| }; | |||||
| #ifdef __cplusplus | |||||
| } | |||||
| #endif | |||||
| #endif |
| // empty Keyboard.h file, for compability with Arduino's Keyboard examples | |||||
| // This header file is in the public domain. |
| #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 |
| # 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 ?= ../../../../.. | |||||
| endif | |||||
| # configurable options | |||||
| OPTIONS = -DF_CPU=48000000 -DUSB_SERIAL -DLAYOUT_US_ENGLISH -DUSING_MAKEFILE | |||||
| # options needed by many Arduino libraries to configure for Teensy 3.x | |||||
| OPTIONS += -D__$(MCU)__ -DARDUINO=10805 -DTEENSYDUINO=144 | |||||
| # use "cortex-m4" for Teensy 3.x | |||||
| # use "cortex-m0plus" for Teensy LC | |||||
| CPUARCH = cortex-m4 | |||||
| #CPUARCH = cortex-m0plus | |||||
| # Other Makefiles and project templates for Teensy 3.x: | |||||
| # | |||||
| # https://github.com/apmorton/teensy-template | |||||
| # https://github.com/xxxajk/Arduino_Makefile_master | |||||
| # https://github.com/JonHylands/uCee | |||||
| #************************************************************************ | |||||
| # Location of Teensyduino utilities, Toolchain, and Arduino Libraries. | |||||
| # To use this makefile without Arduino, copy the resources from these | |||||
| # locations and edit the pathnames. The rest of Arduino is not needed. | |||||
| #************************************************************************ | |||||
| 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 = $(abspath $(ARDUINOPATH)/libraries) | |||||
| # path location for the arm-none-eabi compiler | |||||
| 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=$(CPUARCH) -mthumb -MMD $(OPTIONS) -I. | |||||
| # compiler options for C++ only | |||||
| CXXFLAGS = -std=gnu++14 -felide-constructors -fno-exceptions -fno-rtti | |||||
| # compiler options for C only | |||||
| CFLAGS = | |||||
| # linker options | |||||
| LDFLAGS = -Os -Wl,--gc-sections,--defsym=__rtc_localtime=0 --specs=nano.specs -mcpu=$(CPUARCH) -mthumb -T$(MCU_LD) | |||||
| # additional libraries to link | |||||
| LIBS = -lm | |||||
| # names for the compiler programs | |||||
| 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... | |||||
| C_FILES := $(wildcard *.c) | |||||
| CPP_FILES := $(wildcard *.cpp) | |||||
| OBJS := $(C_FILES:.c=.o) $(CPP_FILES:.cpp=.o) | |||||
| # the actual makefile rules (all .o files built by GNU make's default implicit rules) | |||||
| all: $(TARGET).hex | |||||
| $(TARGET).elf: $(OBJS) $(MCU_LD) | |||||
| $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) | |||||
| %.hex: %.elf | |||||
| $(SIZE) $< | |||||
| $(OBJCOPY) -O ihex -R .eeprom $< $@ | |||||
| 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 |
| // empty Mouse.h file, for compability with Arduino's Mouse examples | |||||
| // This header file is in the public domain. |
| /* 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. | |||||
| */ | |||||
| // Long ago this file contained code from Arduino.cc, which was | |||||
| // Copyright (c) 2008 David A. Mellis. No substantial portion of | |||||
| // Arduino's original code remains. In fact, several improvements | |||||
| // developed for Teensyduino have made their way back into | |||||
| // Arduino's code base. :-) | |||||
| #include <Arduino.h> | |||||
| size_t Print::write(const uint8_t *buffer, size_t size) | |||||
| { | |||||
| if (buffer == nullptr) return 0; | |||||
| size_t count = 0; | |||||
| while (size--) count += write(*buffer++); | |||||
| return count; | |||||
| } | |||||
| size_t Print::print(const String &s) | |||||
| { | |||||
| uint8_t buffer[33]; | |||||
| size_t count = 0; | |||||
| unsigned int index = 0; | |||||
| unsigned int len = s.length(); | |||||
| while (len > 0) { | |||||
| s.getBytes(buffer, sizeof(buffer), index); | |||||
| unsigned int nbytes = len; | |||||
| if (nbytes > sizeof(buffer)-1) nbytes = sizeof(buffer)-1; | |||||
| index += nbytes; | |||||
| len -= nbytes; | |||||
| count += write(buffer, nbytes); | |||||
| } | |||||
| return count; | |||||
| } | |||||
| size_t Print::print(long n) | |||||
| { | |||||
| uint8_t sign=0; | |||||
| if (n < 0) { | |||||
| sign = '-'; | |||||
| n = -n; | |||||
| } | |||||
| return printNumber(n, 10, sign); | |||||
| } | |||||
| size_t Print::println(void) | |||||
| { | |||||
| uint8_t buf[2]={'\r', '\n'}; | |||||
| return write(buf, 2); | |||||
| } | |||||
| extern "C" { | |||||
| __attribute__((weak)) | |||||
| int _write(int file, char *ptr, int len) | |||||
| { | |||||
| ((class Print *)file)->write((uint8_t *)ptr, len); | |||||
| return len; | |||||
| } | |||||
| } | |||||
| 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) | |||||
| { | |||||
| uint8_t buf[34]; | |||||
| uint8_t digit, i; | |||||
| // TODO: make these checks as inline, since base is | |||||
| // almost always a constant. base = 0 (BYTE) should | |||||
| // inline as a call directly to write() | |||||
| if (base == 0) { | |||||
| return write((uint8_t)n); | |||||
| } else if (base == 1) { | |||||
| base = 10; | |||||
| } | |||||
| if (n == 0) { | |||||
| buf[sizeof(buf) - 1] = '0'; | |||||
| i = sizeof(buf) - 1; | |||||
| } else { | |||||
| i = sizeof(buf) - 1; | |||||
| while (1) { | |||||
| digit = n % base; | |||||
| buf[i] = ((digit < 10) ? '0' + digit : 'A' + digit - 10); | |||||
| n /= base; | |||||
| if (n == 0) break; | |||||
| i--; | |||||
| } | |||||
| } | |||||
| if (sign) { | |||||
| i--; | |||||
| buf[i] = '-'; | |||||
| } | |||||
| return write(buf + i, sizeof(buf) - i); | |||||
| } | |||||
| #endif | |||||
| size_t Print::print(int64_t n) | |||||
| { | |||||
| if (n < 0) return printNumber64(-n, 10, 1); | |||||
| return printNumber64(n, 10, 0); | |||||
| } | |||||
| size_t Print::printNumber64(uint64_t n, uint8_t base, uint8_t sign) | |||||
| { | |||||
| uint8_t buf[66]; | |||||
| uint8_t digit, i; | |||||
| if (base < 2) return 0; | |||||
| if (n == 0) { | |||||
| buf[sizeof(buf) - 1] = '0'; | |||||
| i = sizeof(buf) - 1; | |||||
| } else { | |||||
| i = sizeof(buf) - 1; | |||||
| while (1) { | |||||
| digit = n % base; | |||||
| buf[i] = ((digit < 10) ? '0' + digit : 'A' + digit - 10); | |||||
| n /= base; | |||||
| if (n == 0) break; | |||||
| i--; | |||||
| } | |||||
| } | |||||
| if (sign) { | |||||
| i--; | |||||
| buf[i] = '-'; | |||||
| } | |||||
| return write(buf + i, sizeof(buf) - i); | |||||
| } | |||||
| size_t Print::printFloat(double number, uint8_t digits) | |||||
| { | |||||
| uint8_t sign=0; | |||||
| 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; | |||||
| number = -number; | |||||
| } | |||||
| // Round correctly so that print(1.999, 2) prints as "2.00" | |||||
| double rounding = 0.5; | |||||
| for (uint8_t i=0; i<digits; ++i) { | |||||
| rounding *= 0.1; | |||||
| } | |||||
| number += rounding; | |||||
| // Extract the integer part of the number and print it | |||||
| unsigned long int_part = (unsigned long)number; | |||||
| double remainder = number - (double)int_part; | |||||
| count += printNumber(int_part, 10, sign); | |||||
| // Print the decimal point, but only if there are digits beyond | |||||
| if (digits > 0) { | |||||
| uint8_t n, buf[16], count=1; | |||||
| buf[0] = '.'; | |||||
| // Extract digits from the remainder one at a time | |||||
| if (digits > sizeof(buf) - 1) digits = sizeof(buf) - 1; | |||||
| while (digits-- > 0) { | |||||
| remainder *= 10.0; | |||||
| n = (uint8_t)(remainder); | |||||
| buf[count++] = '0' + n; | |||||
| remainder -= n; | |||||
| } | |||||
| count += write(buf, count); | |||||
| } | |||||
| return count; | |||||
| } | |||||
| /* 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 Print_h | |||||
| #define Print_h | |||||
| #include <inttypes.h> | |||||
| #include <stdio.h> // for size_t - gives sprintf and other stuff to all sketches & libs | |||||
| #include <stdarg.h> | |||||
| #include "core_id.h" | |||||
| #include "WString.h" | |||||
| #include "Printable.h" | |||||
| #define DEC 10 | |||||
| #define HEX 16 | |||||
| #define OCT 8 | |||||
| #define BIN 2 | |||||
| // 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: | |||||
| 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); } | |||||
| size_t print(const char s[]) { return write(s); } | |||||
| size_t print(const __FlashStringHelper *f) { return write((const char *)f); } | |||||
| size_t print(uint8_t b) { return printNumber(b, 10, 0); } | |||||
| size_t print(int n) { return print((long)n); } | |||||
| size_t print(unsigned int n) { return printNumber(n, 10, 0); } | |||||
| size_t print(long n); | |||||
| size_t print(unsigned long n) { return printNumber(n, 10, 0); } | |||||
| size_t print(int64_t n); | |||||
| size_t print(uint64_t n) { return printNumber64(n, 10, 0); } | |||||
| size_t print(unsigned char n, int base) { return printNumber(n, base, 0); } | |||||
| size_t print(int n, int base) { return (base == 10) ? print(n) : printNumber(n, base, 0); } | |||||
| size_t print(unsigned int n, int base) { return printNumber(n, base, 0); } | |||||
| size_t print(long n, int base) { return (base == 10) ? print(n) : printNumber(n, base, 0); } | |||||
| size_t print(unsigned long n, int base) { return printNumber(n, base, 0); } | |||||
| size_t print(int64_t n, int base) { return (base == 10) ? print(n) : printNumber64(n, base, 0); } | |||||
| size_t print(uint64_t n, int base) { return printNumber64(n, base, 0); } | |||||
| size_t print(double n, int digits = 2) { return printFloat(n, digits); } | |||||
| size_t print(const Printable &obj) { return obj.printTo(*this); } | |||||
| size_t println(void); | |||||
| size_t println(const String &s) { return print(s) + println(); } | |||||
| size_t println(char c) { return print(c) + println(); } | |||||
| size_t println(const char s[]) { return print(s) + println(); } | |||||
| size_t println(const __FlashStringHelper *f) { return print(f) + println(); } | |||||
| size_t println(uint8_t b) { return print(b) + println(); } | |||||
| size_t println(int n) { return print(n) + println(); } | |||||
| size_t println(unsigned int n) { return print(n) + println(); } | |||||
| size_t println(long n) { return print(n) + println(); } | |||||
| size_t println(unsigned long n) { return print(n) + println(); } | |||||
| size_t println(int64_t n) { return print(n) + println(); } | |||||
| size_t println(uint64_t n) { return print(n) + println(); } | |||||
| size_t println(unsigned char n, int base) { return print(n, base) + println(); } | |||||
| size_t println(int n, int base) { return print(n, base) + println(); } | |||||
| size_t println(unsigned int n, int base) { return print(n, base) + println(); } | |||||
| size_t println(long n, int base) { return print(n, base) + println(); } | |||||
| size_t println(unsigned long n, int base) { return print(n, base) + println(); } | |||||
| size_t println(int64_t n, int base) { return print(n, base) + println(); } | |||||
| size_t println(uint64_t n, int base) { return print(n, base) + println(); } | |||||
| size_t println(double n, int digits = 2) { return print(n, digits) + println(); } | |||||
| size_t println(const Printable &obj) { return obj.printTo(*this) + println(); } | |||||
| int getWriteError() { return write_error; } | |||||
| void clearWriteError() { setWriteError(0); } | |||||
| // format warnings are too pedantic - disable until newer toolchain offers better... | |||||
| // https://forum.pjrc.com/threads/62473?p=256873&viewfull=1#post256873 | |||||
| int printf(const char *format, ...) /*__attribute__ ((format (printf, 2, 3)))*/; | |||||
| int printf(const __FlashStringHelper *format, ...); | |||||
| protected: | |||||
| void setWriteError(int err = 1) { write_error = err; } | |||||
| 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 | |||||
| size_t printNumber64(uint64_t n, uint8_t base, uint8_t sign); | |||||
| }; | |||||
| #endif |
| /* | |||||
| Printable.h - Interface class that allows printing of complex types | |||||
| 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 | |||||
| */ | |||||
| #ifndef Printable_h | |||||
| #define Printable_h | |||||
| #ifdef __cplusplus | |||||
| #include "new.h" | |||||
| class Print; | |||||
| /** The Printable class provides a way for new classes to allow themselves to be printed. | |||||
| By deriving from Printable and implementing the printTo method, it will then be possible | |||||
| for users to print out instances of this class by passing them into the usual | |||||
| Print::print and Print::println methods. | |||||
| */ | |||||
| class Printable | |||||
| { | |||||
| public: | |||||
| virtual size_t printTo(Print& p) const = 0; | |||||
| }; | |||||
| #endif | |||||
| #endif |
| /* 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" | |||||
| #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 | |||||
| #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(60 / 5) * ((1+1)/2) | |||||
| #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1)) //(60 / 2) * ((1+0)/4) = 7.5 MHz | |||||
| #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(0)) //(60 / 5) * ((1+0)/2) | |||||
| #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(2) | SPI_CTAR_DBR) //(60 / 5) * ((1+1)/6) | |||||
| #elif F_BUS == 56000000 | |||||
| #define HAS_SPIFIFO | |||||
| #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(56 / 3) * ((1+1)/2) = 18.67 | |||||
| #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(56 / 2) * ((1+0)/2) = 14 | |||||
| #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(56 / 5) * ((1+1)/2) = 11.2 | |||||
| #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(56 / 7) * ((1+1)/2) | |||||
| #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(0)) //(56 / 5) * ((1+0)/2) | |||||
| #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(0)) //(56 / 7) * ((1+0)/2) | |||||
| #elif F_BUS == 48000000 | |||||
| #define HAS_SPIFIFO | |||||
| #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(48 / 2) * ((1+1)/2) | |||||
| #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(48 / 3) * ((1+1)/2) | |||||
| #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(48 / 2) * ((1+0)/2) | |||||
| #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2) | SPI_CTAR_DBR) //(48 / 2) * ((1+1)/6) | |||||
| #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1)) //(48 / 2) * ((1+0)/4) | |||||
| #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2)) //(48 / 2) * ((1+0)/6) | |||||
| #elif F_BUS == 40000000 | |||||
| #define HAS_SPIFIFO | |||||
| #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(40 / 2) * ((1+1)/2) = 20 | |||||
| #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(40 / 3) * ((1+1)/2) = 13.33 | |||||
| #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(40 / 2) * ((1+0)/2) = 10 | |||||
| #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(40 / 5) * ((1+1)/2) | |||||
| #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(3) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(40 / 7) * ((1+1)/2) = 5.71 | |||||
| #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(1)) //(40 / 5) * ((1+0)/2) | |||||
| #elif F_BUS == 36000000 | |||||
| #define HAS_SPIFIFO | |||||
| #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(36 / 2) * ((1+1)/2) = 18 | |||||
| #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(36 / 3) * ((1+1)/2) = 12 | |||||
| #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(36 / 3) * ((1+1)/2) = 12 | |||||
| #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(36 / 5) * ((1+1)/2) = 7.2 | |||||
| #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2) | SPI_CTAR_DBR) //(36 / 2) * ((1+1)/6) | |||||
| #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(2) | SPI_CTAR_DBR) //(36 / 3) * ((1+1)/6) | |||||
| #elif F_BUS == 24000000 | |||||
| #define HAS_SPIFIFO | |||||
| #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(24 / 2) * ((1+1)/2) 12 MHz | |||||
| #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(24 / 2) * ((1+1)/2) 12 MHz | |||||
| #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(24 / 2) * ((1+1)/2) | |||||
| #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(24 / 3) * ((1+1)/2) | |||||
| #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0)) //(24 / 2) * ((1+0)/2) | |||||
| #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(2) | SPI_CTAR_DBR) //(24 / 2) * ((1+1)/6) | |||||
| #elif F_BUS == 16000000 | |||||
| #define HAS_SPIFIFO | |||||
| #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_DBR) //(16 / 2) * ((1+1)/8) = 2 MHz | |||||
| #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_DBR) //(16 / 2) * ((1+1)/8) = 2 MHz | |||||
| #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_DBR) //(16 / 2) * ((1+1)/8) = 2 MHz | |||||
| #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_DBR) //(16 / 2) * ((1+1)/8) = 2 MHz | |||||
| #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_DBR) //(16 / 2) * ((1+1)/8) = 2 MHz | |||||
| #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_DBR) //(16 / 2) * ((1+1)/8) = 2 MHz | |||||
| #elif F_BUS == 8000000 | |||||
| #define HAS_SPIFIFO | |||||
| #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(8 / 2) * ((1+1)/4) = 2 MHz | |||||
| #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(8 / 2) * ((1+1)/4) = 2 MHz | |||||
| #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(8 / 2) * ((1+1)/4) = 2 MHz | |||||
| #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(8 / 2) * ((1+1)/4) = 2 MHz | |||||
| #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(8 / 2) * ((1+1)/4) = 2 MHz | |||||
| #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_DBR) //(8 / 2) * ((1+1)/4) = 2 MHz | |||||
| #elif F_BUS == 4000000 | |||||
| #define HAS_SPIFIFO | |||||
| #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 2 MHz | |||||
| #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 2 MHz | |||||
| #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 2 MHz | |||||
| #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 2 MHz | |||||
| #define SPI_CLOCK_6MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 2 MHz | |||||
| #define SPI_CLOCK_4MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 2 MHz | |||||
| #elif F_BUS == 2000000 | |||||
| #define HAS_SPIFIFO | |||||
| #define SPI_CLOCK_24MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz | |||||
| #define SPI_CLOCK_16MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz | |||||
| #define SPI_CLOCK_12MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz | |||||
| #define SPI_CLOCK_8MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(4 / 2) * ((1+1)/2) = 1 MHz | |||||
| #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 // F_BUS | |||||
| #endif // KINETISK | |||||
| /* | |||||
| #! /usr/bin/perl | |||||
| $clock = 60; | |||||
| for $i (2, 3, 5, 7) { | |||||
| for $j (0, 1) { | |||||
| for $k (2, 4, 6, 8, 16, 32) { | |||||
| $out = $clock / $i * (1 + $j) / $k; | |||||
| printf "%0.2f : ", $out; | |||||
| print "$clock / $i * (1 + $j) / $k = $out\n"; | |||||
| } | |||||
| } | |||||
| } | |||||
| */ | |||||
| // sck = F_BUS / PBR * ((1+DBR)/BR) | |||||
| // PBR = 2, 3, 5, 7 | |||||
| // DBR = 0, 1 -- zero preferred | |||||
| // BR = 2, 4, 6, 8, 16, 32, 64, 128, 256, 512 | |||||
| #ifdef HAS_SPIFIFO | |||||
| #ifndef SPI_MODE0 | |||||
| #define SPI_MODE0 0x00 // CPOL = 0, CPHA = 0 | |||||
| #define SPI_MODE1 0x04 // CPOL = 0, CPHA = 1 | |||||
| #define SPI_MODE2 0x08 // CPOL = 1, CPHA = 0 | |||||
| #define SPI_MODE3 0x0C // CPOL = 1, CPHA = 1 | |||||
| #endif | |||||
| #define SPI_CONTINUE 1 | |||||
| class SPIFIFOclass | |||||
| { | |||||
| public: | |||||
| 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; | |||||
| 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; | |||||
| ctar |= (ctar & 0x0F) << 8; | |||||
| } else { | |||||
| ctar |= (ctar & 0x0F) << 12; | |||||
| } | |||||
| 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; | |||||
| } else if (pin == 2) { // PTD0 | |||||
| CORE_PIN2_CONFIG = PORT_PCR_MUX(2); | |||||
| p = 0x01; | |||||
| } else if (pin == 9) { // PTC3 | |||||
| CORE_PIN9_CONFIG = PORT_PCR_MUX(2); | |||||
| p = 0x02; | |||||
| } else if (pin == 6) { // PTD4 | |||||
| CORE_PIN6_CONFIG = PORT_PCR_MUX(2); | |||||
| p = 0x02; | |||||
| } else if (pin == 20) { // PTD5 | |||||
| CORE_PIN20_CONFIG = PORT_PCR_MUX(2); | |||||
| p = 0x04; | |||||
| } else if (pin == 23) { // PTC2 | |||||
| CORE_PIN23_CONFIG = PORT_PCR_MUX(2); | |||||
| p = 0x04; | |||||
| } else if (pin == 21) { // PTD6 | |||||
| CORE_PIN21_CONFIG = PORT_PCR_MUX(2); | |||||
| p = 0x08; | |||||
| } else if (pin == 22) { // PTC1 | |||||
| CORE_PIN22_CONFIG = PORT_PCR_MUX(2); | |||||
| p = 0x08; | |||||
| } else if (pin == 15) { // PTC0 | |||||
| CORE_PIN15_CONFIG = PORT_PCR_MUX(2); | |||||
| p = 0x10; | |||||
| #if defined(__MK64FX512__) || defined(__MK66FX1M0__) | |||||
| } else if (pin == 26) { | |||||
| CORE_PIN26_CONFIG = PORT_PCR_MUX(2); | |||||
| p = 0x01; | |||||
| #endif | |||||
| } else { | |||||
| reg = portOutputRegister(pin); | |||||
| pinMode(pin, OUTPUT); | |||||
| *reg = 1; | |||||
| p = 0; | |||||
| } | |||||
| pcs = p; | |||||
| clear(); | |||||
| SPCR.enable_pins(); | |||||
| } | |||||
| inline void write(uint32_t b, uint32_t cont=0) __attribute__((always_inline)) { | |||||
| uint32_t pcsbits = pcs << 16; | |||||
| if (pcsbits) { | |||||
| 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; | |||||
| KINETISK_SPI0.SR = SPI_SR_EOQF; | |||||
| KINETISK_SPI0.PUSHR = (b & 0xFF) | (cont ? 0 : SPI_PUSHR_EOQ); | |||||
| if (cont) { | |||||
| while (((KINETISK_SPI0.SR) & (15 << 12)) > (3 << 12)) ; | |||||
| } else { | |||||
| while (!(KINETISK_SPI0.SR & SPI_SR_EOQF)) ; | |||||
| *reg = 1; | |||||
| } | |||||
| } | |||||
| } | |||||
| inline void write16(uint32_t b, uint32_t cont=0) __attribute__((always_inline)) { | |||||
| uint32_t pcsbits = pcs << 16; | |||||
| if (pcsbits) { | |||||
| KINETISK_SPI0.PUSHR = (b & 0xFFFF) | (pcs << 16) | | |||||
| (cont ? SPI_PUSHR_CONT : 0) | SPI_PUSHR_CTAS(1); | |||||
| while (((KINETISK_SPI0.SR) & (15 << 12)) > (3 << 12)) ; | |||||
| } else { | |||||
| *reg = 0; | |||||
| KINETISK_SPI0.SR = SPI_SR_EOQF; | |||||
| KINETISK_SPI0.PUSHR = (b & 0xFFFF) | (cont ? 0 : SPI_PUSHR_EOQ) | SPI_PUSHR_CTAS(1); | |||||
| if (cont) { | |||||
| while (((KINETISK_SPI0.SR) & (15 << 12)) > (3 << 12)) ; | |||||
| } else { | |||||
| while (!(KINETISK_SPI0.SR & SPI_SR_EOQF)) ; | |||||
| *reg = 1; | |||||
| } | |||||
| } | |||||
| } | |||||
| inline uint32_t read(void) __attribute__((always_inline)) { | |||||
| while ((KINETISK_SPI0.SR & (15 << 4)) == 0) ; // TODO, could wait forever | |||||
| return KINETISK_SPI0.POPR; | |||||
| } | |||||
| inline void clear(void) __attribute__((always_inline)) { | |||||
| KINETISK_SPI0.MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F) | SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF; | |||||
| } | |||||
| private: | |||||
| static uint8_t pcs; | |||||
| static volatile uint8_t *reg; | |||||
| }; | |||||
| extern SPIFIFOclass SPIFIFO; | |||||
| #endif // HAS_SPIFIFO | |||||
| #endif |
| /* | |||||
| 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; | |||||
| }; | |||||
| #endif | |||||
| #endif |
| /* | |||||
| 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); | |||||
| 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.1; | |||||
| } | |||||
| 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 | |||||
| } | |||||
| 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; | |||||
| } |
| /* | |||||
| Stream.h - base class for character-based streams. | |||||
| Copyright (c) 2010 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 | |||||
| */ | |||||
| #ifndef Stream_h | |||||
| #define Stream_h | |||||
| #include <inttypes.h> | |||||
| #include "Print.h" | |||||
| class Stream : public Print | |||||
| { | |||||
| public: | |||||
| 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); } | |||||
| protected: | |||||
| void setReadError(int err = 1) { read_error = err; } | |||||
| unsigned long _timeout; | |||||
| private: | |||||
| char read_error; | |||||
| int timedRead(); | |||||
| int timedPeek(); | |||||
| int peekNextDigit(); | |||||
| }; | |||||
| #endif |
| /* 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> | |||||
| // 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 | |||||
| // changed to allow multiple simultaneous tones. | |||||
| static uint32_t tone_toggle_count; | |||||
| static volatile uint8_t *tone_reg; | |||||
| static uint8_t tone_pin=255; | |||||
| 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; | |||||
| volatile uint32_t *config; | |||||
| float usec; | |||||
| if (pin >= CORE_NUM_DIGITAL) return; | |||||
| if (duration) { | |||||
| count = (frequency * duration / 1000) * 2; | |||||
| if (!(count & 1)) count++; // always full waveform cycles | |||||
| } else { | |||||
| count = 0xFFFFFFFD; | |||||
| } | |||||
| if (frequency < 1) frequency = 1; // minimum is 1 Hz | |||||
| usec = (float)500000.0 / (float)frequency; | |||||
| config = portConfigRegister(pin); | |||||
| // TODO: IntervalTimer really needs an API to disable and enable | |||||
| // the interrupt on a single timer. | |||||
| __disable_irq(); | |||||
| if (pin == tone_pin) { | |||||
| // 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 { | |||||
| // 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_CLEAR_PIN; // clear pin | |||||
| } | |||||
| // configure the new tone to play | |||||
| tone_pin = pin; | |||||
| tone_reg = portClearRegister(pin); | |||||
| #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(); | |||||
| } | |||||
| void tone_interrupt(void) | |||||
| { | |||||
| 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 { | |||||
| // 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; | |||||
| } | |||||
| } | |||||
| } | |||||
| void noTone(uint8_t pin) | |||||
| { | |||||
| if (pin >= CORE_NUM_DIGITAL) return; | |||||
| __disable_irq(); | |||||
| if (pin == tone_pin) { | |||||
| tone_timer.end(); | |||||
| TONE_CLEAR_PIN; // clear | |||||
| tone_pin = 255; | |||||
| } | |||||
| __enable_irq(); | |||||
| } | |||||
| /* | |||||
| * Udp.cpp: Library to send/receive UDP packets. | |||||
| * | |||||
| * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these) | |||||
| * 1) UDP does not guarantee the order in which assembled UDP packets are received. This | |||||
| * might not happen often in practice, but in larger network topologies, a UDP | |||||
| * packet can be received out of sequence. | |||||
| * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being | |||||
| * aware of it. Again, this may not be a concern in practice on small local networks. | |||||
| * For more information, see http://www.cafeaulait.org/course/week12/35.html | |||||
| * | |||||
| * MIT License: | |||||
| * Copyright (c) 2008 Bjoern Hartmann | |||||
| * 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. | |||||
| * | |||||
| * bjoern@cs.stanford.edu 12/30/2008 | |||||
| */ | |||||
| #if ARDUINO >= 100 | |||||
| #ifndef udp_h | |||||
| #define udp_h | |||||
| #include <Stream.h> | |||||
| #include <IPAddress.h> | |||||
| 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 | |||||
| // Start building up a packet to send to the remote host specific in ip and port | |||||
| // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port | |||||
| virtual int beginPacket(IPAddress ip, uint16_t port) =0; | |||||
| // Start building up a packet to send to the remote host specific in host and port | |||||
| // Returns 1 if successful, 0 if there was a problem resolving the hostname or port | |||||
| virtual int beginPacket(const char *host, uint16_t port) =0; | |||||
| // Finish off this packet and send it | |||||
| // Returns 1 if the packet was sent successfully, 0 if there was an error | |||||
| virtual int endPacket() =0; | |||||
| // Write a single byte into the packet | |||||
| virtual size_t write(uint8_t) =0; | |||||
| // Write size bytes from buffer into the packet | |||||
| virtual size_t write(const uint8_t *buffer, size_t size) =0; | |||||
| // Start processing the next available incoming packet | |||||
| // Returns the size of the packet in bytes, or 0 if no packets are available | |||||
| virtual int parsePacket() =0; | |||||
| // Number of bytes remaining in the current packet | |||||
| virtual int available() =0; | |||||
| // Read a single byte from the current packet | |||||
| virtual int read() =0; | |||||
| // Read up to len bytes from the current packet and place them into buffer | |||||
| // Returns the number of bytes read, or 0 if none are available | |||||
| virtual int read(unsigned char* buffer, size_t len) =0; | |||||
| // Read up to len characters from the current packet and place them into buffer | |||||
| // Returns the number of characters read, or 0 if none are available | |||||
| virtual int read(char* buffer, size_t len) =0; | |||||
| // Return the next byte from the current packet without moving on to the next byte | |||||
| virtual int peek() =0; | |||||
| virtual void flush() =0; // Finish reading the current packet | |||||
| // Return the IP address of the host who sent the current incoming packet | |||||
| virtual IPAddress remoteIP() =0; | |||||
| // Return the port of the host who sent the current incoming packet | |||||
| virtual uint16_t remotePort() =0; | |||||
| protected: | |||||
| uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; | |||||
| }; | |||||
| #endif | |||||
| #endif |
| /* | |||||
| 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 | |||||
| */ | |||||
| #ifndef Character_h | |||||
| #define Character_h | |||||
| #include <ctype.h> | |||||
| // WCharacter.h prototypes | |||||
| inline boolean isAlphaNumeric(int c) __attribute__((always_inline)); | |||||
| inline boolean isAlpha(int c) __attribute__((always_inline)); | |||||
| inline boolean isAscii(int c) __attribute__((always_inline)); | |||||
| inline boolean isWhitespace(int c) __attribute__((always_inline)); | |||||
| inline boolean isControl(int c) __attribute__((always_inline)); | |||||
| inline boolean isDigit(int c) __attribute__((always_inline)); | |||||
| inline boolean isGraph(int c) __attribute__((always_inline)); | |||||
| inline boolean isLowerCase(int c) __attribute__((always_inline)); | |||||
| inline boolean isPrintable(int c) __attribute__((always_inline)); | |||||
| inline boolean isPunct(int c) __attribute__((always_inline)); | |||||
| inline boolean isSpace(int c) __attribute__((always_inline)); | |||||
| inline boolean isUpperCase(int c) __attribute__((always_inline)); | |||||
| inline boolean isHexadecimalDigit(int c) __attribute__((always_inline)); | |||||
| inline int toAscii(int c) __attribute__((always_inline)); | |||||
| inline int toLowerCase(int c) __attribute__((always_inline)); | |||||
| inline int toUpperCase(int c)__attribute__((always_inline)); | |||||
| // Checks for an alphanumeric character. | |||||
| // It is equivalent to (isalpha(c) || isdigit(c)). | |||||
| inline boolean isAlphaNumeric(int c) | |||||
| { | |||||
| return ( isalnum(c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for an alphabetic character. | |||||
| // It is equivalent to (isupper(c) || islower(c)). | |||||
| inline boolean isAlpha(int c) | |||||
| { | |||||
| return ( isalpha(c) == 0 ? false : true); | |||||
| } | |||||
| // Checks whether c is a 7-bit unsigned char value | |||||
| // that fits into the ASCII character set. | |||||
| inline boolean isAscii(int c) | |||||
| { | |||||
| return ((c & ~0x7F) != 0 ? false : true); | |||||
| } | |||||
| // Checks for a blank character, that is, a space or a tab. | |||||
| inline boolean isWhitespace(int c) | |||||
| { | |||||
| return ( isblank (c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for a control character. | |||||
| inline boolean isControl(int c) | |||||
| { | |||||
| return ( iscntrl (c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for a digit (0 through 9). | |||||
| inline boolean isDigit(int c) | |||||
| { | |||||
| return ( isdigit (c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for any printable character except space. | |||||
| inline boolean isGraph(int c) | |||||
| { | |||||
| return ( isgraph (c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for a lower-case character. | |||||
| inline boolean isLowerCase(int c) | |||||
| { | |||||
| return (islower (c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for any printable character including space. | |||||
| inline boolean isPrintable(int c) | |||||
| { | |||||
| return ( isprint (c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for any printable character which is not a space | |||||
| // or an alphanumeric character. | |||||
| inline boolean isPunct(int c) | |||||
| { | |||||
| return ( ispunct (c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for white-space characters. For the avr-libc library, | |||||
| // these are: space, formfeed ('\f'), newline ('\n'), carriage | |||||
| // return ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). | |||||
| inline boolean isSpace(int c) | |||||
| { | |||||
| return ( isspace (c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for an uppercase letter. | |||||
| inline boolean isUpperCase(int c) | |||||
| { | |||||
| return ( isupper (c) == 0 ? false : true); | |||||
| } | |||||
| // Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7 | |||||
| // 8 9 a b c d e f A B C D E F. | |||||
| inline boolean isHexadecimalDigit(int c) | |||||
| { | |||||
| return ( isxdigit (c) == 0 ? false : true); | |||||
| } | |||||
| // Converts c to a 7-bit unsigned char value that fits into the | |||||
| // ASCII character set, by clearing the high-order bits. | |||||
| inline int toAscii(int c) | |||||
| { | |||||
| return (c & 0x7F); | |||||
| } | |||||
| // Warning: | |||||
| // Many people will be unhappy if you use this function. | |||||
| // This function will convert accented letters into random | |||||
| // characters. | |||||
| // Converts the letter c to lower case, if possible. | |||||
| inline int toLowerCase(int c) | |||||
| { | |||||
| return tolower (c); | |||||
| } | |||||
| // Converts the letter c to upper case, if possible. | |||||
| inline int toUpperCase(int c) | |||||
| { | |||||
| return toupper (c); | |||||
| } | |||||
| #endif |
| // This header file is in the public domain. | |||||
| #include "wiring.h" |
| /* | |||||
| 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; | |||||
| void randomSeed(uint32_t newseed) | |||||
| { | |||||
| if (newseed > 0) seed = newseed; | |||||
| } | |||||
| void srandom(unsigned int newseed) | |||||
| { | |||||
| seed = newseed; | |||||
| } | |||||
| int32_t random(void) | |||||
| { | |||||
| int32_t hi, lo, x; | |||||
| // the algorithm used in avr-libc 1.6.4 | |||||
| x = seed; | |||||
| if (x == 0) x = 123459876; | |||||
| hi = x / 127773; | |||||
| lo = x % 127773; | |||||
| x = 16807 * lo - 2836 * hi; | |||||
| if (x < 0) x += 0x7FFFFFFF; | |||||
| seed = x; | |||||
| return x; | |||||
| } | |||||
| uint32_t random(uint32_t howbig) | |||||
| { | |||||
| if (howbig == 0) return 0; | |||||
| return random() % howbig; | |||||
| } | |||||
| int32_t random(int32_t howsmall, int32_t howbig) | |||||
| { | |||||
| if (howsmall >= howbig) return howsmall; | |||||
| int32_t diff = howbig - howsmall; | |||||
| return random(diff) + howsmall; | |||||
| } | |||||
| unsigned int makeWord(unsigned int w) { return w; } | |||||
| unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; } | |||||
| /* 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 | |||||
| #include <stdlib.h> | |||||
| #include <string.h> | |||||
| #include <math.h> | |||||
| // some libraries and sketches depend on this | |||||
| // AVR stuff, assuming Arduino.h or WProgram.h | |||||
| // automatically includes it... | |||||
| #include <avr/pgmspace.h> | |||||
| #include <avr/interrupt.h> | |||||
| #include "avr_functions.h" | |||||
| #include "wiring.h" | |||||
| #include "HardwareSerial.h" | |||||
| #define DMAMEM __attribute__ ((section(".dmabuffers"), used)) | |||||
| #define FASTRUN __attribute__ ((section(".fastrun"), noinline, noclone )) | |||||
| #ifdef __cplusplus | |||||
| #include "avr_emulation.h" | |||||
| #include "usb_serial.h" | |||||
| #include "usb_serial2.h" | |||||
| #include "usb_serial3.h" | |||||
| #include "usb_seremu.h" | |||||
| #include "usb_keyboard.h" | |||||
| #include "usb_mouse.h" | |||||
| #include "usb_joystick.h" | |||||
| #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 "WString.h" | |||||
| #include "elapsedMillis.h" | |||||
| #include "IntervalTimer.h" | |||||
| uint16_t makeWord(uint16_t w); | |||||
| uint16_t makeWord(byte h, byte l); | |||||
| #define word(...) makeWord(__VA_ARGS__) | |||||
| unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L); | |||||
| void tone(uint8_t pin, uint16_t frequency, uint32_t duration = 0); | |||||
| void noTone(uint8_t pin); | |||||
| // WMath prototypes | |||||
| 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(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 |
| /* | |||||
| WString.cpp - String library for Wiring & Arduino | |||||
| ...mostly rewritten by Paul Stoffregen... | |||||
| Copyright (c) 2009-10 Hernando Barragan. All rights reserved. | |||||
| Copyright 2011, 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 | |||||
| */ | |||||
| #include <Arduino.h> | |||||
| /*********************************************/ | |||||
| /* Constructors */ | |||||
| /*********************************************/ | |||||
| String::String(const char *cstr) | |||||
| { | |||||
| init(); | |||||
| if (cstr) copy(cstr, strlen(cstr)); | |||||
| } | |||||
| String::String(const __FlashStringHelper *pgmstr) | |||||
| { | |||||
| init(); | |||||
| *this = pgmstr; | |||||
| } | |||||
| String::String(const String &value) | |||||
| { | |||||
| init(); | |||||
| *this = value; | |||||
| } | |||||
| #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) | |||||
| String::String(String &&rval) | |||||
| { | |||||
| init(); | |||||
| move(rval); | |||||
| } | |||||
| String::String(StringSumHelper &&rval) | |||||
| { | |||||
| init(); | |||||
| move(rval); | |||||
| } | |||||
| #endif | |||||
| String::String(char c) | |||||
| { | |||||
| init(); | |||||
| *this = c; | |||||
| } | |||||
| String::String(unsigned char c) | |||||
| { | |||||
| init(); | |||||
| char buf[4]; | |||||
| utoa(c, buf, 10); | |||||
| *this = buf; | |||||
| } | |||||
| String::String(const int value, unsigned char base) | |||||
| { | |||||
| init(); | |||||
| char buf[18]; | |||||
| itoa(value, buf, base); | |||||
| *this = buf; | |||||
| } | |||||
| String::String(unsigned int value, unsigned char base) | |||||
| { | |||||
| init(); | |||||
| char buf[17]; | |||||
| utoa(value, buf, base); | |||||
| *this = buf; | |||||
| } | |||||
| String::String(long value, unsigned char base) | |||||
| { | |||||
| init(); | |||||
| char buf[34]; | |||||
| ltoa(value, buf, base); | |||||
| *this = buf; | |||||
| } | |||||
| String::String(unsigned long value, unsigned char base) | |||||
| { | |||||
| init(); | |||||
| char buf[33]; | |||||
| ultoa(value, buf, base); | |||||
| *this = buf; | |||||
| } | |||||
| String::String(float num, unsigned char digits) | |||||
| { | |||||
| init(); | |||||
| char buf[40]; | |||||
| *this = dtostrf(num, digits + 2, digits, buf); | |||||
| } | |||||
| String::~String() | |||||
| { | |||||
| free(buffer); | |||||
| } | |||||
| /*********************************************/ | |||||
| /* Memory Management */ | |||||
| /*********************************************/ | |||||
| inline void String::init(void) | |||||
| { | |||||
| buffer = NULL; | |||||
| capacity = 0; | |||||
| len = 0; | |||||
| flags = 0; | |||||
| } | |||||
| unsigned char String::reserve(unsigned int size) | |||||
| { | |||||
| if (capacity >= size) return 1; | |||||
| if (changeBuffer(size)) { | |||||
| if (len == 0) buffer[0] = 0; | |||||
| return 1; | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| unsigned char String::changeBuffer(unsigned int maxStrLen) | |||||
| { | |||||
| char *newbuffer = (char *)realloc(buffer, maxStrLen + 1); | |||||
| if (newbuffer) { | |||||
| buffer = newbuffer; | |||||
| capacity = maxStrLen; | |||||
| return 1; | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| /*********************************************/ | |||||
| /* Copy and Move */ | |||||
| /*********************************************/ | |||||
| String & String::copy(const char *cstr, unsigned int length) | |||||
| { | |||||
| if (length == 0) { | |||||
| if (buffer) buffer[0] = 0; | |||||
| len = 0; | |||||
| return *this; | |||||
| } | |||||
| if (!reserve(length)) { | |||||
| if (buffer) { | |||||
| free(buffer); | |||||
| buffer = NULL; | |||||
| } | |||||
| len = capacity = 0; | |||||
| return *this; | |||||
| } | |||||
| len = length; | |||||
| strcpy(buffer, cstr); | |||||
| return *this; | |||||
| } | |||||
| void String::move(String &rhs) | |||||
| { | |||||
| if (buffer) { | |||||
| if (capacity >= rhs.len) { | |||||
| strcpy(buffer, rhs.buffer); | |||||
| len = rhs.len; | |||||
| rhs.len = 0; | |||||
| return; | |||||
| } else { | |||||
| free(buffer); | |||||
| } | |||||
| } | |||||
| buffer = rhs.buffer; | |||||
| capacity = rhs.capacity; | |||||
| len = rhs.len; | |||||
| rhs.buffer = NULL; | |||||
| rhs.capacity = 0; | |||||
| rhs.len = 0; | |||||
| } | |||||
| String & String::operator = (const String &rhs) | |||||
| { | |||||
| if (this == &rhs) return *this; | |||||
| return copy(rhs.buffer, rhs.len); | |||||
| } | |||||
| #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) | |||||
| String & String::operator = (String &&rval) | |||||
| { | |||||
| if (this != &rval) move(rval); | |||||
| return *this; | |||||
| } | |||||
| String & String::operator = (StringSumHelper &&rval) | |||||
| { | |||||
| if (this != &rval) move(rval); | |||||
| return *this; | |||||
| } | |||||
| #endif | |||||
| String & String::operator = (const char *cstr) | |||||
| { | |||||
| if (cstr) { | |||||
| copy(cstr, strlen(cstr)); | |||||
| } else { | |||||
| len = 0; | |||||
| } | |||||
| return *this; | |||||
| } | |||||
| String & String::operator = (const __FlashStringHelper *pgmstr) | |||||
| { | |||||
| copy(pgmstr); | |||||
| return *this; | |||||
| } | |||||
| String & String::operator = (char c) | |||||
| { | |||||
| char buf[2]; | |||||
| buf[0] = c; | |||||
| buf[1] = 0; | |||||
| return copy(buf, 1); | |||||
| } | |||||
| /*********************************************/ | |||||
| /* Append */ | |||||
| /*********************************************/ | |||||
| String & String::append(const String &s) | |||||
| { | |||||
| return append(s.buffer, s.len); | |||||
| } | |||||
| 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; | |||||
| if ( self ) { | |||||
| memcpy(buffer + len, buffer+buffer_offset, length); | |||||
| buffer[newlen] = 0; | |||||
| } | |||||
| else | |||||
| strcpy(buffer + len, cstr); | |||||
| len = newlen; | |||||
| return *this; | |||||
| } | |||||
| String & String::append(const char *cstr) | |||||
| { | |||||
| if (cstr) append(cstr, strlen(cstr)); | |||||
| return *this; | |||||
| } | |||||
| String & String::append(char c) | |||||
| { | |||||
| char buf[2]; | |||||
| buf[0] = c; | |||||
| buf[1] = 0; | |||||
| append(buf, 1); | |||||
| return *this; | |||||
| } | |||||
| String & String::append(int num) | |||||
| { | |||||
| char buf[12]; | |||||
| ltoa((long)num, buf, 10); | |||||
| append(buf, strlen(buf)); | |||||
| return *this; | |||||
| } | |||||
| String & String::append(unsigned int num) | |||||
| { | |||||
| char buf[11]; | |||||
| ultoa((unsigned long)num, buf, 10); | |||||
| append(buf, strlen(buf)); | |||||
| return *this; | |||||
| } | |||||
| String & String::append(long num) | |||||
| { | |||||
| char buf[12]; | |||||
| ltoa(num, buf, 10); | |||||
| append(buf, strlen(buf)); | |||||
| return *this; | |||||
| } | |||||
| String & String::append(unsigned long num) | |||||
| { | |||||
| char buf[11]; | |||||
| ultoa(num, buf, 10); | |||||
| append(buf, strlen(buf)); | |||||
| return *this; | |||||
| } | |||||
| String & String::append(float num) | |||||
| { | |||||
| char buf[30]; | |||||
| dtostrf(num, 4, 2, buf); | |||||
| append(buf, strlen(buf)); | |||||
| return *this; | |||||
| } | |||||
| /*********************************************/ | |||||
| /* Concatenate */ | |||||
| /*********************************************/ | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append(rhs.buffer, rhs.len); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| if (cstr) a.append(cstr, strlen(cstr)); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *pgmstr) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append(pgmstr); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, char c) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append(c); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char c) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append(c); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, int num) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append((long)num); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append((unsigned long)num); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, long num) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append(num); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append(num); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, float num) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append(num); | |||||
| return a; | |||||
| } | |||||
| StringSumHelper & operator + (const StringSumHelper &lhs, double num) | |||||
| { | |||||
| StringSumHelper &a = const_cast<StringSumHelper&>(lhs); | |||||
| a.append(num); | |||||
| return a; | |||||
| } | |||||
| /*********************************************/ | |||||
| /* Comparison */ | |||||
| /*********************************************/ | |||||
| int String::compareTo(const String &s) const | |||||
| { | |||||
| if (!buffer || !s.buffer) { | |||||
| if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer; | |||||
| if (buffer && len > 0) return *(unsigned char *)buffer; | |||||
| return 0; | |||||
| } | |||||
| return strcmp(buffer, s.buffer); | |||||
| } | |||||
| unsigned char String::equals(const String &s2) const | |||||
| { | |||||
| return (len == s2.len && compareTo(s2) == 0); | |||||
| } | |||||
| unsigned char String::equals(const char *cstr) const | |||||
| { | |||||
| if (len == 0) return (cstr == NULL || *cstr == 0); | |||||
| if (cstr == NULL) return buffer[0] == 0; | |||||
| return strcmp(buffer, cstr) == 0; | |||||
| } | |||||
| unsigned char String::operator<(const String &rhs) const | |||||
| { | |||||
| return compareTo(rhs) < 0; | |||||
| } | |||||
| unsigned char String::operator>(const String &rhs) const | |||||
| { | |||||
| return compareTo(rhs) > 0; | |||||
| } | |||||
| unsigned char String::operator<=(const String &rhs) const | |||||
| { | |||||
| return compareTo(rhs) <= 0; | |||||
| } | |||||
| unsigned char String::operator>=(const String &rhs) const | |||||
| { | |||||
| return compareTo(rhs) >= 0; | |||||
| } | |||||
| unsigned char String::equalsIgnoreCase( const String &s2 ) const | |||||
| { | |||||
| if (this == &s2) return 1; | |||||
| if (len != s2.len) return 0; | |||||
| if (len == 0) return 1; | |||||
| const char *p1 = buffer; | |||||
| const char *p2 = s2.buffer; | |||||
| while (*p1) { | |||||
| if (tolower(*p1++) != tolower(*p2++)) return 0; | |||||
| } | |||||
| return 1; | |||||
| } | |||||
| unsigned char String::startsWith( const String &s2 ) const | |||||
| { | |||||
| if (len < s2.len) return 0; | |||||
| return startsWith(s2, 0); | |||||
| } | |||||
| unsigned char String::startsWith( const String &s2, unsigned int offset ) const | |||||
| { | |||||
| if (offset > len - s2.len || !buffer || !s2.buffer) return 0; | |||||
| return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0; | |||||
| } | |||||
| unsigned char String::endsWith( const String &s2 ) const | |||||
| { | |||||
| if ( len < s2.len || !buffer || !s2.buffer) return 0; | |||||
| return strcmp(&buffer[len - s2.len], s2.buffer) == 0; | |||||
| } | |||||
| /*********************************************/ | |||||
| /* Character Access */ | |||||
| /*********************************************/ | |||||
| const char String::zerotermination = 0; | |||||
| char String::charAt(unsigned int loc) const | |||||
| { | |||||
| return operator[](loc); | |||||
| } | |||||
| void String::setCharAt(unsigned int loc, char c) | |||||
| { | |||||
| if (loc < len) buffer[loc] = c; | |||||
| } | |||||
| char & String::operator[](unsigned int index) | |||||
| { | |||||
| static char dummy_writable_char; | |||||
| if (index >= len || !buffer) { | |||||
| dummy_writable_char = 0; | |||||
| return dummy_writable_char; | |||||
| } | |||||
| return buffer[index]; | |||||
| } | |||||
| char String::operator[]( unsigned int index ) const | |||||
| { | |||||
| if (index >= len || !buffer) return 0; | |||||
| return buffer[index]; | |||||
| } | |||||
| void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const | |||||
| { | |||||
| if (!bufsize || !buf) return; | |||||
| if (index >= len) { | |||||
| buf[0] = 0; | |||||
| return; | |||||
| } | |||||
| unsigned int n = bufsize - 1; | |||||
| if (n > len - index) n = len - index; | |||||
| strncpy((char *)buf, buffer + index, n); | |||||
| buf[n] = 0; | |||||
| } | |||||
| /*********************************************/ | |||||
| /* Search */ | |||||
| /*********************************************/ | |||||
| int String::indexOf(char c) const | |||||
| { | |||||
| return indexOf(c, 0); | |||||
| } | |||||
| int String::indexOf( char ch, unsigned int fromIndex ) const | |||||
| { | |||||
| if (fromIndex >= len) return -1; | |||||
| const char* temp = strchr(buffer + fromIndex, ch); | |||||
| if (temp == NULL) return -1; | |||||
| return temp - buffer; | |||||
| } | |||||
| int String::indexOf(const String &s2) const | |||||
| { | |||||
| return indexOf(s2, 0); | |||||
| } | |||||
| int String::indexOf(const String &s2, unsigned int fromIndex) const | |||||
| { | |||||
| if (fromIndex >= len) return -1; | |||||
| const char *found = strstr(buffer + fromIndex, s2.buffer); | |||||
| if (found == NULL) return -1; | |||||
| return found - buffer; | |||||
| } | |||||
| int String::lastIndexOf( char theChar ) const | |||||
| { | |||||
| return lastIndexOf(theChar, len - 1); | |||||
| } | |||||
| int String::lastIndexOf(char ch, unsigned int fromIndex) const | |||||
| { | |||||
| if (fromIndex >= len) return -1; | |||||
| char tempchar = buffer[fromIndex + 1]; | |||||
| buffer[fromIndex + 1] = '\0'; | |||||
| char* temp = strrchr( buffer, ch ); | |||||
| buffer[fromIndex + 1] = tempchar; | |||||
| if (temp == NULL) return -1; | |||||
| return temp - buffer; | |||||
| } | |||||
| int String::lastIndexOf(const String &s2) const | |||||
| { | |||||
| return lastIndexOf(s2, len - s2.len); | |||||
| } | |||||
| int String::lastIndexOf(const String &s2, unsigned int fromIndex) const | |||||
| { | |||||
| 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++) { | |||||
| p = strstr(p, s2.buffer); | |||||
| if (!p) break; | |||||
| if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer; | |||||
| } | |||||
| return found; | |||||
| } | |||||
| String String::substring( unsigned int left ) const | |||||
| { | |||||
| return substring(left, len); | |||||
| } | |||||
| String String::substring(unsigned int left, unsigned int right) const | |||||
| { | |||||
| if (left > right) { | |||||
| unsigned int temp = right; | |||||
| right = left; | |||||
| left = temp; | |||||
| } | |||||
| String out; | |||||
| if (left > len) return out; | |||||
| if (right > len) right = len; | |||||
| char temp = buffer[right]; // save the replaced character | |||||
| buffer[right] = '\0'; | |||||
| out = buffer + left; // pointer arithmetic | |||||
| buffer[right] = temp; //restore character | |||||
| return out; | |||||
| } | |||||
| /*********************************************/ | |||||
| /* Modification */ | |||||
| /*********************************************/ | |||||
| String & String::replace(char find, char replace) | |||||
| { | |||||
| if (!buffer) return *this; | |||||
| for (char *p = buffer; *p; p++) { | |||||
| if (*p == find) *p = replace; | |||||
| } | |||||
| return *this; | |||||
| } | |||||
| String & String::replace(const String& find, const String& replace) | |||||
| { | |||||
| if (len == 0 || find.len == 0) return *this; | |||||
| int diff = replace.len - find.len; | |||||
| char *readFrom = buffer; | |||||
| char *foundAt; | |||||
| if (diff == 0) { | |||||
| while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { | |||||
| memcpy(foundAt, replace.buffer, replace.len); | |||||
| readFrom = foundAt + replace.len; | |||||
| } | |||||
| } else if (diff < 0) { | |||||
| char *writeTo = buffer; | |||||
| while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { | |||||
| unsigned int n = foundAt - readFrom; | |||||
| memcpy(writeTo, readFrom, n); | |||||
| writeTo += n; | |||||
| memcpy(writeTo, replace.buffer, replace.len); | |||||
| writeTo += replace.len; | |||||
| readFrom = foundAt + find.len; | |||||
| len += diff; | |||||
| } | |||||
| strcpy(writeTo, readFrom); | |||||
| } else { | |||||
| unsigned int size = len; // compute size needed for result | |||||
| while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { | |||||
| readFrom = foundAt + find.len; | |||||
| size += diff; | |||||
| } | |||||
| if (size == len) return *this; | |||||
| if (size > capacity && !changeBuffer(size)) return *this; | |||||
| int index = len - 1; | |||||
| while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) { | |||||
| readFrom = buffer + index + find.len; | |||||
| memmove(readFrom + diff, readFrom, len - (readFrom - buffer)); | |||||
| len += diff; | |||||
| buffer[len] = 0; | |||||
| memcpy(buffer + index, replace.buffer, replace.len); | |||||
| index--; | |||||
| } | |||||
| } | |||||
| return *this; | |||||
| } | |||||
| String & String::remove(unsigned int index) | |||||
| { | |||||
| if (index < len) { | |||||
| len = index; | |||||
| buffer[len] = 0; | |||||
| } | |||||
| return *this; | |||||
| } | |||||
| String & String::remove(unsigned int index, unsigned int count) | |||||
| { | |||||
| if (index < len && count > 0) { | |||||
| if (index + count > len) count = len - index; | |||||
| len = len - count; | |||||
| memmove(buffer + index, buffer + index + count, len - index); | |||||
| buffer[len] = 0; | |||||
| } | |||||
| return *this; | |||||
| } | |||||
| String & String::toLowerCase(void) | |||||
| { | |||||
| if (!buffer) return *this; | |||||
| for (char *p = buffer; *p; p++) { | |||||
| *p = tolower(*p); | |||||
| } | |||||
| return *this; | |||||
| } | |||||
| String & String::toUpperCase(void) | |||||
| { | |||||
| if (!buffer) return *this; | |||||
| for (char *p = buffer; *p; p++) { | |||||
| *p = toupper(*p); | |||||
| } | |||||
| return *this; | |||||
| } | |||||
| String & String::trim(void) | |||||
| { | |||||
| if (!buffer || len == 0) return *this; | |||||
| char *begin = buffer; | |||||
| while (isspace(*begin)) begin++; | |||||
| char *end = buffer + len - 1; | |||||
| while (isspace(*end) && end >= begin) end--; | |||||
| len = end + 1 - begin; | |||||
| if (begin > buffer) memcpy(buffer, begin, len); | |||||
| buffer[len] = 0; | |||||
| return *this; | |||||
| } | |||||
| /*********************************************/ | |||||
| /* Parsing / Conversion */ | |||||
| /*********************************************/ | |||||
| long String::toInt(void) const | |||||
| { | |||||
| if (buffer) return atol(buffer); | |||||
| return 0; | |||||
| } | |||||
| float String::toFloat(void) const | |||||
| { | |||||
| if (buffer) return strtof(buffer, (char **)NULL); | |||||
| return 0.0; | |||||
| } | |||||
| /* | |||||
| WString.h - String library for Wiring & Arduino | |||||
| ...mostly rewritten by Paul Stoffregen... | |||||
| Copyright (c) 2009-10 Hernando Barragan. All right reserved. | |||||
| Copyright 2011, 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 | |||||
| */ | |||||
| #ifndef String_class_h | |||||
| #define String_class_h | |||||
| #ifdef __cplusplus | |||||
| #include <stdlib.h> | |||||
| #include <string.h> | |||||
| #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. | |||||
| // -felide-constructors | |||||
| // -std=c++0x | |||||
| // Brian Cook's "no overhead" Flash String type (message on Dec 14, 2010) | |||||
| // modified by Mikal Hart for his FlashString library | |||||
| class __FlashStringHelper; | |||||
| #ifndef F | |||||
| #define F(string_literal) ((const __FlashStringHelper *)(string_literal)) | |||||
| #endif | |||||
| // An inherited class for holding the result of a concatenation. These | |||||
| // result objects are assumed to be writable by subsequent concatenations. | |||||
| class StringSumHelper; | |||||
| // The string class | |||||
| class String | |||||
| { | |||||
| public: | |||||
| // constructors | |||||
| String(const char *cstr = (const char *)NULL); | |||||
| String(const __FlashStringHelper *pgmstr); | |||||
| String(const String &str); | |||||
| #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) | |||||
| String(String &&rval); | |||||
| String(StringSumHelper &&rval); | |||||
| #endif | |||||
| String(char c); | |||||
| String(unsigned char c); | |||||
| String(int, unsigned char base=10); | |||||
| String(unsigned int, unsigned char base=10); | |||||
| String(long, unsigned char base=10); | |||||
| String(unsigned long, unsigned char base=10); | |||||
| String(float num, unsigned char digits=2); | |||||
| String(double num, unsigned char digits=2) : String((float)num, digits) {} | |||||
| ~String(void); | |||||
| // memory management | |||||
| unsigned char reserve(unsigned int size); | |||||
| inline unsigned int length(void) const {return len;} | |||||
| // copy and move | |||||
| String & copy(const char *cstr, unsigned int length); | |||||
| String & copy(const __FlashStringHelper *s) { return copy((const char *)s, strlen((const char *)s)); } | |||||
| void move(String &rhs); | |||||
| String & operator = (const String &rhs); | |||||
| String & operator = (const char *cstr); | |||||
| String & operator = (const __FlashStringHelper *pgmstr); | |||||
| #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) | |||||
| String & operator = (String &&rval); | |||||
| String & operator = (StringSumHelper &&rval); | |||||
| #endif | |||||
| String & operator = (char c); | |||||
| // append | |||||
| String & append(const String &str); | |||||
| String & append(const char *cstr); | |||||
| String & append(const __FlashStringHelper *s) {return append((const char *)s, strlen((const char *)s)); } | |||||
| String & append(char c); | |||||
| String & append(unsigned char c) {return append((int)c);} | |||||
| String & append(int num); | |||||
| String & append(unsigned int num); | |||||
| String & append(long num); | |||||
| String & append(unsigned long num); | |||||
| String & append(float num); | |||||
| String & append(double num) {return append((float)num);} | |||||
| String & operator += (const String &rhs) {return append(rhs);} | |||||
| String & operator += (const char *cstr) {return append(cstr);} | |||||
| String & operator += (const __FlashStringHelper *pgmstr) {return append(pgmstr);} | |||||
| String & operator += (char c) {return append(c);} | |||||
| String & operator += (unsigned char c) {return append((int)c);} | |||||
| String & operator += (int num) {return append(num);} | |||||
| String & operator += (unsigned int num) {return append(num);} | |||||
| String & operator += (long num) {return append(num);} | |||||
| String & operator += (unsigned long num) {return append(num);} | |||||
| String & operator += (float num) {return append(num);} | |||||
| String & operator += (double num) {return append(num);} | |||||
| // concatenate | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *pgmstr); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, char c); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char c); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, int num); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, long num); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, float num); | |||||
| friend StringSumHelper & operator + (const StringSumHelper &lhs, double num); | |||||
| String & concat(const String &str) {return append(str);} | |||||
| String & concat(const char *cstr) {return append(cstr);} | |||||
| String & concat(const __FlashStringHelper *pgmstr) {return append(pgmstr);} | |||||
| String & concat(char c) {return append(c);} | |||||
| String & concat(unsigned char c) {return append((int)c);} | |||||
| String & concat(int num) {return append(num);} | |||||
| String & concat(unsigned int num) {return append(num);} | |||||
| String & concat(long num) {return append(num);} | |||||
| String & concat(unsigned long num) {return append(num);} | |||||
| String & concat(float num) {return append(num);} | |||||
| String & concat(double num) {return append(num);} | |||||
| // comparison | |||||
| int compareTo(const String &s) const; | |||||
| unsigned char equals(const String &s) const; | |||||
| unsigned char equals(const char *cstr) const; | |||||
| //unsigned char equals(const __FlashStringHelper *pgmstr) const; | |||||
| unsigned char operator == (const String &rhs) const {return equals(rhs);} | |||||
| unsigned char operator == (const char *cstr) const {return equals(cstr);} | |||||
| unsigned char operator == (const __FlashStringHelper *s) const {return equals((const char *)s);} | |||||
| unsigned char operator != (const String &rhs) const {return !equals(rhs);} | |||||
| unsigned char operator != (const char *cstr) const {return !equals(cstr);} | |||||
| unsigned char operator != (const __FlashStringHelper *s) const {return !equals(s);} | |||||
| unsigned char operator < (const String &rhs) const; | |||||
| unsigned char operator > (const String &rhs) const; | |||||
| unsigned char operator <= (const String &rhs) const; | |||||
| unsigned char operator >= (const String &rhs) const; | |||||
| unsigned char equalsIgnoreCase(const String &s) const; | |||||
| unsigned char startsWith( const String &prefix) const; | |||||
| unsigned char startsWith(const String &prefix, unsigned int offset) const; | |||||
| unsigned char endsWith(const String &suffix) const; | |||||
| // character acccess | |||||
| char charAt(unsigned int index) const; | |||||
| void setCharAt(unsigned int index, char c); | |||||
| char operator [] (unsigned int index) const; | |||||
| char& operator [] (unsigned int index); | |||||
| void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const; | |||||
| void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const | |||||
| {getBytes((unsigned char *)buf, bufsize, index);} | |||||
| const char * c_str() const { | |||||
| if (!buffer) return &zerotermination; // https://forum.pjrc.com/threads/63842 | |||||
| return buffer; | |||||
| } | |||||
| // search | |||||
| int indexOf( char ch ) const; | |||||
| int indexOf( char ch, unsigned int fromIndex ) const; | |||||
| int indexOf( const String &str ) const; | |||||
| int indexOf( const String &str, unsigned int fromIndex ) const; | |||||
| int lastIndexOf( char ch ) const; | |||||
| int lastIndexOf( char ch, unsigned int fromIndex ) const; | |||||
| int lastIndexOf( const String &str ) const; | |||||
| int lastIndexOf( const String &str, unsigned int fromIndex ) const; | |||||
| String substring( unsigned int beginIndex ) const; | |||||
| String substring( unsigned int beginIndex, unsigned int endIndex ) const; | |||||
| // modification | |||||
| String & replace(char find, char replace); | |||||
| String & replace(const String& find, const String& replace); | |||||
| String & remove(unsigned int index); | |||||
| String & remove(unsigned int index, unsigned int count); | |||||
| String & toLowerCase(void); | |||||
| String & toUpperCase(void); | |||||
| String & trim(void); | |||||
| // parsing/conversion | |||||
| long toInt(void) const; | |||||
| float toFloat(void) const; | |||||
| protected: | |||||
| char *buffer; // the actual char array | |||||
| unsigned int capacity; // the array length minus one (for the '\0') | |||||
| unsigned int len; // the String length (not counting the '\0') | |||||
| unsigned char flags; // unused, for future features | |||||
| 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 {} | |||||
| static const char zerotermination; | |||||
| public: | |||||
| operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; } | |||||
| }; | |||||
| class StringSumHelper : public String | |||||
| { | |||||
| public: | |||||
| StringSumHelper(const String &s) : String(s) {} | |||||
| StringSumHelper(const char *p) : String(p) {} | |||||
| StringSumHelper(const __FlashStringHelper *pgmstr) : String(pgmstr) {} | |||||
| StringSumHelper(char c) : String(c) {} | |||||
| StringSumHelper(unsigned char c) : String(c) {} | |||||
| StringSumHelper(int num) : String(num, 10) {} | |||||
| StringSumHelper(unsigned int num) : String(num, 10) {} | |||||
| StringSumHelper(long num) : String(num, 10) {} | |||||
| StringSumHelper(unsigned long num) : String(num, 10) {} | |||||
| }; | |||||
| #endif // __cplusplus | |||||
| #endif // String_class_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 "core_pins.h" | |||||
| //#include "HardwareSerial.h" | |||||
| static uint8_t calibrating; | |||||
| static uint8_t analog_right_shift = 0; | |||||
| static uint8_t analog_config_bits = 10; | |||||
| static uint8_t analog_num_average = 4; | |||||
| 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 == 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 || 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 | |||||
| #define ADC_CFG1_8BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 14 MHz | |||||
| #elif F_BUS == 48000000 | |||||
| #define ADC_CFG1_16BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 12 MHz | |||||
| #define ADC_CFG1_12BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 12 MHz | |||||
| #define ADC_CFG1_10BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 12 MHz | |||||
| #define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1) // 24 MHz | |||||
| #elif F_BUS == 40000000 | |||||
| #define ADC_CFG1_16BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 10 MHz | |||||
| #define ADC_CFG1_12BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 10 MHz | |||||
| #define ADC_CFG1_10BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 10 MHz | |||||
| #define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1) // 20 MHz | |||||
| #elif F_BUS == 36000000 | |||||
| #define ADC_CFG1_16BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(1) // 9 MHz | |||||
| #define ADC_CFG1_12BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1) // 18 MHz | |||||
| #define ADC_CFG1_10BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1) // 18 MHz | |||||
| #define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(1) // 18 MHz | |||||
| #elif F_BUS == 24000000 | |||||
| #define ADC_CFG1_16BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(0) // 12 MHz | |||||
| #define ADC_CFG1_12BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(0) // 12 MHz | |||||
| #define ADC_CFG1_10BIT ADC_CFG1_ADIV(1) + ADC_CFG1_ADICLK(0) // 12 MHz | |||||
| #define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 24 MHz | |||||
| #elif F_BUS == 16000000 | |||||
| #define ADC_CFG1_16BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz | |||||
| #define ADC_CFG1_12BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz | |||||
| #define ADC_CFG1_10BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz | |||||
| #define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 16 MHz | |||||
| #elif F_BUS == 8000000 | |||||
| #define ADC_CFG1_16BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz | |||||
| #define ADC_CFG1_12BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz | |||||
| #define ADC_CFG1_10BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz | |||||
| #define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 8 MHz | |||||
| #elif F_BUS == 4000000 | |||||
| #define ADC_CFG1_16BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 4 MHz | |||||
| #define ADC_CFG1_12BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 4 MHz | |||||
| #define ADC_CFG1_10BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 4 MHz | |||||
| #define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 4 MHz | |||||
| #elif F_BUS == 2000000 | |||||
| #define ADC_CFG1_16BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 2 MHz | |||||
| #define ADC_CFG1_12BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 2 MHz | |||||
| #define ADC_CFG1_10BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 2 MHz | |||||
| #define ADC_CFG1_8BIT ADC_CFG1_ADIV(0) + ADC_CFG1_ADICLK(0) // 2 MHz | |||||
| #else | |||||
| #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); | |||||
| #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); | |||||
| #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); | |||||
| #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); | |||||
| #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 | |||||
| ADC1_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref | |||||
| } else { | |||||
| ADC0_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref | |||||
| ADC1_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref | |||||
| } | |||||
| #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 | |||||
| #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); | |||||
| #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); | |||||
| #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); | |||||
| #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); | |||||
| #ifdef HAS_KINETIS_ADC1 | |||||
| ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3); | |||||
| #endif | |||||
| } | |||||
| calibrating = 1; | |||||
| } | |||||
| static void wait_for_cal(void) | |||||
| { | |||||
| uint16_t sum; | |||||
| //serial_print("wait_for_cal\n"); | |||||
| #if defined(HAS_KINETIS_ADC0) && defined(HAS_KINETIS_ADC1) | |||||
| while ((ADC0_SC3 & ADC_SC3_CAL) || (ADC1_SC3 & ADC_SC3_CAL)) { | |||||
| // wait | |||||
| } | |||||
| #elif defined(HAS_KINETIS_ADC0) | |||||
| while (ADC0_SC3 & ADC_SC3_CAL) { | |||||
| // wait | |||||
| } | |||||
| #endif | |||||
| __disable_irq(); | |||||
| if (calibrating) { | |||||
| //serial_print("\n"); | |||||
| sum = ADC0_CLPS + ADC0_CLP4 + ADC0_CLP3 + ADC0_CLP2 + ADC0_CLP1 + ADC0_CLP0; | |||||
| sum = (sum / 2) | 0x8000; | |||||
| ADC0_PG = sum; | |||||
| //serial_print("ADC0_PG = "); | |||||
| //serial_phex16(sum); | |||||
| //serial_print("\n"); | |||||
| sum = ADC0_CLMS + ADC0_CLM4 + ADC0_CLM3 + ADC0_CLM2 + ADC0_CLM1 + ADC0_CLM0; | |||||
| sum = (sum / 2) | 0x8000; | |||||
| ADC0_MG = sum; | |||||
| //serial_print("ADC0_MG = "); | |||||
| //serial_phex16(sum); | |||||
| //serial_print("\n"); | |||||
| #ifdef HAS_KINETIS_ADC1 | |||||
| sum = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0; | |||||
| sum = (sum / 2) | 0x8000; | |||||
| ADC1_PG = sum; | |||||
| sum = ADC1_CLMS + ADC1_CLM4 + ADC1_CLM3 + ADC1_CLM2 + ADC1_CLM1 + ADC1_CLM0; | |||||
| sum = (sum / 2) | 0x8000; | |||||
| ADC1_MG = sum; | |||||
| #endif | |||||
| calibrating = 0; | |||||
| } | |||||
| __enable_irq(); | |||||
| } | |||||
| // ADCx_SC2[REFSEL] bit selects the voltage reference sources for ADC. | |||||
| // 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) { | |||||
| // internal reference requested | |||||
| if (!analog_reference_internal) { | |||||
| analog_reference_internal = 1; | |||||
| if (calibrating) { | |||||
| ADC0_SC3 = 0; // cancel cal | |||||
| #ifdef HAS_KINETIS_ADC1 | |||||
| ADC1_SC3 = 0; // cancel cal | |||||
| #endif | |||||
| } | |||||
| analog_init(); | |||||
| } | |||||
| } else { | |||||
| // vcc or external reference requested | |||||
| if (analog_reference_internal) { | |||||
| analog_reference_internal = 0; | |||||
| if (calibrating) { | |||||
| ADC0_SC3 = 0; // cancel cal | |||||
| #ifdef HAS_KINETIS_ADC1 | |||||
| ADC1_SC3 = 0; // cancel cal | |||||
| #endif | |||||
| } | |||||
| analog_init(); | |||||
| } | |||||
| } | |||||
| } | |||||
| void analogReadRes(unsigned int bits) | |||||
| { | |||||
| unsigned int config; | |||||
| if (bits >= 13) { | |||||
| if (bits > 16) bits = 16; | |||||
| config = 16; | |||||
| } else if (bits >= 11) { | |||||
| config = 12; | |||||
| } else if (bits >= 9) { | |||||
| config = 10; | |||||
| } else { | |||||
| config = 8; | |||||
| } | |||||
| analog_right_shift = config - bits; | |||||
| if (config != analog_config_bits) { | |||||
| analog_config_bits = config; | |||||
| if (calibrating) { | |||||
| ADC0_SC3 = 0; // cancel cal | |||||
| #ifdef HAS_KINETIS_ADC1 | |||||
| ADC1_SC3 = 0; | |||||
| #endif | |||||
| } | |||||
| analog_init(); | |||||
| } | |||||
| } | |||||
| void analogReadAveraging(unsigned int num) | |||||
| { | |||||
| if (calibrating) wait_for_cal(); | |||||
| if (num <= 1) { | |||||
| num = 0; | |||||
| ADC0_SC3 = 0; | |||||
| } 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; | |||||
| } | |||||
| // The SC1A register is used for both software and hardware trigger modes of operation. | |||||
| #if defined(__MK20DX128__) | |||||
| 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 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 | |||||
| // TODO: perhaps this should store the NVIC priority, so it works recursively? | |||||
| static volatile uint8_t analogReadBusyADC0 = 0; | |||||
| #ifdef HAS_KINETIS_ADC1 | |||||
| static volatile uint8_t analogReadBusyADC1 = 0; | |||||
| #endif | |||||
| int analogRead(uint8_t pin) | |||||
| { | |||||
| int result; | |||||
| uint8_t channel; | |||||
| //serial_phex(pin); | |||||
| //serial_print(" "); | |||||
| if (pin >= sizeof(pin2sc1a)) return 0; | |||||
| channel = pin2sc1a[pin]; | |||||
| if (channel == 255) return 0; | |||||
| if (calibrating) wait_for_cal(); | |||||
| #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(); | |||||
| while (1) { | |||||
| __disable_irq(); | |||||
| if ((ADC0_SC1A & ADC_SC1_COCO)) { | |||||
| result = ADC0_RA; | |||||
| analogReadBusyADC0 = 0; | |||||
| __enable_irq(); | |||||
| result >>= analog_right_shift; | |||||
| return result; | |||||
| } | |||||
| // detect if analogRead was used from an interrupt | |||||
| // if so, our analogRead got canceled, so it must | |||||
| // be restarted. | |||||
| if (!analogReadBusyADC0) goto startADC0; | |||||
| __enable_irq(); | |||||
| yield(); | |||||
| } | |||||
| #ifdef HAS_KINETIS_ADC1 | |||||
| beginADC1: | |||||
| __disable_irq(); | |||||
| startADC1: | |||||
| //serial_print("startADC1\n"); | |||||
| // ADC1_CFG2[MUXSEL] bit selects between ADCx_SEn channels a and b. | |||||
| if (channel & 0x40) { | |||||
| ADC1_CFG2 &= ~ADC_CFG2_MUXSEL; | |||||
| } else { | |||||
| ADC1_CFG2 |= ADC_CFG2_MUXSEL; | |||||
| } | |||||
| ADC1_SC1A = channel & 0x3F; | |||||
| analogReadBusyADC1 = 1; | |||||
| __enable_irq(); | |||||
| while (1) { | |||||
| __disable_irq(); | |||||
| if ((ADC1_SC1A & ADC_SC1_COCO)) { | |||||
| result = ADC1_RA; | |||||
| analogReadBusyADC1 = 0; | |||||
| __enable_irq(); | |||||
| result >>= analog_right_shift; | |||||
| return result; | |||||
| } | |||||
| // detect if analogRead was used from an interrupt | |||||
| // if so, our analogRead got canceled, so it must | |||||
| // be restarted. | |||||
| if (!analogReadBusyADC1) goto startADC1; | |||||
| __enable_irq(); | |||||
| yield(); | |||||
| } | |||||
| #endif | |||||
| } | |||||
| typedef int16_t __attribute__((__may_alias__)) aliased_int16_t; | |||||
| void analogWriteDAC0(int val) | |||||
| { | |||||
| #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 | |||||
| } | |||||
| __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; | |||||
| *(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 | |||||
| /* ---------------------------------------------------------------------- | |||||
| * Copyright (C) 2010 ARM Limited. All rights reserved. | |||||
| * | |||||
| * $Date: 11. November 2010 | |||||
| * $Revision: V1.0.2 | |||||
| * | |||||
| * Project: CMSIS DSP Library | |||||
| * Title: arm_common_tables.h | |||||
| * | |||||
| * Description: This file has extern declaration for common tables like Bitreverse, reciprocal etc which are used across different functions | |||||
| * | |||||
| * Target Processor: Cortex-M4/Cortex-M3 | |||||
| * | |||||
| * 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. | |||||
| * -------------------------------------------------------------------- */ | |||||
| #ifndef _ARM_COMMON_TABLES_H | |||||
| #define _ARM_COMMON_TABLES_H | |||||
| #include "arm_math.h" | |||||
| extern const uint16_t armBitRevTable[1024]; | |||||
| extern const q15_t armRecipTableQ15[64]; | |||||
| extern const q31_t armRecipTableQ31[64]; | |||||
| extern const q31_t realCoefAQ31[1024]; | |||||
| extern const q31_t realCoefBQ31[1024]; | |||||
| extern const float32_t twiddleCoef[6144]; | |||||
| extern const q31_t twiddleCoefQ31[6144]; | |||||
| extern const q15_t twiddleCoefQ15[6144]; | |||||
| #endif /* ARM_COMMON_TABLES_H */ |
| /* 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> | |||||
| #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 |
| // This header file is in the public domain. |
| /* 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" |
| /* 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 | |||||
| #include <inttypes.h> | |||||
| #define PROGMEM | |||||
| #define FLASHMEM | |||||
| #define PGM_P const char * | |||||
| #define PSTR(str) (str) | |||||
| #define _SFR_BYTE(n) (n) | |||||
| typedef void prog_void; | |||||
| typedef char prog_char; | |||||
| typedef unsigned char prog_uchar; | |||||
| typedef int8_t prog_int8_t; | |||||
| typedef uint8_t prog_uint8_t; | |||||
| 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)) | |||||
| #define memcpy_P(dest, src, num) memcpy((dest), (src), (num)) | |||||
| #define memmem_P(a, alen, b, blen) memmem((a), (alen), (b), (blen)) | |||||
| #define memrchr_P(str, val, len) memrchr((str), (val), (len)) | |||||
| #define strcat_P(dest, src) strcat((dest), (src)) | |||||
| #define strchr_P(str, c) strchr((str), (c)) | |||||
| #define strchrnul_P(str, c) strchrnul((str), (c)) | |||||
| #define strcmp_P(a, b) strcmp((a), (b)) | |||||
| #define strcpy_P(dest, src) strcpy((dest), (src)) | |||||
| #define strcasecmp_P(a, b) strcasecmp((a), (b)) | |||||
| #define strcasestr_P(a, b) strcasestr((a), (b)) | |||||
| #define strlcat_P(dest, src, len) strlcat((dest), (src), (len)) | |||||
| #define strlcpy_P(dest, src, len) strlcpy((dest), (src), (len)) | |||||
| #define strlen_P(s) strlen((const char *)(s)) | |||||
| #define strnlen_P(str, len) strnlen((str), (len)) | |||||
| #define strncmp_P(a, b, n) strncmp((a), (b), (n)) | |||||
| #define strncasecmp_P(a, b, n) strncasecmp((a), (b), (n)) | |||||
| #define strncat_P(a, b, n) strncat((a), (b), (n)) | |||||
| #define strncpy_P(a, b, n) strncpy((a), (b), (n)) | |||||
| #define strpbrk_P(str, chrs) strpbrk((str), (chrs)) | |||||
| #define strrchr_P(str, c) strrchr((str), (c)) | |||||
| #define strsep_P(strp, delim) strsep((strp), (delim)) | |||||
| #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(fp, s, ...) vfprintf((fp), (s), __VA_ARGS__) | |||||
| #define printf_P(...) printf(__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 |
| /* 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 |