/**
 * @file wrtd-rt-fd.c
 *
 * Copyright (c) 2018-2019 CERN (home.cern)
 *
 * SPDX-License-Identifier: LGPL-3.0-or-later
 */

#include "mockturtle-rt.h"
#include <mockturtle-framework.h>
#include "wrtd-common.h"

#include "wrtd-fd.h"

#define NBR_CPUS 1
#define CPU_IDX 0
#define NBR_RULES 16
#define NBR_DEVICES 1
#define NBR_ALARMS 1
#define DEVICES_NBR_CHS { 2 * FD_NUM_CHANNELS, 0, 0, 0}
#define DEVICES_CHS_DIR { WRTD_CH_DIR_OUT, 0, 0, 0}
#define APP_ID 0x35E0
#define APP_VER RT_VERSION(2, 0)
#define APP_NAME "wrtd-fd-x2"
#define WRTD_NET_TX 0
#define WRTD_NET_RX 1
#define WRTD_LOCAL_TX 1
#define WRTD_LOCAL_RX 0

#include "wrtd-rt-common.h"

#include "wrtd-fd.c"

#include "fd-acam.c"
#include "fd-gpio.c"
#include "fd-pll.c"
#include "fd-i2c.c"
#include "fd-calibrate.c"
#include "fd-init.c"

struct wrtd_fd_dev fd0 = {
        .io_addr = 0x0
};

struct wrtd_fd_dev fd1 = {
        .io_addr = 0x8000
};

static int wr_link_up(void)
{
        return fd_wr_link_up(&fd0);
}

static int wr_time_ready(void)
{
        return fd_wr_time_ready(&fd0);
}

static void wr_enable_lock(int enable)
{
        fd_wr_enable_lock(&fd0, enable);
        fd_wr_enable_lock(&fd1, enable);
}

static int wr_aux_locked(void)
{
        return fd_wr_aux_locked(&fd0) && fd_wr_aux_locked(&fd1);
}

static inline int wr_sync_timeout(void)
{
#ifdef SIMULATION
        return 0;
#else
        return fd_wr_sync_timeout();
#endif
}

static int wrtd_local_output(struct wrtd_event *ev, unsigned ch)
{
  	if (ch < 4)
                return fd_local_output(&fd0, ev, ch);
        else
                return fd_local_output(&fd1, ev, ch - 4);
}

/**
 * Initialize data structures, RT application and variables
 */
static int wrtd_user_init(void)
{
        if (!fd_wr_present(&fd0)) {
                pr_error("WhiteRabbit not found\n\r");
                return -EINVAL;
        }

        wr_enable_lock(0);

        /* Channels */
        wrtd_fd_data_init(&fd0);
        wrtd_fd_data_init(&fd1);

#ifdef SIMULATION
        fd_sim_init(&fd0);
        fd_sim_init(&fd1);
#else
        fd_init(&fd0);
        fd_init(&fd1);
#endif

        pr_debug("rt-output firmware initialized.\n\r");

        return 0;
}

static void wrtd_io(void)
{
        fd_outputs(&fd0);
        fd_outputs(&fd1);
}
