#ifndef __AVRTTY_H__
#define __AVRTTY_H__

/*****************************************
  tty i/o
*/

#include <avr/io.h>

#ifdef UCSR0A

#include "avrbuf.h"
#include "avrtime.h"

/*********************
 low level
*/

// return baud rate error * 1000
struct tty_baudcode_t {
  uint16_t code;
  uint32_t err; // divide with 100 to get %
};

uint8_t tty_baudcode(uint32_t baudrate, struct tty_baudcode_t arr[2]);
void tty_setbaud(uint8_t port, uint16_t baudcode, uint8_t u2x);

/* from uart power on there is a delay before one can use the uart
 > 1ms seems to work
 to power off: tty_power(port, 0, 0);
*/
void tty_power(uint8_t port, uint8_t enable_rx, uint8_t enable_tx);

//  I get complaints about multiple definitions with inline when linking, soo, make theese as defines
// check if read/write is enabled
#define tty_rd_enabled(port) (UCSR0B & _BV(RXEN0))
#define tty_wr_enabled(port) (UCSR0B & _BV(TXEN0))

// check if we got something or uart is ready to send something
#define tty_readable(port) (tty_rd_enabled(port) && tty_readable_q(port))
#define tty_writeable(port) (tty_wr_enabled(port) && tty_writeable_q(port))
// assume reciever/transmitter are enabled, q = quick
#define tty_readable_q(port) ((void) port, (UCSR0A & _BV(RXC0)))
#define tty_writeable_q(port) ((void) port, (UCSR0A & _BV(UDRE0)))

// get what's in the uart, put something in the uart
#define tty_rread(port, cc) (*(cc) = UDR0)
// p.186 says we should clear UDRE0 bit for "compatibility with future devices"
#define tty_rwrite(port, cc) (UDR0 = (cc), (UCSR0A &= (uint8_t) ~_BV(UDRE0)))

// return #of chars transferred, tty_read: cc == 0 if no chars was read
uint8_t tty_writechar(uint8_t port, uint8_t cc);
uint8_t tty_readchar(uint8_t port, uint8_t *cc);


/*********************
 mid level
*/

extern uint32_t tty_bytetime; // in timer ticks (rounded up)
struct ttydata_t {
  // init theese with two buffers
  struct buf_t wr;
  struct buf_t rd;
  uint32_t bytetime;
};

#define TTYDATASZ 1
extern struct ttydata_t ttydata[TTYDATASZ];

void tty_init(uint8_t port, uint32_t baudrate, uint8_t *wbuf, uint8_t wsz, uint8_t *rbuf, uint8_t rsz);

// full duplex version
uint8_t tty_run(uint8_t port, uint8_t enable_echo);

// half duplex version
uint8_t tty_recv(uint8_t *buf, uint8_t sz);
uint8_t tty_send(uint8_t *buf, uint8_t sz);
void tty_hdrun(void);

#endif // UCSR0A

#endif
