

#include "riscv.h"
#include "stdio.h"


#define PRINT_BASE_ADDR 0x40000000
#define PRINT_SIZE 0x4

#define dev_wr(addr) g_map[(addr-PRINT_BASE_ADDR) >> 2]
#define dev_wrb(addr) ((uint8_t *)g_map)[(addr-PRINT_BASE_ADDR)]
#define dev_wrh(addr) ((uint16_t *)g_map)[(addr-PRINT_BASE_ADDR) >> 1]



static uint32_t g_map[1];

static uint32_t read(uint32_t addr) {
  if (!(addr & 0x3)) {
    return dev_wr(addr);
  } else if (!(addr & 0x1)) {
    return dev_wrh(addr);
  } else {
    return dev_wrb(addr);
  }
}

#define BUFF_LEN 1024
static char g_buff[BUFF_LEN];
static int g_index;

static void write(uint32_t addr, uint32_t data) {
  // printf("print: write data=%x\n", data);
  if (!(addr & 0x3)) {
    dev_wr(addr) = data;
  } else if (!(addr & 0x1)) {
    dev_wrh(addr) = data;
  } else {
    dev_wrb(addr) = data;
  }
  if (g_index < BUFF_LEN) {
    g_buff[g_index++] = data;
  }
  if (data == '\n') {
    g_buff[g_index] = 0;
    printf("\033[33m%s\033[0m", g_buff);
    g_index = 0;
  }
}




const static device_t g_print = {
    .addr = PRINT_BASE_ADDR,
    .size = PRINT_SIZE,
    .read = read,
    .write = write,
};


const device_t* print_dev() {
  return &g_print;
}

