Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Any way of using Half-Duplex Serial? #197

Open
jonathanmlang opened this issue Mar 19, 2024 · 7 comments
Open

Any way of using Half-Duplex Serial? #197

jonathanmlang opened this issue Mar 19, 2024 · 7 comments

Comments

@jonathanmlang
Copy link

I cannot seem to find any way of implementing Half-Duplex serial. Is it supported? Can't find any mention of it anywhere in this library even though the atmega4809 datasheet mentions support for it.
Ive come from the spence konde megatinycore and I can do:

Serial1.begin(9600, (SERIAL_8N1 | SERIAL_HALF_DUPLEX));

and that works great for attiny chips, but that does not work here and cannot find an alternative.
Can you help?

@MCUdude
Copy link
Owner

MCUdude commented Mar 19, 2024

It's currently not supported

@jonathanmlang
Copy link
Author

How about in the softwareserial library?

@MCUdude
Copy link
Owner

MCUdude commented Mar 19, 2024

Sorry, but the SoftwareSerial library doesn't support it either.

@jonathanmlang
Copy link
Author

Ive managed to add support myself. It was trivial.

@MCUdude
Copy link
Owner

MCUdude commented Mar 19, 2024

A PR is always welcome if you want to contribute to the project. Or if you aren't as good with the whole git thing, sharing the details here also helps.

@jonathanmlang
Copy link
Author

At line 255 in UART.cpp I changed
(*_hwserial_module).CTRLA |= USART_RXCIE_bm;
to
(*_hwserial_module).CTRLA |= (USART_RXCIE_bm | USART_LBME_bm);

Then commented out the pinmodes

// Set pin state for swapped UART pins
pinMode(set->rx_pin, INPUT_PULLUP);
//digitalWrite(set->tx_pin, HIGH);
//pinMode(set->tx_pin, OUTPUT);

then when sending:

pinMode(PIN_PC4,1);
Serial1.write(array, 24);
delay(10); //give the serial chance to get sent
while (Serial1.available()){byte d = Serial1.read();} // sent serial gets looped back, dump it into disposable variable
pinMode(PIN_PC4,0);
digitalWrite(PIN_PC4,0);

@SpenceKonde
Copy link
Contributor

You need to set ODME as well to get half duplex in most applications, because usually you need open drain mode, otherwise the to devices may fight eachother over the state of the line, potentially damaging one of them. I think on mega0's you also need to make sure the PORTx.OUT bit corresponding to the data line being used by serial is cleared, otherwise it can try to drive the pin high even in open drain mode... similar to the bug with TWI (they overrode the direction, but forgot to override the output value)

Oh and wait, no, it's definitely not that simple, not at all, because in half duplex mode you'll receive every character you send. I went to a great deal of effort to blackhole the echo. That was a pain in the arse to do - I think I had write() turn off RXEN and turn on the TXC interrupt after clearing the TXC flag. And TXC int would... turn off TXC int, read from RXDATA until RXCIF is cleared and turn on RXCIE I think? Important to not clear TXC, because we need TXC set at all times that we have finished sending data. flush() needs to be able to know whether data is currently being sent. That data is not exposed. So it stores a flag in a variable the first time it is written to, and flush() doesn't wait at all if that's not set because if nothing was sent to the serial port, you know nothing is being sent right now. If data has been sent, flush waits for TXC flag to be set. So for flush to work you must clear TXC only in write(), and if you ever use the TXC interrupt (which as I said, you need to do if you don't want to hear yourself talk), instead of clearing TXC, it should turn itself off and the write should reenable it.

And of course like all the ISRs, TXC is written in asm so I can do unholy things that save flash and improve performance. And, I know I said

I may have gone a little overboard on the USART feature support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants