// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#ifdef __linux__
#include <pty.h>
#elif __APPLE__
#include <util.h>
#endif

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include "spidpi.h"
#include "verilator_sim_ctrl.h"

// Enable this define to stop tracing at cycle 4
// and resume at the first SPI packet
// #define CONTROL_TRACE

extern VerilatorSimCtrl *simctrl;

static void finish(void) {
  if (!simctrl) {
    return;
  }
  simctrl->RequestStop();
}

#ifdef CONTROL_TRACE
static void trace(int enable) {
  if (!simctrl) {
    return;
  }
  if (enable) {
    simctrl->TraceOn();
  } else {
    simctrl->TraceOff();
  }
}
#endif

void *spidpi_create(const char *name, int mode, int loglevel) {
  int i;
  struct spidpi_ctx *ctx =
      (struct spidpi_ctx *)calloc(1, sizeof(struct spidpi_ctx));
  assert(ctx);

  ctx->loglevel = loglevel;
  ctx->mon = monitor_spi_init(mode);
  ctx->tick = 0;
  ctx->msbfirst = 1;
  ctx->nmax = MAX_TRANSACTION;
  ctx->nin = 0;
  ctx->nout = 0;
  ctx->bout = 0;
  ctx->state = SP_IDLE;
  /* mode is CPOL << 1 | CPHA
   * cpol = 0 --> external clock matches internal
   * cpha = 0 --> drive on internal falling edge, capture on rising
   */
  ctx->cpol = ((mode == 0) || (mode == 2)) ? 0 : 1;
  ctx->cpha = ((mode == 1) || (mode == 3)) ? 1 : 0;
  /* CPOL = 1 for clock idle high */
  ctx->driving = P2D_CSB | ((ctx->cpol) ? P2D_SCK : 0);
  char cwd[PATH_MAX];
  char *cwd_rv;
  cwd_rv = getcwd(cwd, sizeof(cwd));
  assert(cwd_rv != NULL);

  int rv;
  struct termios tty;
  cfmakeraw(&tty);

  rv = openpty(&ctx->master, &ctx->slave, 0, &tty, 0);
  assert(rv != -1);

  rv = ttyname_r(ctx->slave, ctx->ptyname, 64);
  assert(rv == 0 && "ttyname_r failed");

  int cur_flags = fcntl(ctx->master, F_GETFL, 0);
  assert(cur_flags != -1 && "Unable to read current flags.");
  int new_flags = fcntl(ctx->master, F_SETFL, cur_flags | O_NONBLOCK);
  assert(new_flags != -1 && "Unable to set FD flags");

  printf(
      "\n"
      "SPI: Created %s for %s. Connect to it with any terminal program, e.g.\n"
      "$ screen %s\n"
      "NOTE: a SPI transaction is run for every 4 characters entered.\n",
      ctx->ptyname, name, ctx->ptyname);

  rv = snprintf(ctx->mon_pathname, PATH_MAX, "%s/%s.log", cwd, name);
  assert(rv <= PATH_MAX && rv > 0);
  ctx->mon_file = fopen(ctx->mon_pathname, "w");
  if (ctx->mon_file == NULL) {
    fprintf(stderr, "SPI: Unable to open file at %s: %s\n", ctx->mon_pathname,
            strerror(errno));
    return NULL;
  }
  // more useful for tail -f
  setlinebuf(ctx->mon_file);
  printf(
      "SPI: Monitor output file created at %s. Works well with tail:\n"
      "$ tail -f %s\n",
      ctx->mon_pathname, ctx->mon_pathname);

  return (void *)ctx;
}

