#ifndef SERIAL_H
#define SERIAL_H

#include "hardware.h"

#ifndef NO_SERIAL

/* "static inline" saves runtime memory at the expense of code bloat.
 * Your call.
 */

/* #define SERIALAPI static inline */
#define SERIALAPI

static inline void init_serial()
{
  *baud = 0x30;  /* 9600, N81 */
  *sccr2 |= 0x0c; /* transmit and receive enable */
}

SERIALAPI void putchar(uint8_t ch)
{
  while ((*scsr & 0x80) == 0) {} /* Transmit Data Register Empty */
  *scdr = ch;
}

SERIALAPI void putstring(const char *str)
{
  do
  {    
    putchar(*str++);
  } while (*str);
}

SERIALAPI uint8_t getchar()
{
  while ((*scsr & 0x20) == 0) {} /* Receive Data Register Full */
  return *scdr;
}

/* outputs a uint8 in hex in MSB-first (left to right reading) */
SERIALAPI void put_ui8(const uint8_t *x)
{
  static const char hexit[17] = "0123456789ABCDEF";
  putchar(hexit[(*x & 0xF0) >> 4]);
  putchar(hexit[ *x & 0x0F      ]);
}

/* output an signed int8 */
SERIALAPI void put_si8(const int8_t *x)
{
  if (*x < 0)
  {
    putchar('-');
    uint8_t y = -*x;
    put_ui8(&y);
  } else
    put_ui8((uint8_t*)x);
}

/* outputs a uint16 in binary in MSB-first (left to right reading) */
SERIALAPI void put_ui16(const uint16_t *x)
{
  put_ui8((const uint8_t *)(x)  );
  put_ui8((const uint8_t *)(x)+2);
}

#undef SERIALAPI

#else
#define init_serial() do {} while (0)
#define putchar(x) do {} while (0)
#define putstring(x) do {} while (0)
#define put_ui16(x) do {} while (0)
#define put_ui8(x) do {} while (0)
#define put_si8(x) do {} while (0)
#endif

#endif /* header guard */

(download)