#ifndef SERIAL_H
#define SERIAL_H

/* These serial port routines use both transmit and receive queues.
   The actual sending/receiving is handled by the serial_interrupt
   functions, which should get called on TXIF or RCIF. */

#include "config.h"

#define STQ_BITS 6    /* transmit queue */
#define SRQ_BITS 6    /* receive queue */

#define STQ_SIZE (1<<(STQ_BITS))
#define SRQ_SIZE (1<<(SRQ_BITS))
#define STQ_MASK (STQ_SIZE-1)
#define SRQ_MASK (SRQ_SIZE-1)
extern volatile uint8_t stq[STQ_SIZE], stq_start, stq_len;
extern volatile bank1 uint8_t srq[SRQ_SIZE], srq_start, srq_len;

/* Initialize serial port, queues, serial interrupt */
void serial_init(void);

/* Call this on (TXIE && TXIF) and (RCIE && RCIF), respectively */
void serial_interrupt_tx(void);
void serial_interrupt_rx(void);

/* Send byte to PC.  Blocks iff transmit queue is full. */
void serial_put(uint8_t x);

/* Helper functions */
void serial_put_string(const uint8_t *s);
void serial_crlf(void);
void serial_put_hex(uint8_t x);
void serial_put_hex32(uint32_t x);

/* Get byte from PC.  Blocks iff receive queue is empty. */
uint8_t serial_get(void);

/* Returns true if the respective get/put operation would not block */
#define serial_can_get() (srq_len != 0)
#define serial_can_put() (!(stq_len & STQ_SIZE))

#endif
