Skip to content

Commit

Permalink
V1.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
felias-fogg committed Sep 25, 2023
1 parent a5dd0b6 commit 90b98c7
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 49 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/LibraryBuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ jobs:
steps:
- uses: actions/checkout@v2
- uses: arduino/arduino-lint-action@v1
# with:
# library-manager: update
with:
library-manager: update
build:
name: ${{ matrix.arduino-boards-fqbn }} - test compiling examples

Expand Down
64 changes: 36 additions & 28 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,36 +1,44 @@
0.9.1 Initial commit
0.9.1a setRxIntMsk static / recv eliminated
0.9.1b curr deleted
0.9.2 handle_interrupt redesigned (is faster now and terminates earlier)
1.0.0 first publication
1.1.0 Complete redesign of receiving ISR. It is now all inline assembler,
it uses only 4 registers + SREG and employs OCRA for bit timing. Is now millis
interrupt safe with 125,000 bps and still has one bit time (4
microseconds) between bytes when working at 250,000 bps with the millis
interrupt disabled.
1.1.1 Rearranged the initial instructions.
1.1.2 Corrected an annoying typo in the write method that led to the
problem that the single-wire mode did not work anymore, modified
the example, and declared setRxIntMsk to be protected so that
derived classes can use it
1.1.3 fixed the problem that the sending routine starts before the
stop bit of the receiving byte is fully received, which led to
problems with debugWIRE
handle_interrupt is now a private method (as it should!)
1.1.4 removed the last change since it is impossible to parametrize it
for different MCUs
1.1.5 changed default timer for those MCUs that do not support input
capture in their Timer1 modules
added some code for Mega2560 & 1280 so that they can read from
the respective input port (which cannot be addressed by IN and OUT)
1.2.0 - added _finishSendingEarly as a protected member that can be used
in order to return before the end of the stop bit when sinding.
This turned out to be necessary for dwSerial (the debugWIRE
communcation class) because after changing the
communication speed, you have to recalibrate communication speed
which cannot be done by using the usual IRQ driven input.
- added another possible prescaler (256) for ultra-slow bps down to 20
bps
1.1.7 moved "enable input capture interrupt" to the start of the stop
bit when writing a byte; this way, we do not miss the start bit
of a following input byte!
1.1.6 changed attribute definitions from private to protected
added TOV to the compile-time constants in SingleWireSerial_config.h
use prescaler of 64 for all communication speeds lower than 4000
bps, meaning that now we can deal with down to 40 bps
GitHub actions are used to compile the examples when changes are
made
made some adjustments in SingleWireSerial_config.h
1.1.7 moved "enable input capture interrupt" to the start of the stop
bit when writing a byte; this way, we do not miss the start bit
of a following input byte!
1.1.5 changed default timer for those MCUs that do not support input
capture in their Timer1 modules
added some code for Mega2560 & 1280 so that they can read from
the respective input port (which cannot be addressed by IN and OUT)
1.1.4 removed the last change since it is impossible to parametrize it
for different MCUs
1.1.3 fixed the problem that the sending routine starts before the
stop bit of the receiving byte is fully received, which led to
problems with debugWIRE
handle_interrupt is now a private method (as it should!)
1.1.2 Corrected an annoying typo in the write method that led to the
problem that the single-wire mode did not work anymore, modified
the example, and declared setRxIntMsk to be protected so that
derived classes can use it
1.1.1 Rearranged the initial instructions.
1.1.0 Complete redesign of receiving ISR. It is now all inline assembler,
it uses only 4 registers + SREG and employs OCRA for bit timing. Is now millis
interrupt safe with 125,000 bps and still has one bit time (4
microseconds) between bytes when working at 250,000 bps with the millis
interrupt disabled.
1.0.0 first publication
0.9.2 handle_interrupt redesigned (is faster now and terminates earlier)
0.9.1b curr deleted
0.9.1a setRxIntMsk static / recv eliminated
0.9.1 Initial commit

2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.1.7",
"version": "1.2.0",
"name": "SingleWireSerial",
"keywords": "Serial communication, UART, Input Capture",
"description": "Software serial library using a single line in half-duplex mode. In addition, it uses the input capture feature of timer 1 for improved accuracy. Works reliably up to 125,000 bps with millis interrupt enabled. With millis interrupt disabled, it works up to 250,000 bps. Tested with Arduino Uno and Mega, but should work on other boards/MCUs.",
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=SingleWireSerial
version=1.1.7
version=1.2.0
author=Bernhard Nebel <nebel@hinterm-ziel.de>
maintainer=Bernhard Nebel <nebel@hinterm-ziel.de>
sentence=Robust software serial library using a single line in half-duplex mode.
Expand Down
31 changes: 15 additions & 16 deletions src/SingleWireSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ void SingleWireSerial::handle_interrupt()

