/* ROVFILE.C, ROVER FILE SYSTEM */

#include <TT7.h>
#include "rovfile.h"
#include "rovsys.h"
#include "rovlib.h"
#include <psram.h>
#include <time.h>
#include <stdio.h>

#ifdef AZTEC_C
#include <offload.h>
#include <drive.h>
#include <pario.h>
#include <datafile.h>
#include <serio.h>
#include <userio.h>

#else                    /* Turbo C */
#include "tt7pclib.h"
#endif


/* Global Variables */

short df_count, record_count;
short g_curr_dir, g_curr_speed, g_heading;
long mem_size;
void *mem_start, *rov_data_start, *inst_mem_start, *inst_data_start;
unsigned char *inst_data_ptr;
unsigned long max_inst_bytes, max_rov_records;

struct file_header{
  unsigned long record_count;
} *file_head_ptr;

struct inst_file_header{
  ulong byte_count;
  ulong inst_start_time[4];
} *inst_head_ptr;

struct rov_data{
  short record_type;
  time_t caltime;
  short analog[8];
  short heading;
  short curr_speed;
  short curr_dir;
} *rov_data_ptr;


/*******************************************************
	      Datafiles Function
********************************************************/

int datafiles(void){
  char menukey;
  short i, chan;
  unsigned long dfnum = 0;
  XmdmErr xerr;
  DriveErr derr;

  while(1){
    SerInFlush();
    printf("\n\n\nRover Datafiles Menu");
    printf("\n\n  1 -- Display File Status");
    printf("\n  2 -- Load Disk File to Memory");
    printf("\n  3 -- Offload Data Memory");
    printf("\n  4 -- Load Instrument Data");
    printf("\n  5 -- Store Memory to Disk");
    printf("\n  6 -- Display Rover Data");
    printf("\n  7 -- Display Inst. Data");
    printf("\n  8 -- Fill Memory with Test Data");
    printf("\n  9 -- Exit");
    QueryChar("\nEnter Selection: ",'9',"123456789a",&menukey);

    switch(menukey){

      case '1':  /*Datafile Status*/
	printf("\n\nMaximum Rover Data Records = %lu", max_rov_records);
	printf("\nMaximum Inst. Data Bytes = %lu", max_inst_bytes);
	printf("\nRover Data Records in Memory = %lu", file_head_ptr->record_count);
	printf("\nInst. Data Bytes in Memory = %lu", inst_head_ptr->byte_count);
	printf("\nDisk Files Written = %hd", df_count);
	break;

      case '2':  /* Load Disk Files */
	if( QueryNum("\nEnter disk file number to load: ","%lu", "%lu", &dfnum) ){
	  derr = DFRead(mem_start, (short)dfnum);
	  if(derr) printf("\nDisk file error: %d", derr);
	  else printf("\nDisk file loaded");
	}
	break;

      case '3':  /* Offload Data */
	offload();
	break;

      case '4':  /* Load Instrument Data */
	clear_inst_files();
	stbd_bc_pwr_on();
	delaysecs(1);
	port_bc_pwr_on();
	delaysecs(5);

	inst_transfer_data(STBD_BENCHAM);
	inst_transfer_data(PORT_BENCHAM);

	stbd_bc_pwr_off();
	port_bc_pwr_off();
	break;

      case '5':  /* Store Memory to Disk */
	if(QueryYesNo("\n\nStore memory to disk?", FALSE)){
	  mem_to_disk();
	}
	break;
	

      case '6':  /* Display Rover Data */
	display_data();
	break;

      case '7':  /* Display Inst. Data */
	inst_data_ptr = inst_mem_start;
	printf("\n");
	for(i = 0; i < inst_head_ptr->byte_count; i++){
	  SerPutByte(*inst_data_ptr);
	  inst_data_ptr++;
	}
	break;

      case '8':  /* Test Data */
	clear_rov_files();

	for(i = 1; i <= 100; i++){
	  rov_data_ptr->record_type = TRANSIT;
	  rov_data_ptr->caltime = time(0);
	  for(chan = 0; chan <= 7; chan++) rov_data_ptr->analog[chan] = 16380;
	  rov_data_ptr->heading = 359;
	  rov_data_ptr->curr_speed = 10;
	  rov_data_ptr->curr_dir = 359;

	  rov_data_ptr++;
	  file_head_ptr->record_count++;
	}

	printf("\n%lu test data files stored", file_head_ptr->record_count);
	break;

      case '9':  /* Exit */
	DriveOff();
	DisableParIO();
	return 0;

      case 'a':
	stbd_bc_pwr_on();
	delaysecs(1);
	port_bc_pwr_on();
	delaysecs(5);

	if(inst_start(STBD_BENCHAM)) printf("\nStbd benthic chamber not responding");
	else printf("\nStbd benthic chamber running");
	if(inst_start(PORT_BENCHAM)) printf("\nPort benthic chamber not responding");
	else printf("\nPort benthic chamber running");
	break;

    }  /* Switch ends */

  }  /* End of WHILE loop */

}


