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

T3.x,T4.x LC Serial half duplex support #489

Merged
merged 2 commits into from
Nov 20, 2020

Conversation

KurtE
Copy link
Contributor

@KurtE KurtE commented Sep 9, 2020

Migrating the half duplex support I did in the Stagnant and out of date PR to enhance Uarts:

#419 Which I will close out.

To try to support Half duplex mode in a similar way like we do for RS485 like support.

With T3.x made use of bitband address for the TX Direction setting, so
Except for the begin which calls format, no code changed, we simply stored the bitband address of the TXDIR flag into the TXDIR variable that was already used for the set direction flag.

For T4.x - it is a little more work as there is no bitband support on M7 processors. For GPIO there is a Set and Clear register which we use, but for the appropriate UART register there is no such setup of registers. So I have to special case we are in that mode and do it... Also since not atomic I cli/sei...

Serial Half Duplex - Fix T4Serial1 and T-LC Serial1-3

Updates: T4
T4 Serial 1 did not have proper settings for IOMUXC_LPUART6_TX_SELECT_INPUT

Tested T4.1 Serial1-8

Tested T3.5 Serial1-6

T3.6 - Added support for LPUART which is Serial6 which now works.

T-LC
Make half duplex work on T-LC on Serials1-3

Tested on on T3.5 1-6

Test sketch:

#define DEBUG_PIN 2
#define LOOP_DELAY_MS 50

#ifndef SERIAL_HALF_DUPLEX
#error Requires Teensy core with half duplex support
#endif
#define FORMAT SERIAL_HALF_DUPLEX
// Serial3 information - Say this is our Main Serial port
#define SERIALM Serial6
#define SERIALE Serial1
#define SERIAL_BAUD 115200
elapsedMillis  em_last_recv;
uint8_t receive_buffer[80];
uint8_t receive_index = 0;

