// 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

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;
  const char *test_out_dir = getenv("TEST_UNDECLARED_OUTPUTS_DIR");
  if (test_out_dir) {
    cwd_rv = strncpy(cwd, test_out_dir, sizeof(cwd));
  } else {
    cwd_rv = getcwd(cwd, sizeof(cwd));
  }
  assert(cwd_rv != NULL);

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

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

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

  int cur_flags = fcntl(ctx->host, F_GETFL, 0);
  assert(cur_flags != -1 && "Unable to read current flags.");
  int new_flags = fcntl(ctx->host, 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, const svLogicVecVal *d2p_data) {
  struct spidpi_ctx *ctx = (struct spidpi_ctx *)ctx_void;
  assert(ctx);
  int d2p = d2p_data->aval;

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

#ifdef CONTROL_TRACE
  if (ctx->tick == 4) {
    VerilatorSimCtrl::GetInstance().TraceOff();
  }
#endif

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

  if (ctx->state == SP_IDLE) {
    int n = read(ctx->host, &(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
        VerilatorSimCtrl::GetInstance().TraceOn();
#endif
      }
    }
  }
  // SPI clock toggles every 4th tick (i.e. freq=primary_frequency/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) {
    // host 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_SDI : 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 {
    // host 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_SDO) ? ctx->bin : 0);
        ctx->bin = (ctx->msbfirst) ? ctx->bin >> 1 : ctx->bin << 1;
        if (ctx->bin == 0) {
          int rv = write(ctx->host, &(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 SDI to first bit
        ctx->driving =
            (set_sck | (ctx->buf[ctx->nout] & ctx->bout) ? P2D_SDI : 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:
        VerilatorSimCtrl::GetInstance().RequestStop(true);
        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);
}