/****************************************************
	    File Functions
****************************************************/

int file_init(void){

  PSMemFreeAll();

  mem_start = PSMemAlloc(ROV_FILE_BLKS);   /* Allocate all free memory to file system */
  if(!mem_start){
    printf("\nRov. Data memory request failure");
    return -1;
  }

  file_head_ptr = mem_start;
  rov_data_start = file_head_ptr + 1;  /* Pointer arithmetic adds 4 */
  rov_data_ptr = rov_data_start;       /* Void pointer keeps compiler happy */
  max_rov_records = ROV_FILE_BLKS;
  max_rov_records *= (16384/sizeof(struct rov_data));
  file_head_ptr->record_count = 0;

  inst_mem_start = PSMemAlloc(INST_FILE_BLKS);
  if(!inst_mem_start){
    printf("\nInst. Data memory request failure");
    return -1;
  }

  inst_head_ptr = inst_mem_start;
  inst_data_start = inst_head_ptr + 1;
  inst_data_ptr = inst_data_start;
  max_inst_bytes =  INST_FILE_BLKS;
  max_inst_bytes *= 16384;
  inst_head_ptr->byte_count = 0;

  printf("\nFile system initialized");

  return 0;
}


/***********************************************/

int store_data(short type){
  short chan;

  rov_data_ptr->record_type = type;
  rov_data_ptr->caltime = time(0);
  for(chan = 0; chan <=7; chan++) rov_data_ptr->analog[chan] = get_ad_counts(chan);
  rov_data_ptr->heading = g_heading;
  if(type == CURRMET_DATA){
    rov_data_ptr->curr_speed = g_curr_speed;
    rov_data_ptr->curr_dir = g_curr_dir;
  }
  else{
    rov_data_ptr->curr_speed = -1;
    rov_data_ptr->curr_dir = -1;
  }
  rov_data_ptr++;
  file_head_ptr->record_count++;
  return 0;
}
/***********************************************/

void clear_rov_files(void){

  rov_data_ptr = rov_data_start;
  file_head_ptr->record_count = 0;
  return;
}

/***********************************************/

void clear_inst_files(void){

  inst_data_ptr = inst_data_start;
  inst_head_ptr->byte_count = 0;

  return;
}

/***********************************************/
int inst_start(int instrument){
  int x;
  char inbuf[20];

    setcomchan(instrument);
    delaysecs(1);
    TSerInFlush(13);
    TPuts("3");            /* Start data cycle */
    delaysecs(1);          /* Benthic chamber contoller is slow */
    TPuts("\n");
    for(x=0; x<5; x++){
      TGetsTimed(1000, inbuf);
      printf("\n%s", inbuf);
      if( !strcmp(inbuf, "Running...") ){     /* Check for confirmation string */
	inst_head_ptr->inst_start_time[instrument] = time(NOW);
	return 0;
      }
    }
    inst_head_ptr->inst_start_time[instrument] = 0;
    return -1;
}