char spidpi_tick(void *ctx_void, svBitVecVal *d2p_data) {
  struct spidpi_ctx *ctx = (struct spidpi_ctx *)ctx_void;
  assert(ctx);
  int d2p = d2p_data[0];

  // Will tick at the master clock
  ctx->tick++;

#ifdef CONTROL_TRACE
  if (ctx->tick == 4) {
    trace(0);
  }
#endif

  monitor_spi(ctx->mon, ctx->mon_file, ctx->loglevel, ctx->tick, ctx->driving,
              d2p);

  if (ctx->state == SP_IDLE) {
    int n = read(ctx->master, &(ctx->buf[ctx->nin]), ctx->nmax - ctx->nin);
    if (n == -1) {
      if (errno != EAGAIN) {
        fprintf(stderr, "Read on SPI FIFO gave %s\n", strerror(errno));
      }
    } else {
      ctx->nin += n;
      if (ctx->nin == ctx->nmax) {
        ctx->nout = 0;
        ctx->nin = 0;
        ctx->bout = ctx->msbfirst ? 0x80 : 0x01;
        ctx->bin = ctx->msbfirst ? 0x80 : 0x01;
        ctx->din = 0;
        ctx->state = SP_CSFALL;
#ifdef CONTROL_TRACE
        trace(1);
#endif
      }
    }
  }
  // SPI clock toggles every 4th tick (i.e. freq=master/8)
  if ((ctx->tick & 3) || (ctx->state == SP_IDLE)) {
    return ctx->driving;
  }

  // Only get here on sck edges when active
  int internal_sck = (ctx->tick & 4) ? 1 : 0;
  int set_sck = (internal_sck ? P2D_SCK : 0);
  if (ctx->cpol) {
    set_sck ^= P2D_SCK;
  }

  if (internal_sck == ctx->cpha) {
    // master driving edge (falling for mode 0)
    switch (ctx->state) {
      case SP_DMOVE:
        // SCLK low, CSB low
        ctx->driving =
            set_sck | (ctx->buf[ctx->nout] & ctx->bout) ? P2D_MOSI : 0;
        ctx->bout = (ctx->msbfirst) ? ctx->bout >> 1 : ctx->bout << 1;
        if ((ctx->bout & 0xff) == 0) {
          ctx->bout = ctx->msbfirst ? 0x80 : 0x01;
          ctx->nout++;
          if (ctx->nout == ctx->nmax) {
            ctx->state = SP_LASTBIT;
          }
        }
        break;
      case SP_LASTBIT:
        ctx->state = SP_CSRISE;
        // fallthrough
      default:
        ctx->driving = set_sck | (ctx->driving & ~P2D_SCK);
        break;
    }
  } else {
    // master other edge (rising for mode 0)
    switch (ctx->state) {
        // Read input data (opposite edge to sending)
        // both DMOVE and LASTBIT states are data moving ones!
      case SP_DMOVE:
      case SP_LASTBIT:
        ctx->din = ctx->din | ((d2p & D2P_MISO) ? ctx->bin : 0);
        ctx->bin = (ctx->msbfirst) ? ctx->bin >> 1 : ctx->bin << 1;
        if (ctx->bin == 0) {
          int rv = write(ctx->master, &(ctx->din), 1);
          assert(rv == 1 && "write() failed.");
          ctx->bin = (ctx->msbfirst) ? 0x80 : 0x01;
          ctx->din = 0;
        }
        ctx->driving = set_sck | (ctx->driving & ~P2D_SCK);
        break;
      case SP_CSFALL:
        // CSB low, drive MOSI to first bit
        ctx->driving =
            (set_sck | (ctx->buf[ctx->nout] & ctx->bout) ? P2D_MOSI : 0);
        ctx->state = SP_DMOVE;
        break;
      case SP_CSRISE:
        // CSB high, clock stopped
        ctx->driving = P2D_CSB;
        ctx->state = SP_IDLE;
        break;
      case SP_FINISH:
        finish();
        break;
      default:
        ctx->driving = set_sck | (ctx->driving & ~P2D_SCK);
        break;
    }
  }
  return ctx->driving;
}

void spidpi_close(void *ctx_void) {
  struct spidpi_ctx *ctx = (struct spidpi_ctx *)ctx_void;
  if (!ctx) {
    return;
  }
  fclose(ctx->mon_file);
  free(ctx);
}