// load CTC setting, check for slowness, store TCNT and TCCRB, clear flag
"lds r24, _setCTC ; set counter to CTC operation\n\t"
"sbrs r24, %[SLOWCS] ; when slow bit is set, skip\n\t"
"sbrc r24, %[FASTCS] ; when fast bit is clear, skip\n\t"
"adiw r30, %[STARTOFFSET] ; time that is unaccounted for\n\t"
"sts %B[TCNTaddr], r31 ; store back to TCNT\n\t"
"sts %A[TCNTaddr], r30\n\t"
Expand Down Expand Up @@ -229,17 +229,14 @@ void SingleWireSerial::handle_interrupt()
#endif
"reti ; done\n\t"
:
:
#if _DEBUG
[PORTCaddr] "I" (_SFR_IO_ADDR(PORTC)),
#endif
: [PORTCaddr] "I" (_SFR_IO_ADDR(PORTC)),
[ICRaddr] "M" (&ICR),
[TCNTaddr] "M" (&TCNT),
[STARTOFFSET] "I" (35),
[BUFFMASK] "M" (_SS_MAX_RX_BUFF-1),
[OCRAaddr] "M" (&OCRA),
[TCCRBaddr] "M" (&TCCRB),
[TIFRIOaddr] "M" (_SFR_IO_ADDR(TIFR)),
[TIFRIOaddr] "M" (_SFR_IO_ADDR(TIFR)),
[OCFAconst] "M" (OCFA),
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
[INPORTaddr] "n" (&ICPIN),
Expand All @@ -249,7 +246,7 @@ void SingleWireSerial::handle_interrupt()
[INPIN] "I" (ICBIT),
[ENDOFFSET] "M" (10),
[ICFconst] "M" (ICF),
[SLOWCS] "M" (CS0));
[FASTCS] "M" (CS0));
}
#else // not _FASTIRQ
{
Expand Down Expand Up @@ -291,9 +288,7 @@ void SingleWireSerial::handle_interrupt()
: [ICRaddr] "M" (&ICR),
[TCCRBaddr] "M" (&TCCRB),
[EDGEUP] "M" (_BV(ICES)),
#if _DEBUG
[PORTCaddr] "I" (_SFR_IO_ADDR(PORTC))
#endif
);
setRxIntMsk(false); // disable the ICR interrupts
ch = 0;
Expand Down Expand Up @@ -359,10 +354,7 @@ void SingleWireSerial::handle_interrupt()
#endif
"reti"
:
:
#if _DEBUG
[PORTCaddr] "I" (_SFR_IO_ADDR(PORTC))
#endif
: [PORTCaddr] "I" (_SFR_IO_ADDR(PORTC))
);
}
#endif // not _FASTIRQ
Expand Down Expand Up @@ -425,6 +417,10 @@ void SingleWireSerial::begin(long speed)
if (bit_delay100 > 400000UL) {
bit_delay100 = bit_delay100/64;
prescaler = _BV(CS1)|_BV(CS0); // prescaler = 64
if (bit_delay100 > 400000UL) {
bit_delay100 = bit_delay100/4;
prescaler = _BV(CS2); // prescaler = 256
}
} else {
prescaler = _BV(CS0); // prescaler = 1
}
Expand Down Expand Up @@ -523,7 +519,8 @@ size_t SingleWireSerial::write(uint8_t data)
}
TIFR |= _BV(OCFA);
data >>= 1;
} while (!(TIFR & _BV(OCFA)));
}
while (!(TIFR & _BV(OCFA)));
ICDDR &= ~_BV(ICBIT); // make output again high-impedance for stop bit
DebugPulse(0x02);
} else { // twoWire!
Expand All @@ -537,15 +534,17 @@ size_t SingleWireSerial::write(uint8_t data)
OCPORT &= ~_BV(OCBIT); // make output low
TIFR |= _BV(OCFA);
data >>= 1;
} while (!(TIFR & _BV(OCFA)));
}
while (!(TIFR & _BV(OCFA)));
OCPORT |= _BV(OCBIT); // make output again high for stop bit
}
if (_finishSendingEarly) OCRA = _bitDelay >> 1; // wait only half the stop bit (needed when a response might come early)
TIFR |= _BV(OCFA); // clear overflow flag

SREG = oldSREG; // enable interrupts again
setRxIntMsk(true); //enable input capture input interrupts again

while (!(TIFR & _BV(OCFA))); // wait for stop bit to finish
while (!(TIFR & _BV(OCFA))); // wait for stop bit (or half stop bit) to finish
DebugPulse(0x01);
return 1;
}
Expand Down
2 changes: 1 addition & 1 deletion src/SingleWireSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
class SingleWireSerial : public Stream
{
protected:
// only 1 object possible, so everything is static
bool _finishSendingEarly = false;
static bool _twoWire;
static bool _waitBeforeSending;
static bool _buffer_overflow;
Expand Down

0 comments on commit 90b98c7

Please sign in to comment.