/*
 * sav_init.c
 *
 *  Created on: 04 Mar 2020
 *      Author: lx
 */

/* ------------------------ System architecture includes ----------------------------- */

#include "fsl_gpio.h"
#include "fsl_lpspi.h"

#include "arch/sys_arch.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "lwip/memp.h"
#include "lwip/timeouts.h"
#include "lwip/tcpip.h"

// #include "defines.h"
#include "sav_init.h"

// #include "init_timer.h"
// #include "ads8688.h"
// #include "config_spi.h"
// #include "config_process_bus.h"
#include "enet_mac_if1.h"

static sys_mbox_t sav_mbox;

static struct trans_savif * trans_sav_interface  = NULL;

/**
 * The sav thread.
 * It also starts all the timers to make sure they are running in the right
 * thread context.
 *
 * @param arg unused argument
 */

void set_trans_interface(struct trans_savif *trans_sav_intf)
{
	trans_sav_interface = trans_sav_intf;
}

static void sav_thread(void *arg)
{
  struct sav_msg *msg;
  (void) arg;

  // NickP: this must be called first here!
  enetif0_init();

  // This must have been set before we go any further!
  assert(trans_sav_interface);

  if (trans_sav_interface->sav_tx_enabled())
  {
	  trans_sav_interface->enable_ready_to_transfer();
  }

  while (1)
  {
    /* MAIN Loop */
    sys_mbox_fetch(&sav_mbox, (void **)&msg); // wait here for a message

    if (msg == NULL) {
      LWIP_PLATFORM_DIAG(("sav_thread: invalid message\n"));
      continue;
    }
    switch (msg->type) {

    case SAV_TRANSMIT_CALLBACK:
//      LWIP_PLATFORM_DIAG(("sav_thread: SAV_TRANSMIT_CALLBACK\n"));
      msg->function(msg->length, msg->ctx);
      memp_free(MEMP_SAV_MSG_API, msg);
      break;

    case SAV_RECEIVE_CALLBACK:
//      LWIP_PLATFORM_DIAG(("sav_thread: SAV_RECEIVE_CALLBACK\n"));
      msg->function(msg->length,msg->ctx);
      memp_free(MEMP_SAV_MSG_API, msg);
      break;

    default:
      LWIP_PLATFORM_DIAG(("sav_thread: invalid message:\n"));
      LWIP_ASSERT("sav_thread: invalid message", 0);
      break;
    }
  }
}



/**
 * Call a specific function in the thread context of
 * sav_thread for easy access synchronization.
 * without fearing concurrent access.
 *
 * @param function the function to call
 * @param ctx parameter passed to f
 * @param block 1 to block until the request is posted, 0 to non-blocking mode
 * @return ERR_OK if the function was called, another err_t if not
 */
int8_t sav_callback_with_block(uint8_t msg_type, sav_callback_fn function, uint16_t length, void *ctx, uint8_t block)
{
  struct sav_msg *msg;

  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(sav_mbox));

  msg = (struct sav_msg *)memp_malloc(MEMP_SAV_MSG_API);
  if (msg == NULL) {
    return ERR_MEM;
  }

  msg->type = msg_type;
  msg->length = length;
  msg->function = function;
  msg->ctx = ctx;
  if (block) {
    sys_mbox_post(&sav_mbox, msg);
  } else {
    if (sys_mbox_trypost(&sav_mbox, msg) != ERR_OK) {
      memp_free(MEMP_SAV_MSG_API, msg);
      return ERR_MEM;
    }
  }
  return ERR_OK;
}



/**
 * @ingroup lwip_os
 * Initialize this module:
 * - initialize all sub modules
 * - start the tcpip_thread
 *
 * @param initfunc a function to call when tcpip_thread is running and finished initializing
 * @param arg argument to pass to initfunc
 */
void sav_init(void)
{
  if (sys_mbox_new(&sav_mbox, SAV_MBOX_SIZE) != ERR_OK) {
    LWIP_ASSERT("failed to create sav_thread mbox", 0);
  }
#if SAV_CORE_LOCKING
  if (sys_mutex_new(&lock_sav_core) != ERR_OK) {
    LWIP_ASSERT("failed to create lock_tcpip_core", 0);
  }
#endif // SAV_CORE_LOCKING //

  sys_thread_new(SAV_THREAD_NAME, sav_thread, NULL, SAV_THREAD_STACKSIZE, SAV_THREAD_PRIO);

}

