#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>

#include "console.h"
#include "io.h"

void con_set_baudrate(uint32_t b)
{
    uint32_t bauddiv;

    /*
     * Produce a CON_BAUD_BITS binary fraction. The +1 produces better
     * rounding behavior: see Hacker's Delight.
     */
    bauddiv = (b * ((1ULL << (32+CON_BAUD_BITS))/CON_BAUD_BASE+1)) >> 32;

    /*
     * Not really a divisor, but a fractional multiplier. The -1
     * is simply a technicality of the implementation.
     */
    CON_BAUDDIV = bauddiv - 1;
}

void con_putc(char c)
{
    /* Wait for FIFO space */
    while (CON_STATUS & (1 << 4))
	pause();

    if (c == '\n')
	CON_DATA = '\r';
    CON_DATA = c;
}

void con_puts(const char *str)
{
    while (*str)
	con_putc(*str++);
}

void con_vprintf(const char *fmt, va_list ap)
{
    char buf[128];		/* Maximum text size */
    unsigned int len;
    const char *p;

    vsnprintf(buf, sizeof buf, fmt, ap);
    con_puts(buf);
}

void con_printf(const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    con_vprintf(fmt, ap);
    va_end(ap);
}
