Trasmettere tramite seriale 9 bit

Mi spiego vorrei usare arduino per interfacciare il mio pc a un vecchio apparato che usa questo protocollo:
8bit dati
1bti mode
1 stop

e la linea alla fine deve rimanere livello basso.

magari usando le librerie softwareserial, ma non conoscendo bene il c/c++ non vorrei vare casini.
Ho aperto il file SostwareSerial.cpp ho modificano aggiungendo il metodo:

SoftwareSerial::write_9(uint8_t b,bool b9)
{
  if (_tx_delay == 0) {
    setWriteError();
    return 0;
  }

  uint8_t oldSREG = SREG;
  cli();  // turn off interrupts for a clean txmit

  // Write the start bit
  tx_pin_write(_inverse_logic ? HIGH : LOW);
  tunedDelay(_tx_delay + XMIT_START_ADJUSTMENT);

  // Write each of the 8 bits
  if (_inverse_logic)
  {
    for (byte mask = 0x01; mask; mask <<= 1)
    {
      if (b & mask) // choose bit
        tx_pin_write(LOW); // send 1
      else
        tx_pin_write(HIGH); // send 0
    
      tunedDelay(_tx_delay);
    }
    if (b9){
              tx_pin_write(LOW); // send 1
    } else{
              tx_pin_write(HIGH); // send 0
    }

    tx_pin_write(LOW); // restore pin to natural state
  }
  else
  {
    for (byte mask = 0x01; mask; mask <<= 1)
    {
      if (b & mask) // choose bit
        tx_pin_write(HIGH); // send 1
      else
        tx_pin_write(LOW); // send 0
    
      tunedDelay(_tx_delay);
    }

    tx_pin_write(HIGH); // restore pin to natural state
    if (b9){
              tx_pin_write(HIGH); // send 1
    } else{
              tx_pin_write(LOW); // send 0
    }
  }

  SREG = oldSREG; // turn interrupts back on
  tunedDelay(_tx_delay);
  
  return 1;
}

ho praticamente solo aggiunto :

    if (b9){
              tx_pin_write(HIGH); // send 1
    } else{
              tx_pin_write(LOW); // send 0
    }

alla fine del metodo in modo da inviare un altro bit prima del bit di stop.

Secondo voi è giusto?

Come posso modificare in modo analogo il metodo read?

int SoftwareSerial::read()
{
  if (!isListening())
    return -1;

  // Empty buffer?
  if (_receive_buffer_head == _receive_buffer_tail)
    return -1;

  // Read from "head"
  uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte
  _receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF;
  return d;
}

da quello che ho capito dopo aver letto un byte dal buffer lo cancella tramite questa stringa:
_receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF;

dovrei dirgli di conservare il 9bit da qualche parte in modo da porterlo leggere con un altro metodo, come faccio?

Inoltre mi spiegate come la libreria fa a temporizzare i dati della seriale a 9600?

Grazie in anticipo a tutti coloro che vorranno darmi una mano o un consiglio
Massimo

nel frattempo che arrivino pareri, modifica il post e racchiudi il codice con l'apposito tag, in modo da leggerlo piu' leggibile

massimotriggiano76: Mi spiego vorrei usare arduino per interfacciare il mio pc a un vecchio apparato che usa questo protocollo: 8bit dati 1bti mode 1 stop

Lascia perdere la software serial che ti crea solo problemi, l'UART dei 328 supporta anche la modalità a 9 bit, solitamente il nono bit si usa sulla RS485 per discriminare tra address e data, fai riferimento al data sheet del 328, sezione UART, per vedere come settare il micro per il modo 9 bit e come settare il bit stesso C'è una cosa che non torna, la condizione di idle della UART, vale per tutte indipendentemente dal produttore/modello, è 1 logico e non 0 logico.

Sono nuovo del mondo arduino, ma potresti spiegarti meglio quando dici

al data sheet del 328, sezione UART, per vedere come settare il micro per il modo 9 bit e come settare il bit stesso

non dirmi che non posso usare il linguaggio di arduino e devo usare l'assembler??

e poi :

C'è una cosa che non torna, la condizione di idle della UART, vale per tutte indipendentemente dal produttore/modello, è 1 logico e non 0 logico.

in che senso deve tornare sempre allo stesso stato logico per ricominciare il ciclo di ricezione?

GRAZIE per la risposta, aspetto info

no, apri hardwareSerial.cpp e noterai con gioia e tripudio che la begin accetta due parametri numerico, uno è il baudrate e l’altro la configurazione.

void HardwareSerial::begin(unsigned long baud, byte config)

esistono delle definizioni di costanti (nel .h) che corrrispondono ai vari tipi di modalità utilizzabili:

// Define config for Serial.begin(baud, config);
#define SERIAL_5N1 0x00
#define SERIAL_6N1 0x02
#define SERIAL_7N1 0x04
#define SERIAL_8N1 0x06
#define SERIAL_5N2 0x08
#define SERIAL_6N2 0x0A
#define SERIAL_7N2 0x0C
#define SERIAL_8N2 0x0E
#define SERIAL_5E1 0x20
#define SERIAL_6E1 0x22
#define SERIAL_7E1 0x24
#define SERIAL_8E1 0x26
#define SERIAL_5E2 0x28
#define SERIAL_6E2 0x2A
#define SERIAL_7E2 0x2C
#define SERIAL_8E2 0x2E
#define SERIAL_5O1 0x30
#define SERIAL_6O1 0x32
#define SERIAL_7O1 0x34
#define SERIAL_8O1 0x36
#define SERIAL_5O2 0x38
#define SERIAL_6O2 0x3A
#define SERIAL_7O2 0x3C
#define SERIAL_8O2 0x3E

quindi:

Serial.begin(baudrate, SERIAL_8E1);

oppure

Serial.begin(baudrate, SERIAL_8O1);

in base alla tua configurazione

Ho aperto il file che mi ha indicato ma la modalità 9n1 (9b no parita 1b stop) non l'ho trovato? ho altre alternative?

Inoltre poi dovrei usare sempre i metodi read e write per leggere i dati dalla seriale?

Scusate se faccio domande banali, ma non ci arrivo. Massimo

che non sia supportato dall'HW? dovresti controllare il datashett... sicuramente vederndo come passare da 7n1 a 8n1 ti aiusta a capire cosa cambiare, una volta che sai che lamodalitàè supportata

sto leggendo appunto il manuale, la modalità è supportata. vedo se riesco a capire come gestire il tutto e puoi posto qualcosa.

a domani, è un pò incasinata la cosa.

Grazie comunque le risposte.

Non credo basti inserire una #define relativa alla modalità a 9 bit scelta perché il core di Arduino sia in grado di gestire la trasmissione di pacchetti a 9 bit. Leggendo il datasheet si vede come il 9° bit risieda in un registro differente e che questo bit vada letto prima di leggere il registro che contiene gli altri 8 bit. Penso quindi che sia da seguire la strada di Astrobeed, ossia quella di scrivere una funzione ad hoc (non in assembly ma in C) che faccia questo lavoro.