/* 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;

struct file_header{
  unsigned long record_count;
} *file_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  5 -- Store Memory to Disk");
/*  printf("\n  6 -- Prep. Disk Drive/Clear Disk Files"); */
    printf("\n  7 -- Display Data");
    printf("\n  8 -- Fill Memory with Test Data");
    printf("\n  9 -- Exit");
    QueryChar("\nEnter Selection: ",'9',"12345789",&menukey);

    switch(menukey){

      case '1':  /*Datafile Status*/
	printf("\n\nMemory Size = %ld bytes", mem_size );
	printf("\nRover Data Records in Memory = %lu", file_head_ptr->record_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':  /* Rover Data */
	if(QueryYesNo("\n\nOffload the memory data using XMODEM-1K ?", FALSE)){
	  printf("\n\nStarting XMODEM-1K transfer ... ");
	  offload();
	}
	break;

      case '5':  /* Store Memory to Disk */
	if(QueryYesNo("\n\nStore memory to disk?", FALSE)){
	  mem_to_disk();
	}
	break;
        
/*
      case '6':
	if(QueryYesNo("\n\nClear all disk files?", FALSE)){
	  DriveOn(TRUE);
	  delaysecs(1);
	  derr = DFDrivePrep();
	  if(derr) printf("\nDisk file error: %d", derr);
	  else printf("\nAll disk files erased");
	}
	break;
*/
      case '7':  /* Display Data */
	display_data();
	break;

      case '8':  /* Test Data */
	file_init();

	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;

    }  /* Switch ends */

  }  /* End of WHILE loop */

}


/****************************************************
	    File Functions
****************************************************/

int file_init(void){

  PSMemFreeAll();

  mem_start = PSMemAllocAll(&mem_size);   /* Allocate all free memory to file system */
  if(!mem_start){
    printf("\nOut of memory");
    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 */

  file_head_ptr->record_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;
}

/***********************************************/

int offload(void){
  XmdmErr xerr;

  xerr = XmodemSendMem(mem_start, file_head_ptr->record_count * sizeof(struct rov_data)
		       + sizeof(struct file_header), 30);
  if(xerr) printf("\nXmodem error: %d", xerr);
  else printf("\nTransfer complete");
  return xerr;
}

/*****************************************************/

int display_data(void){
  int i, chan;
  time_t rovtime;

  rov_data_ptr = rov_data_start;
  SerInFlush();

  for(i = 1; i <= 5000; i++){
    while( !kbhit() ){
      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]/CMVANECAL);
      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() );
  SerInFlush();
  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;
}