void setup() {
  while (!Serial && millis() < 5000) ; // wait up to 5 seconds for terminal monitor
  pinMode(DEBUG_PIN, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(4, OUTPUT);

  // Setup Serial3 for Half duplex:
  //SERIALM.setTX(53);
  for (int i=0;i<6;i++) {
    digitalToggleFast(4);
    delay(2);
  }
#ifdef FORMAT
  Serial.printf("Serial ports using format %x\n", FORMAT);
  SERIALM.begin(SERIAL_BAUD, FORMAT); // would probably want to see how close we are
  SERIALE.begin(SERIAL_BAUD, FORMAT); // would probably want to see how close we arer
#else
  Serial.println("Serial ports using default format");
  SERIALM.begin(SERIAL_BAUD); // would probably want to see how close we are
  SERIALE.begin(SERIAL_BAUD); // would probably want to see how close we arer
#endif
  
  Serial.println("After Serial begins"); Serial.flush();
  for (int i=0;i<6;i++) {
    digitalToggleFast(4);
    delay(2);
  }
#if 0
  Serial.printf("LPUART_CTRL: %x\n", (uint32_t)LPUART0_CTRL);
  LPUART0_CTRL = LPUART0_CTRL & ~(LPUART_CTRL_TE);
  Serial.printf("After turn of TE? LPUART_CTRL: %x\n", (uint32_t)LPUART0_CTRL);
#endif
//    Serial.printf("Serial1 C1:%x C2:%x C3:%x S1:%x, D1 Config:%x\n", UART0_C1, UART0_C2, UART0_C3, UART0_S1, CORE_PIN1_CONFIG);
//    Serial.printf("Serial2 C1:%x C2:%x C3:%x S1:%x, D10 Config:%x\n", UART1_C1, UART1_C2, UART1_C3, UART1_S1, CORE_PIN10_CONFIG);
  em_last_recv = 0;
}

uint32_t loop_count = 0;

void loop() {
  // Lets see if we have anything coming in on the Echo PORT
  if (SERIALE.available()) {
    digitalWriteFast(5, HIGH);
    while (SERIALE.available()) {
      uint8_t ch = SERIALE.read();
      receive_buffer[receive_index++] = ch;
      if (ch == '\n') {
        receive_buffer[receive_index] = 0;  // Null terminate.
        // BUGBUG:: Put in line instead of calls
        SERIALE.write((char*)receive_buffer);
        receive_index = 0;
      }
      em_last_recv = 0;
    }
    digitalWriteFast(5, LOW);
  }

  // Lets see if we have anything coming in on the main port
  if (SERIALM.available()) {
    digitalWriteFast(4, HIGH);
    while (SERIALM.available()) {
      uint8_t ch = SERIALM.read();
      Serial.write(ch);
      em_last_recv = 0;
    }
    digitalWriteFast(4, LOW);
  }

  if (em_last_recv > LOOP_DELAY_MS) {
    digitalToggleFast(13);
    // output new packet
    SERIALM.printf("Loop: %d\n", loop_count++);
//    Serial.printf("Serial1 C1:%x C2:%x C3:%x S1:%x, D1 Config:%x\n", UART0_C1, UART0_C2, UART0_C3, UART0_S1, CORE_PIN1_CONFIG);
//    Serial.printf("Serial2 C1:%x C2:%x C3:%x S1:%x, D10 Config:%x\n\n", UART1_C1, UART1_C2, UART1_C3, UART1_S1, CORE_PIN10_CONFIG);
    em_last_recv = 0;
  }
}

Migrating the half duplex support I did in the Stagnant and out of date PR to enhance Uarts: PaulStoffregen#419

To try to support Half duplex mode in a similar way like we do for RS485 like support.

With T3.x made use of bitband address for the TX Direction setting, so
Except for the begin which calls format, no code changed, we simply stored the bitband address of the TXDIR flag into the TXDIR variable that was already used for the set direction flag.

For T4.x - it is a little more work as there is no bitband support on M7 processors.  For GPIO there is a Set and Clear register which we use, but for the appropriate UART register there is no such setup of registers.  So I have to special case we are in that mode and do it... Also since not atomic I cli/sei...

Serial Half Duplex - Fix T4Serial1 and T-LC Serial1-3

Updates: T4
T4 Serial 1 did not have proper settings for IOMUXC_LPUART6_TX_SELECT_INPUT

Tested T4.1 Serial1-8

Tested T3.5 Serial1-6

T3.6 - Added support for LPUART which is Serial6 which now works.

T-LC
Make half duplex work on T-LC on Serials1-3

Tested on on T3.5 1-6
@PaulStoffregen
Copy link
Owner

PaulStoffregen commented Sep 10, 2020

I believe we should merge this, but first let's talk about the public API.

I'd like to follow the convention of SERIAL_8N1_DETAILS for the format constants. Somehow we have SERIAL_2STOP_BITS in the code, which really should be constants like SERIAL_8N2.

Any chance I can talk you into one more commit to make the public define SERIAL_8N1_HALF_DUPLEX?

@KurtE
Copy link
Contributor Author

KurtE commented Sep 10, 2020

I'd like to follow the convention of SERIAL_8N1_DETAILS for the format constants. Somehow we have SERIAL_2STOP_BITS in the code, which really should be constants like SERIAL_8N2.

Any chance I can talk you into one more commit to make the public define SERIAL_8N1_HALF_DUPLEX?

Of course - I just defined the bit, with the idea like all of the others, it can and should be combined like this... Will define them this morning

Added in define in standard Arduino setup.

I also added for 7E1 and 7O1 as well.
@KurtE
Copy link
Contributor Author

KurtE commented Sep 10, 2020

@PaulStoffregen - I added the define as you mentioned, plus added 7E1 and 7O1 as well, to show that this can be combined like others. Updated my test sketch to try out parity. I needed to mask off the high bit on receive as to check again '\n' ...

I tested again on T4.1 and LC and T3.2 (just Serial1/Serial2) to make sure I did not screw up anything

#define DEBUG_PIN 2
#define LOOP_DELAY_MS 50

#ifndef SERIAL_HALF_DUPLEX
#error Requires Teensy core with half duplex support
#endif
#define FORMAT SERIAL_7O1_HALF_DUPLEX
// Serial3 information - Say this is our Main Serial port
#define SERIALM Serial2
#define SERIALE Serial1
#define SERIAL_BAUD 115200
elapsedMillis  em_last_recv;
uint8_t receive_buffer[80];
uint8_t receive_index = 0;

void setup() {
  while (!Serial && millis() < 5000) ; // wait up to 5 seconds for terminal monitor
  pinMode(DEBUG_PIN, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(4, OUTPUT);

  // Setup Serial3 for Half duplex:
  //SERIALM.setTX(53);
  for (int i=0;i<6;i++) {
    digitalToggleFast(4);
    delay(2);
  }
#ifdef FORMAT
  Serial.printf("Serial ports using format %x\n", FORMAT);
  SERIALM.begin(SERIAL_BAUD, FORMAT); // would probably want to see how close we are
  SERIALE.begin(SERIAL_BAUD, FORMAT); // would probably want to see how close we arer
#else
  Serial.println("Serial ports using default format");
  SERIALM.begin(SERIAL_BAUD); // would probably want to see how close we are
  SERIALE.begin(SERIAL_BAUD); // would probably want to see how close we arer
#endif
  
  Serial.println("After Serial begins"); Serial.flush();
  for (int i=0;i<6;i++) {
    digitalToggleFast(4);
    delay(2);
  }
#if 0
  Serial.printf("LPUART_CTRL: %x\n", (uint32_t)LPUART0_CTRL);
  LPUART0_CTRL = LPUART0_CTRL & ~(LPUART_CTRL_TE);
  Serial.printf("After turn of TE? LPUART_CTRL: %x\n", (uint32_t)LPUART0_CTRL);
#endif
//    Serial.printf("Serial1 C1:%x C2:%x C3:%x S1:%x, D1 Config:%x\n", UART0_C1, UART0_C2, UART0_C3, UART0_S1, CORE_PIN1_CONFIG);
//    Serial.printf("Serial2 C1:%x C2:%x C3:%x S1:%x, D10 Config:%x\n", UART1_C1, UART1_C2, UART1_C3, UART1_S1, CORE_PIN10_CONFIG);
  em_last_recv = 0;
}

uint32_t loop_count = 0;

void loop() {
  // Lets see if we have anything coming in on the Echo PORT
  if (SERIALE.available()) {
    digitalWriteFast(5, HIGH);
    while (SERIALE.available()) {
      uint8_t ch = SERIALE.read() & 0x7f;  // strip off possible parity bit...
      receive_buffer[receive_index++] = ch;
      if (ch == '\n') {
        receive_buffer[receive_index] = 0;  // Null terminate.
        // BUGBUG:: Put in line instead of calls
        SERIALE.write((char*)receive_buffer);
        receive_index = 0;
      }
      em_last_recv = 0;
    }
    digitalWriteFast(5, LOW);
  }

  // Lets see if we have anything coming in on the main port
  if (SERIALM.available()) {
    digitalWriteFast(4, HIGH);
    while (SERIALM.available()) {
      uint8_t ch = SERIALM.read() & 0x7f;
      Serial.write(ch);
      em_last_recv = 0;
    }
    digitalWriteFast(4, LOW);
  }

  if (em_last_recv > LOOP_DELAY_MS) {
    digitalToggleFast(13);
    // output new packet
    SERIALM.printf("Loop: %d\n", loop_count++);
//    Serial.printf("Serial1 C1:%x C2:%x C3:%x S1:%x, D1 Config:%x\n", UART0_C1, UART0_C2, UART0_C3, UART0_S1, CORE_PIN1_CONFIG);
//    Serial.printf("Serial2 C1:%x C2:%x C3:%x S1:%x, D10 Config:%x\n\n", UART1_C1, UART1_C2, UART1_C3, UART1_S1, CORE_PIN10_CONFIG);
    em_last_recv = 0;
  }
}

@PaulStoffregen
Copy link
Owner

Looks like this fell off my radar. Should this go into 1.54-beta6?

@KurtE
Copy link
Contributor Author

KurtE commented Nov 20, 2020 via email

@PaulStoffregen
Copy link
Owner

ok, merging now...

@PaulStoffregen PaulStoffregen merged commit 1268d26 into PaulStoffregen:master Nov 20, 2020
@KurtE KurtE deleted the serial_half_duplex branch November 20, 2020 22:19
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

Successfully merging this pull request may close these issues.

2 participants