├── .gitattributes ├── .gitignore ├── NeoICSerial.cpp ├── NeoICSerial.h ├── README.md └── config ├── NeoICSerial_Boards.h └── NeoICSerial_Timers.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /NeoICSerial.cpp: -------------------------------------------------------------------------------- 1 | /* An Alternative Software Serial Library which uses Input Capture pins 2 | * http://www.pjrc.com/teensy/td_libs_NeoICSerial.html 3 | * Copyright (c) 2014 PJRC.COM, LLC, Paul Stoffregen, paul@pjrc.com 4 | * Modified November 2015 by SlashDev 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | // Revisions are now tracked on GitHub 26 | // https://github.com/PaulStoffregen/AltSoftSerial 27 | // 28 | // Version 1.2: Support Teensy 3.x 29 | // 30 | // Version 1.1: Improve performance in receiver code 31 | // 32 | // Version 1.0: Initial Release 33 | 34 | 35 | #include "NeoICSerial.h" 36 | #include "config/NeoICSerial_Boards.h" 37 | #include "config/NeoICSerial_Timers.h" 38 | 39 | /****************************************/ 40 | /** Initialization **/ 41 | /****************************************/ 42 | 43 | static uint16_t ticks_per_bit=0; 44 | //bool NeoICSerial::timing_error=false; 45 | 46 | static uint8_t rx_state; 47 | static uint8_t rx_byte; 48 | static uint8_t rx_bit = 0; 49 | static uint16_t rx_target; 50 | static uint16_t rx_stop_ticks=0; 51 | static volatile uint8_t rx_buffer_head; 52 | static volatile uint8_t rx_buffer_tail; 53 | #define RX_BUFFER_SIZE 80 54 | static volatile uint8_t rx_buffer[RX_BUFFER_SIZE]; 55 | 56 | static volatile uint8_t tx_state=0; 57 | static uint8_t tx_byte; 58 | static uint8_t tx_bit; 59 | static volatile uint8_t tx_buffer_head; 60 | static volatile uint8_t tx_buffer_tail; 61 | #define TX_BUFFER_SIZE 68 62 | static volatile uint8_t tx_buffer[TX_BUFFER_SIZE]; 63 | 64 | 65 | #ifndef INPUT_PULLUP 66 | #define INPUT_PULLUP INPUT 67 | #endif 68 | 69 | #define MAX_COUNTS_PER_BIT 6241 // 65536 / 10.5 70 | 71 | void NeoICSerial::init(uint32_t cycles_per_bit) 72 | { 73 | //Serial.printf("cycles_per_bit = %d\n", cycles_per_bit); 74 | if (cycles_per_bit < MAX_COUNTS_PER_BIT) { 75 | CONFIG_TIMER_NOPRESCALE(); 76 | } else { 77 | cycles_per_bit /= 8; 78 | //Serial.printf("cycles_per_bit/8 = %d\n", cycles_per_bit); 79 | if (cycles_per_bit < MAX_COUNTS_PER_BIT) { 80 | CONFIG_TIMER_PRESCALE_8(); 81 | } else { 82 | #if defined(CONFIG_TIMER_PRESCALE_256) 83 | cycles_per_bit /= 32; 84 | //Serial.printf("cycles_per_bit/256 = %d\n", cycles_per_bit); 85 | if (cycles_per_bit < MAX_COUNTS_PER_BIT) { 86 | CONFIG_TIMER_PRESCALE_256(); 87 | } else { 88 | return; // baud rate too low for AltSoftSerial 89 | } 90 | #elif defined(CONFIG_TIMER_PRESCALE_128) 91 | cycles_per_bit /= 16; 92 | //Serial.printf("cycles_per_bit/128 = %d\n", cycles_per_bit); 93 | if (cycles_per_bit < MAX_COUNTS_PER_BIT) { 94 | CONFIG_TIMER_PRESCALE_128(); 95 | } else { 96 | return; // baud rate too low for AltSoftSerial 97 | } 98 | #else 99 | return; // baud rate too low for AltSoftSerial 100 | #endif 101 | } 102 | } 103 | ticks_per_bit = cycles_per_bit; 104 | rx_stop_ticks = cycles_per_bit * 37 / 4; 105 | pinMode(INPUT_CAPTURE_PIN, INPUT_PULLUP); 106 | digitalWrite(OUTPUT_COMPARE_A_PIN, HIGH); 107 | pinMode(OUTPUT_COMPARE_A_PIN, OUTPUT); 108 | rx_state = 0; 109 | rx_buffer_head = 0; 110 | rx_buffer_tail = 0; 111 | tx_state = 0; 112 | tx_buffer_head = 0; 113 | tx_buffer_tail = 0; 114 | ENABLE_INT_INPUT_CAPTURE(); 115 | } 116 | 117 | void NeoICSerial::end(void) 118 | { 119 | DISABLE_INT_COMPARE_B(); 120 | DISABLE_INT_INPUT_CAPTURE(); 121 | flushInput(); 122 | flushOutput(); 123 | DISABLE_INT_COMPARE_A(); 124 | // TODO: restore timer to original settings? 125 | } 126 | 127 | 128 | /****************************************/ 129 | /** Transmission **/ 130 | /****************************************/ 131 | 132 | static NeoICSerial::TXCisr_t _TXCisr; 133 | 134 | void NeoICSerial::attachTxCompleteInterrupt( TXCisr_t fn ) 135 | { 136 | uint8_t oldSREG = SREG; 137 | cli(); 138 | _TXCisr = fn; 139 | SREG = oldSREG; 140 | } 141 | 142 | void NeoICSerial::writeByte(uint8_t b) 143 | { 144 | uint8_t intr_state, head; 145 | 146 | head = tx_buffer_head + 1; 147 | if (head >= TX_BUFFER_SIZE) head = 0; 148 | while (tx_buffer_tail == head) ; // wait until space in buffer 149 | intr_state = SREG; 150 | cli(); 151 | if (tx_state) { 152 | tx_buffer[head] = b; 153 | tx_buffer_head = head; 154 | } else { 155 | tx_state = 1; 156 | tx_byte = b; 157 | tx_bit = 0; 158 | ENABLE_INT_COMPARE_A(); 159 | CONFIG_MATCH_CLEAR(); 160 | SET_COMPARE_A(GET_TIMER_COUNT() + 16); 161 | } 162 | SREG = intr_state; 163 | } 164 | 165 | 166 | ISR(COMPARE_A_INTERRUPT) 167 | { 168 | uint8_t state, byte, bit, head, tail; 169 | uint16_t target; 170 | 171 | state = tx_state; 172 | byte = tx_byte; 173 | target = GET_COMPARE_A(); 174 | while (state < 10) { 175 | target += ticks_per_bit; 176 | if (state < 9) 177 | bit = byte & 1; 178 | else 179 | bit = 1; // stopbit 180 | byte >>= 1; 181 | state++; 182 | if (bit != tx_bit) { 183 | if (bit) { 184 | CONFIG_MATCH_SET(); 185 | } else { 186 | CONFIG_MATCH_CLEAR(); 187 | } 188 | SET_COMPARE_A(target); 189 | tx_bit = bit; 190 | tx_byte = byte; 191 | tx_state = state; 192 | // TODO: how to detect timing_error? 193 | return; 194 | } 195 | } 196 | head = tx_buffer_head; 197 | tail = tx_buffer_tail; 198 | if (head == tail) { 199 | if (state == 10) { 200 | // Wait for final stop bit to finish 201 | tx_state = 11; 202 | SET_COMPARE_A(target + ticks_per_bit); 203 | } else { 204 | tx_state = 0; 205 | CONFIG_MATCH_NORMAL(); 206 | DISABLE_INT_COMPARE_A(); 207 | if (_TXCisr) 208 | _TXCisr(); 209 | } 210 | } else { 211 | if (++tail >= TX_BUFFER_SIZE) tail = 0; 212 | tx_buffer_tail = tail; 213 | tx_byte = tx_buffer[tail]; 214 | tx_bit = 0; 215 | CONFIG_MATCH_CLEAR(); 216 | if (state == 10) 217 | SET_COMPARE_A(target + ticks_per_bit); 218 | else 219 | SET_COMPARE_A(GET_TIMER_COUNT() + 16); 220 | tx_state = 1; 221 | // TODO: how to detect timing_error? 222 | } 223 | } 224 | 225 | void NeoICSerial::flushOutput(void) 226 | { 227 | while (tx_state) /* wait */ ; 228 | } 229 | 230 | 231 | /****************************************/ 232 | /** Reception **/ 233 | /****************************************/ 234 | 235 | static NeoICSerial::isr_t _isr; 236 | 237 | void NeoICSerial::attachInterrupt( isr_t fn ) 238 | { 239 | uint8_t oldSREG = SREG; 240 | cli(); 241 | _isr = fn; 242 | SREG = oldSREG; 243 | } 244 | 245 | static void rx_char( uint8_t rx_byte ) 246 | { 247 | if (_isr) 248 | _isr( rx_byte ); 249 | else { 250 | uint8_t head = rx_buffer_head + 1; 251 | if (head >= RX_BUFFER_SIZE) head = 0; 252 | if (head != rx_buffer_tail) { 253 | rx_buffer[head] = rx_byte; 254 | rx_buffer_head = head; 255 | } 256 | } 257 | } 258 | 259 | ISR(CAPTURE_INTERRUPT) 260 | { 261 | uint8_t state, bit, head; 262 | uint16_t capture, target; 263 | uint16_t offset, offset_overflow; 264 | 265 | capture = GET_INPUT_CAPTURE(); 266 | bit = rx_bit; 267 | if (bit) { 268 | CONFIG_CAPTURE_FALLING_EDGE(); 269 | rx_bit = 0; 270 | } else { 271 | CONFIG_CAPTURE_RISING_EDGE(); 272 | rx_bit = 0x80; 273 | } 274 | state = rx_state; 275 | if (state == 0) { 276 | if (!bit) { 277 | uint16_t end = capture + rx_stop_ticks; 278 | SET_COMPARE_B(end); 279 | ENABLE_INT_COMPARE_B(); 280 | rx_target = capture + ticks_per_bit + ticks_per_bit/2; 281 | rx_state = 1; 282 | } 283 | } else { 284 | target = rx_target; 285 | offset_overflow = 65535 - ticks_per_bit; 286 | while (1) { 287 | offset = capture - target; 288 | if (offset > offset_overflow) break; 289 | rx_byte = (rx_byte >> 1) | rx_bit; 290 | target += ticks_per_bit; 291 | state++; 292 | if (state >= 9) { 293 | DISABLE_INT_COMPARE_B(); 294 | rx_char( rx_byte ); 295 | CONFIG_CAPTURE_FALLING_EDGE(); 296 | rx_bit = 0; 297 | rx_state = 0; 298 | return; 299 | } 300 | } 301 | rx_target = target; 302 | rx_state = state; 303 | } 304 | //if (GET_TIMER_COUNT() - capture > ticks_per_bit) NeoICSerial::timing_error = true; 305 | } 306 | 307 | ISR(COMPARE_B_INTERRUPT) 308 | { 309 | uint8_t head, state, bit; 310 | 311 | DISABLE_INT_COMPARE_B(); 312 | CONFIG_CAPTURE_FALLING_EDGE(); 313 | state = rx_state; 314 | bit = rx_bit ^ 0x80; 315 | while (state < 9) { 316 | rx_byte = (rx_byte >> 1) | bit; 317 | state++; 318 | } 319 | rx_char( rx_byte ); 320 | rx_state = 0; 321 | CONFIG_CAPTURE_FALLING_EDGE(); 322 | rx_bit = 0; 323 | } 324 | 325 | 326 | 327 | int NeoICSerial::read(void) 328 | { 329 | uint8_t head, tail, out; 330 | 331 | head = rx_buffer_head; 332 | tail = rx_buffer_tail; 333 | if (head == tail) return -1; 334 | if (++tail >= RX_BUFFER_SIZE) tail = 0; 335 | out = rx_buffer[tail]; 336 | rx_buffer_tail = tail; 337 | return out; 338 | } 339 | 340 | int NeoICSerial::peek(void) 341 | { 342 | uint8_t head, tail; 343 | 344 | head = rx_buffer_head; 345 | tail = rx_buffer_tail; 346 | if (head == tail) return -1; 347 | if (++tail >= RX_BUFFER_SIZE) tail = 0; 348 | return rx_buffer[tail]; 349 | } 350 | 351 | int NeoICSerial::available(void) 352 | { 353 | uint8_t head, tail; 354 | 355 | head = rx_buffer_head; 356 | tail = rx_buffer_tail; 357 | if (head >= tail) return head - tail; 358 | return RX_BUFFER_SIZE + head - tail; 359 | } 360 | 361 | void NeoICSerial::flushInput(void) 362 | { 363 | rx_buffer_head = rx_buffer_tail; 364 | } 365 | 366 | 367 | #ifdef ALTSS_USE_FTM0 368 | void ftm0_isr(void) 369 | { 370 | uint32_t flags = FTM0_STATUS; 371 | FTM0_STATUS = 0; 372 | if (flags & (1<<0) && (FTM0_C0SC & 0x40)) altss_compare_b_interrupt(); 373 | if (flags & (1<<5)) altss_capture_interrupt(); 374 | if (flags & (1<<6) && (FTM0_C6SC & 0x40)) altss_compare_a_interrupt(); 375 | } 376 | #endif 377 | 378 | -------------------------------------------------------------------------------- /NeoICSerial.h: -------------------------------------------------------------------------------- 1 | /* An Alternative Software Serial Library which uses Input Capture pins 2 | * Based on: 3 | * http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html 4 | * Copyright (c) 2014 PJRC.COM, LLC, Paul Stoffregen, paul@pjrc.com 5 | * 6 | * Modified November 2015 by SlashDev 7 | * 8 | * NeoICSerial always uses these pins: 9 | * 10 | * Board Transmit Receive PWM Unusable 11 | * ----- -------- ------- ------------ 12 | * Teensy 3.0 & 3.1 21 20 22 13 | * Teensy 2.0 9 10 (none) 14 | * Teensy++ 2.0 25 4 26, 27 15 | * Arduino Uno 9 8 10 16 | * Arduino Leonardo 5 13 (none) 17 | * Arduino Mega 46 48 44, 45 18 | * Wiring-S 5 6 4 19 | * Sanguino 13 14 12 20 | * 21 | * Permission is hereby granted, free of charge, to any person obtaining a copy 22 | * of this software and associated documentation files (the "Software"), to deal 23 | * in the Software without restriction, including without limitation the rights 24 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | * copies of the Software, and to permit persons to whom the Software is 26 | * furnished to do so, subject to the following conditions: 27 | * 28 | * The above copyright notice and this permission notice shall be included in 29 | * all copies or substantial portions of the Software. 30 | * 31 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 37 | * THE SOFTWARE. 38 | */ 39 | 40 | #ifndef NeoICSerial_h 41 | #define NeoICSerial_h 42 | 43 | #include 44 | 45 | #include "Arduino.h" 46 | 47 | #if defined(__arm__) && defined(CORE_TEENSY) 48 | #define ALTSS_BASE_FREQ F_BUS 49 | #else 50 | #define ALTSS_BASE_FREQ F_CPU 51 | #endif 52 | 53 | class NeoICSerial : public Stream 54 | { 55 | public: 56 | NeoICSerial() { } 57 | ~NeoICSerial() { end(); } 58 | static void begin(uint32_t baud) { init((ALTSS_BASE_FREQ + baud / 2) / baud); } 59 | static void end(); 60 | int peek(); 61 | int read(); 62 | int available(); 63 | size_t write(uint8_t byte) { writeByte(byte); return 1; } 64 | void flush() { flushOutput(); } 65 | 66 | using Print::write; 67 | static void flushInput(); 68 | static void flushOutput(); 69 | 70 | typedef void (* isr_t)( uint8_t ); 71 | static void attachInterrupt( isr_t fn ); 72 | static void detachInterrupt() 73 | { attachInterrupt( nullptr ); }; 74 | 75 | typedef void (* TXCisr_t)(); 76 | static void attachTxCompleteInterrupt( TXCisr_t fn ); 77 | static void detachTxCompleteInterrupt() 78 | { attachTxCompleteInterrupt( nullptr ); }; 79 | private: 80 | static void init(uint32_t cycles_per_bit); 81 | static void writeByte(uint8_t byte); 82 | }; 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The **NeoICSerial** class is intended as a drop-in replacement for Paul Stoffregen's class [AltSoftSerial](https://github.com/PaulStoffregen/AltSoftSerial). It adds the capability to register a function to be called when a new character is received or when all character have been transmitted. 2 | 3 | This class can only use one predefined Input Capture pin. Each MCU and board has a pre-determined pin: 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
Board Transmit Receive PWM Unusable
Teensy 3.0 & 3.1 21 20 22
Teensy 2.0 9 10 (none)
Teensy++ 2.0 25 4 26, 27
Arduino Uno 9 8 10
Arduino Leonardo 5 13 (none)
Arduino Mega 46 48 44, 45
Wiring-S 5 6 4
Sanguino 13 14 12
15 | 16 | If the Input Capture pin is not available, you may want to consider [NeoHWSerial](https://github.com/SlashDevin/NeoHWSerial) or [NeoSWSerial](https://github.com/SlashDevin/NeoSWSerial). 17 | 18 | # RX character interrupt 19 | 20 | To handle received characters with your procedure, you must register it with the `NeoICSerial` class or your instance: 21 | 22 | #include 23 | NeoICSerial serial_port; 24 | 25 | volatile uint32_t newlines = 0UL; 26 | 27 | static void handleRxChar( uint8_t c ) 28 | { 29 | if (c == '\n') 30 | newlines++; 31 | } 32 | 33 | void setup() 34 | { 35 | serial_port.attachInterrupt( handleRxChar ); 36 | // OR NeoICSerial::attachInterrupt( handleRxChar ); 37 | serial_port.begin( 9600 ); 38 | } 39 | 40 | The registered procedure will be called from the ISR whenever a character is received. The received character **will not** be stored in the `rx_buffer`, and it **will not** be returned from `read()`. Any characters that were received and buffered before `attachInterrupt` was called remain in `rx_buffer`, and could be retrieved by calling `read()`. 41 | 42 | If `attachInterrupt` is never called, or it is passed a `NULL` procedure, the normal buffering occurs, and all received characters must be obtained by calling `read()`. 43 | 44 | # TX complete interrupt 45 | 46 | To detect when all characters have been transmitted, you must register it with the `NeoICSerial` class or your instance: 47 | 48 | ``` 49 | NeoICSerial serial_port; 50 | NeoICSerial::attachTxCompleteInterrupt( handleTxComplete ); 51 | // OR 52 | serial_port.attachTxCompleteInterrupt( handleTxComplete ); 53 | ``` 54 | 55 | Remember that these registered procedures are called from an interrupt context, and they should return as quickly as possible. Taking too much time in these procedures will cause many unpredictable behaviors, including loss of received data. See the similar warnings for the built-in [`attachInterrupt`](https://www.arduino.cc/en/Reference/AttachInterrupt) for digital pins. 56 | 57 | # Differences from current AltSoftSerial 58 | 59 | Support for Arduino IDE v1.0 was removed. 60 | 61 | New methods were added for the user-defined IRS: `attachInterrupt`/`detachInterrupt` and `attachTxCompleteInterrupt`/`detachTxCompleteInterrupt`. 62 | 63 | Methods for compatibilty with other software serial libraries were removed: 64 | ``` 65 | // for drop-in compatibility with NewSoftSerial, rxPin & txPin ignored 66 | AltSoftSerial(uint8_t rxPin, uint8_t txPin, bool inverse = false) { } 67 | ``` 68 | -------------------------------------------------------------------------------- /config/NeoICSerial_Boards.h: -------------------------------------------------------------------------------- 1 | /* An Alternative Software Serial Library 2 | * http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html 3 | * Copyright (c) 2014 PJRC.COM, LLC, Paul Stoffregen, paul@pjrc.com 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | * THE SOFTWARE. 22 | */ 23 | 24 | 25 | // Teensy 2.0 26 | // 27 | #if defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY) 28 | 29 | //#define ALTSS_USE_TIMER1 30 | //#define INPUT_CAPTURE_PIN 22 // receive 31 | //#define OUTPUT_COMPARE_A_PIN 14 // transmit 32 | //#define OUTPUT_COMPARE_B_PIN 15 // unusable PWM 33 | //#define OUTPUT_COMPARE_C_PIN 4 // unusable PWM 34 | 35 | #define ALTSS_USE_TIMER3 36 | #define INPUT_CAPTURE_PIN 10 // receive 37 | #define OUTPUT_COMPARE_A_PIN 9 // transmit 38 | 39 | 40 | 41 | // Teensy++ 2.0 42 | // 43 | #elif defined(__AVR_AT90USB1286__) && defined(CORE_TEENSY) 44 | 45 | #define ALTSS_USE_TIMER1 46 | #define INPUT_CAPTURE_PIN 4 // receive 47 | #define OUTPUT_COMPARE_A_PIN 25 // transmit 48 | #define OUTPUT_COMPARE_B_PIN 26 // unusable PWM 49 | #define OUTPUT_COMPARE_C_PIN 27 // unusable PWM 50 | 51 | //#define ALTSS_USE_TIMER3 52 | //#define INPUT_CAPTURE_PIN 17 // receive 53 | //#define OUTPUT_COMPARE_A_PIN 16 // transmit 54 | //#define OUTPUT_COMPARE_B_PIN 15 // unusable PWM 55 | //#define OUTPUT_COMPARE_C_PIN 14 // unusable PWM 56 | 57 | 58 | // Teensy 3.x 59 | // 60 | #elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) 61 | #define ALTSS_USE_FTM0 62 | #define INPUT_CAPTURE_PIN 20 // receive (FTM0_CH5) 63 | #define OUTPUT_COMPARE_A_PIN 21 // transmit (FTM0_CH6) 64 | #define OUTPUT_COMPARE_B_PIN 22 // unusable PWM (FTM0_CH0) 65 | #define OUTPUT_COMPARE_C_PIN 23 // PWM usable fixed freq 66 | #define OUTPUT_COMPARE_D_PIN 5 // PWM usable fixed freq 67 | #define OUTPUT_COMPARE_E_PIN 6 // PWM usable fixed freq 68 | #define OUTPUT_COMPARE_F_PIN 9 // PWM usable fixed freq 69 | #define OUTPUT_COMPARE_G_PIN 10 // PWM usable fixed freq 70 | 71 | 72 | // Wiring-S 73 | // 74 | #elif defined(__AVR_ATmega644P__) && defined(WIRING) 75 | 76 | #define ALTSS_USE_TIMER1 77 | #define INPUT_CAPTURE_PIN 6 // receive 78 | #define OUTPUT_COMPARE_A_PIN 5 // transmit 79 | #define OUTPUT_COMPARE_B_PIN 4 // unusable PWM 80 | 81 | 82 | 83 | // Arduino Uno, Duemilanove, LilyPad, etc 84 | // 85 | #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) 86 | 87 | #define ALTSS_USE_TIMER1 88 | #define INPUT_CAPTURE_PIN 8 // receive 89 | #define OUTPUT_COMPARE_A_PIN 9 // transmit 90 | #define OUTPUT_COMPARE_B_PIN 10 // unusable PWM 91 | 92 | 93 | // Arduino Leonardo & Yun (from Cristian Maglie) 94 | // 95 | #elif defined(ARDUINO_AVR_YUN) || defined(ARDUINO_AVR_LEONARDO) || defined(__AVR_ATmega32U4__) 96 | 97 | //#define ALTSS_USE_TIMER1 98 | //#define INPUT_CAPTURE_PIN 4 // receive 99 | //#define OUTPUT_COMPARE_A_PIN 9 // transmit 100 | //#define OUTPUT_COMPARE_B_PIN 10 // unusable PWM 101 | //#define OUTPUT_COMPARE_C_PIN 11 // unusable PWM 102 | 103 | #define ALTSS_USE_TIMER3 104 | #define INPUT_CAPTURE_PIN 13 // receive 105 | #define OUTPUT_COMPARE_A_PIN 5 // transmit 106 | 107 | 108 | // Arduino Mega 109 | // 110 | #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 111 | 112 | //#define ALTSS_USE_TIMER4 113 | //#define INPUT_CAPTURE_PIN 49 // receive 114 | //#define OUTPUT_COMPARE_A_PIN 6 // transmit 115 | //#define OUTPUT_COMPARE_B_PIN 7 // unusable PWM 116 | //#define OUTPUT_COMPARE_C_PIN 8 // unusable PWM 117 | 118 | #define ALTSS_USE_TIMER5 119 | #define INPUT_CAPTURE_PIN 48 // receive 120 | #define OUTPUT_COMPARE_A_PIN 46 // transmit 121 | #define OUTPUT_COMPARE_B_PIN 45 // unusable PWM 122 | #define OUTPUT_COMPARE_C_PIN 44 // unusable PWM 123 | 124 | 125 | 126 | // Sanguino 127 | #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) 128 | #define ALTSS_USE_TIMER1 129 | #define INPUT_CAPTURE_PIN 14 // receive 130 | #define OUTPUT_COMPARE_A_PIN 13 // transmit 131 | #define OUTPUT_COMPARE_B_PIN 12 // unusable PWM 132 | 133 | 134 | // Unknown board 135 | #else 136 | #error "Please define your board timer and pins" 137 | #endif 138 | 139 | -------------------------------------------------------------------------------- /config/NeoICSerial_Timers.h: -------------------------------------------------------------------------------- 1 | /* An Alternative Software Serial Library 2 | * http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html 3 | * Copyright (c) 2014 PJRC.COM, LLC, Paul Stoffregen, paul@pjrc.com 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | * THE SOFTWARE. 22 | */ 23 | 24 | #if defined(ALTSS_USE_TIMER1) 25 | #define CONFIG_TIMER_NOPRESCALE() (TIMSK1 = 0, TCCR1A = 0, TCCR1B = (1<