Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/lgt8f/libraries/SoftwareSerial/SoftwareSerial.cpp b/lgt8f/libraries/SoftwareSerial/SoftwareSerial.cpp
- index 7d3cde6..17a182b 100644
- --- a/lgt8f/libraries/SoftwareSerial/SoftwareSerial.cpp
- +++ b/lgt8f/libraries/SoftwareSerial/SoftwareSerial.cpp
- @@ -43,23 +43,22 @@ http://arduiniana.org.
- #include <Arduino.h>
- #include <SoftwareSerial.h>
- // #include <util/delay_basic.h>
- -// replace modified _delay_loop_2() for LGT8F328P
- -/*
- - Delay loop using a 16-bit counter \c __count, so up to 65536
- - iterations are possible. (The value 65536 would have to be
- - passed as 0.) The loop executes four CPU cycles per iteration,
- - not including the overhead the compiler requires to setup the
- - counter register pair.
- -
- - Thus, at a CPU speed of 1 MHz, delays of up to about 262.1
- - milliseconds can be achieved.
- - */
- -static void SoftwareSerial::_delay_loop_2(uint16_t __count)
- +// copy from <util/delay_basic.h> with two modifications
- +// - to reduce CALL/RET overhead, use always_inline
- +// - NOP afrer BRNE ensures delay time
- +// be careful to differences of instruction execute cycle
- +// NOP 1
- +// BRNE 1:branch not taken, 2:taken
- +// SBIW 2:AVR processor, 1:LGT8x processor
- +// CALL 4
- +// RET 4:AVR processor, 2:LGT8x processor
- +// at CPU speed of 1MHz, up to 262.1ms (AVR) or 196.6ms (LGT8x)
- +__attribute__((always_inline)) static inline void SoftwareSerial::_delay_loop_2(uint16_t __count)
- {
- __asm__ volatile (
- "1: sbiw %0,1" "\n\t"
- - "nop" "\n\t" // LGT8F328P's SBIW takes 1 clock, adjust
- - "brne 1b"
- + "brne 1b" "\n\t"
- + "nop"
- : "=w" (__count)
- : "0" (__count)
- );
- @@ -99,7 +98,7 @@ inline void DebugPulse(uint8_t, uint8_t) {}
- //
- /* static */
- -inline void SoftwareSerial::tunedDelay(uint16_t delay) {
- +__attribute__((always_inline)) static inline void SoftwareSerial::tunedDelay(uint16_t delay) {
- _delay_loop_2(delay);
- }
- @@ -347,23 +346,40 @@ void SoftwareSerial::begin(uint16_t rxcenter, uint16_t rxintra, uint16_t rxsto
- listen();
- }
- +// Calculated by gcc-7.3.0
- +#if defined(__LGT8F__)
- +#define DELAY_CYCLE 3
- +#define TXDELAY 14
- +#define RXDELAY_BEFORECENTER 44 /*45*/
- +#define RXDELAY_CENTER2READ 14
- +#define RXDELAY_READLOOP 14
- +#define RXDELAY_BEFORESTOP 28 /*25*/
- +#define RXDELAY_AFTERSTOP 6
- +#else
- +#define DELAY_CYCLE 4
- +#define TXDELAY 16
- +#define RXDELAY_BEFORECENTER 73
- +#define RXDELAY_CENTER2READ 20
- +#define RXDELAY_READLOOP 15
- +#define RXDELAY_BEFORESTOP 33 /*32*/
- +#define RXDELAY_AFTERSTOP 11
- +#endif
- void SoftwareSerial::begin(long speed)
- {
- _rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0;
- - // Precalculate the various delays, in number of 4-cycle delays
- - uint16_t bit_delay = (F_CPU / speed) / 4;
- + // Precalculate the various delays, in number of delay cycles
- + uint16_t bit_delay = (F_CPU / speed) / DELAY_CYCLE;
- // 12 (gcc 4.8.2) or 13 (gcc 4.3.2) cycles from start bit to first bit,
- // 15 (gcc 4.8.2) or 16 (gcc 4.3.2) cycles between bits,
- // 12 (gcc 4.8.2) or 14 (gcc 4.3.2) cycles from last bit to stop bit
- // These are all close enough to just use 15 cycles, since the inter-bit
- // timings are the most critical (deviations stack 8 times)
- - _tx_delay = subtract_cap(bit_delay, 15 / 4);
- + _tx_delay = subtract_cap(bit_delay, TXDELAY / DELAY_CYCLE);
- // Only setup rx when we have a valid PCINT for this pin
- if (digitalPinToPCICR((int8_t)_receivePin)) {
- - #if GCC_VERSION > 40800
- // Timings counted from gcc 4.8.2 output. This works up to 115200 on
- // 16Mhz and 57600 on 8Mhz.
- //
- @@ -371,16 +387,20 @@ void SoftwareSerial::begin(long speed)
- // interrupt flag is set, 4 cycles before the PC is set to the right
- // interrupt vector address and the old PC is pushed on the stack,
- // and then 75 cycles of instructions (including the RJMP in the
- - // ISR vector table) until the first delay. After the delay, there
- - // are 17 more cycles until the pin value is read (excluding the
- - // delay in the loop).
- + // ISR vector table) until the first delay (RXDELAY_BEFORECENTER).
- + // After the delay, there are 17 more cycles until the pin value is read
- + // (excluding the delay in the loop, RXDELAY_CENTER2READ).
- // We want to have a total delay of 1.5 bit time. Inside the loop,
- // we already wait for 1 bit time - 23 cycles, so here we wait for
- // 0.5 bit time - (71 + 18 - 22) cycles.
- - _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 75 + 17 - 23) / 4);
- + _rx_delay_centering = subtract_cap(bit_delay / 2,
- + (4 + 4 + RXDELAY_BEFORECENTER +
- + RXDELAY_CENTER2READ -
- + RXDELAY_READLOOP) / DELAY_CYCLE);
- // There are 23 cycles in each loop iteration (excluding the delay)
- - _rx_delay_intrabit = subtract_cap(bit_delay, 23 / 4);
- + _rx_delay_intrabit = subtract_cap(bit_delay,
- + RXDELAY_READLOOP / DELAY_CYCLE);
- // There are 37 cycles from the last bit read to the start of
- // stopbit delay and 11 cycles from the delay until the interrupt
- @@ -389,15 +409,9 @@ void SoftwareSerial::begin(long speed)
- // delay will be at 1/4th of the stopbit. This allows some extra
- // time for ISR cleanup, which makes 115200 baud at 16Mhz work more
- // reliably
- - _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (37 + 11) / 4);
- - #else // Timings counted from gcc 4.3.2 output
- - // Note that this code is a _lot_ slower, mostly due to bad register
- - // allocation choices of gcc. This works up to 57600 on 16Mhz and
- - // 38400 on 8Mhz.
- - _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 97 + 29 - 11) / 4);
- - _rx_delay_intrabit = subtract_cap(bit_delay, 11 / 4);
- - _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (44 + 17) / 4);
- - #endif
- + _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4,
- + (RXDELAY_BEFORESTOP + RXDELAY_AFTERSTOP) /
- + DELAY_CYCLE);
- // Enable the PCINT for the entire port here, but never disable it
- diff --git a/lgt8f/libraries/SoftwareSerial/SoftwareSerial.h b/lgt8f/libraries/SoftwareSerial/SoftwareSerial.h
- index 1e17b2d..b2412f9 100644
- --- a/lgt8f/libraries/SoftwareSerial/SoftwareSerial.h
- +++ b/lgt8f/libraries/SoftwareSerial/SoftwareSerial.h
- @@ -85,7 +85,7 @@ private:
- static uint16_t subtract_cap(uint16_t num, uint16_t sub);
- // private static method for timing
- - static void _delay_loop_2(uint16_t __count);
- + static inline void _delay_loop_2(uint16_t __count);
- static inline void tunedDelay(uint16_t delay);
- public:
Add Comment
Please, Sign In to add comment