#include <LiquidCrystal.h>
#include <SoftwareSerial.h>

const byte rxPin = 2;
const byte txPin = 3;

// Set up a new SoftwareSerial object
SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);

/* Display */
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);

char data_read;

unsigned char uart_chr;
char oled_chr;
char oled_pos;
char line1_active;
char line2_active;

// Extra chr as it's easier for the array to be 1-based.
char line1[18];
char line2[18];

// Message sent to MVHR unit at start-up.
unsigned char alive_str[] = {0x04, 0x06, 0xFF, 0xFF, 0xFF, 0x10, 0xFC, 0xE8, '\0'};
// unsigned char alive_str[] = {0x48, 0x65, 0x6C, 0x6C, 0x6F}; //testing

// *****************************************************************************
// FUNCTIONS
// *****************************************************************************

// Write the two lines of text to the OLED display.
void update_oled(void)
{
  // // Overwrite the display with an indication of button long-press
  // // and a hint to move to the top menu item for them to be effective.
  // if (long_press_counter >= 600) {
  //   line1[16] = '^';
  // }

  lcd.setCursor(0, 0);
  lcd.print(&line1[1]); // Line array indexes are 1-based.

  // if ((btn_set_curr_state) && (long_press_counter >= 500)) {
  //   // Conversely to below it this used less ROM than individual writes.
  //   lcd.setCursor(0, 1);
  //   lcd.print("ENTER COMMISSION");
  // }
  // else {
  lcd.setCursor(0, 1);
  lcd.print(&line2[1]);
  // }
}

void showSpalshScreen() {
  lcd.print("VENT-AXIA Remote");
  lcd.setCursor(0, 1);
  String message = "CV1.0 bmd.......";
  String message2 = "";
  for (byte i = 0; i < message.length(); i++) {
    lcd.print(message[i]);
    // delay(50);
    if (i > 7) delay(300);
  }
  // delay(1000);
}



void setup() {
  Serial.begin(9600);

  // Define pin modes for TX and RX
  pinMode(rxPin, INPUT);
  pinMode(txPin, OUTPUT);

  // Set the baud rate for the SoftwareSerial object
  mySerial.begin(9600);

  lcd.begin(16, 2);

  // Send an "alive" message to the MVHR unit:
  // (This is what the original remote did).
  // NOT ESSENTIAL : REMOVE IF ROM SPACE IS REQUIRED.
  for (int i = 0; i < sizeof(alive_str); i++) mySerial.print((char)alive_str[i]);

  showSpalshScreen();
  lcd.clear();
}

void loop() {
  // put your main code here, to run repeatedly:
  if (mySerial.available()) {
    uart_chr = mySerial.read();
    data_read = 1;

    switch (uart_chr) {
      case 0x15:
        // NAK - start of line 1
        line1_active = 1;
        oled_pos = 0;
        break;

      case 0x16:
        // SYN - end of line 1, start of line 2
        line2_active = 1;
        oled_pos = 0;
        break;

      default:
        // Record the characters for Line#1 (top)
        if ((line1_active) && (oled_pos > 0)) {
          line1[oled_pos] = uart_chr;

          if (oled_pos >= 16) {
            line1_active = 0;
          }
        }

        // Record the characters for Line#2 (bottom)
        if ((line2_active) && (oled_pos > 0)) {
          line2[oled_pos] = uart_chr;

          if (oled_pos >= 16) {
            line2_active = 0;

            update_oled();
          }
        }

        break;
    }

    oled_pos++;
  } else {
    data_read = 0;
    //
    // While we don't have data to read, do something else useful.
    //
  }
}
Vent Axia Sentinel Kinetic UARTBreakout