/*
 * A ring buffer for AVR.
 *
 * This version is intended to be used with an ISR calling get() and
 * the main program calling put().  So put() blocks, and the variable
 * put() modifies (the `front` pointer) isn’t declared volatile; get()
 * simply returns false rather than blocking, and the variable *it*
 * modifies *is* declared volatile.  (So it caches it in a local
 * variable.)
 */

const int buffer_log_size = 7;
static char buffer[1 << buffer_log_size];
typedef unsigned char bufidx;
static bufidx front = 0;
static volatile bufidx rear = 0;

static inline bufidx next(bufidx cur)
{
  return (cur + 1) & ((1 << buffer_log_size) - 1);
}   

static inline void put(char v)
{ 
  while (rear == next(front))
    ;
  buffer[unsigned(front)] = v;
  front = next(front);
} 

static inline char get(char *where)
{ 
  register bufidx r = rear;
  if (r == front) return 0;
  *where = buffer[unsigned(r)];
  rear = next(r);
  return 1;
}

void putt(char v) { put(v); }
char gett(char *where) { return get(where); }