/***********************************************/

int inst_transfer_data(int instrument){    /* Transfers data from rack instruments */
  setcomchan(instrument);
  delaysecs(1);
  TSerInFlush(13);
  TPuts("4");
  delaysecs(1);     /* Benthic chamber controller is slow */
  TPuts("\n");
  inst_store_data();

  return 0;
}

/***********************************************/

void inst_store_data(void){    /* Stores data from rack instruments */
  int inbyte;

  while(1){
    inbyte = TSerGetByteTimed(1000);
    if( inbyte == (-1) ) break;
    else{
      *inst_data_ptr++ = inbyte;    /* Store the data in hex form */
      inst_head_ptr->byte_count++;
    }
  }
  return;
}

/***********************************************/

void offload(void){
  char menukey;
  XmdmErr xerr;
  long length;

  while(1){
    SerInFlush();

    printf("\n\n\nOffload Menu");
    printf("\n\n1 -- Rover Data");
    printf("\n2 -- Instrument Data");
    printf("\n9 -- Exit");

    QueryChar("\nEnter Selection: ",'9',"12345789",&menukey);

    switch(menukey){
      case '1':
	printf("\n\nStarting XMODEM-1K transfer ... ");
	length = sizeof(struct file_header)
		 + file_head_ptr->record_count * sizeof(struct rov_data);
	xerr = XmodemSendMem(mem_start, length, 30);
	if(xerr) printf("\nXmodem error: %d", xerr);
	else printf("\nTransfer complete");
	break;

      case '2':
	printf("\n\nStarting XMODEM-1K transfer ... ");
	length = inst_head_ptr->byte_count;
	xerr = XmodemSendMem(inst_data_start, length, 30);
	if(xerr) printf("\nXmodem error: %d", xerr);
	else printf("\nTransfer complete");
	break;

      case '9':
	return;
    }
  }
}

/*****************************************************/

int display_data(void){
  int chan;
  unsigned long i;
  time_t rovtime;

  rov_data_ptr = rov_data_start;
  SerInFlush();

  for(i = 1; i <= file_head_ptr->record_count; i++){
      if( kbhit() ) break;

      printf("\n\n%hd ", rov_data_ptr->record_type);
      rovtime = rov_data_ptr->caltime;
      printf("   %s", ctime(&rovtime));
      printf("%6.2f ", ((float)rov_data_ptr->analog[0]/BATTCAL));
      printf("%6.2f ", (float)rov_data_ptr->analog[1]/HPCURRCAL);
      printf("%6.2f ", (float)rov_data_ptr->analog[2]/LPCURRCAL);
      printf("%6.2f ", (float)rov_data_ptr->analog[3]/GFVOLTCAL);
      printf("%5.1f ", (float)rov_data_ptr->analog[4]/TILTX_CAL-TILTX_OFFSET);
      printf("%5.1f ", (float)rov_data_ptr->analog[5]/TILTY_CAL-TILTY_OFFSET);
      printf("%5.1f ", (float)rov_data_ptr->analog[6]);
      printf("%5.1f ", (float)rov_data_ptr->analog[7]/AUXANACAL);
      printf(" %hd ", rov_data_ptr->heading);
      printf("%5.1f ", (float)rov_data_ptr->curr_speed);
      printf("%5.1f ", (float)rov_data_ptr->curr_dir);

      rov_data_ptr++;
  }

  printf("\nEnd of data, press any key to continue");
  while( !kbhit() );
  return 0;
}

/***********************************************************/

int mem_to_disk(void){
  DriveErr derr;

  derr = DFWrite( mem_start, df_count);
  if(derr) printf("\nDisk error: %d ", derr);
  else{
    printf("\nMemory to written to disk file %hd", df_count);
    df_count++;
  }
  DriveOff();
  DisableParIO();

  file_init();
  printf("\nDisk drive off");
  return(0);
}

/****************************************************/

void clear_disk_files(void){

  df_count = 0;
}
