/**
* @file   sd_main.c
*
* @brief  This file contains middle-ware functions that access SD Card drivers.
*   
* This module uses the NIOS II core in the Altera Cyclone 2 used on the DE1
* development board. It is assumed the processor core, SRAM, and SPI components
* have been initialized and programmed in the FPGA fabric.
*
* <pre>
* The following is a list of the IP core base addresses:
*   1 - BTN_BASE:         4 Pushbuttons
*   2 - SWITCH_BASE:      10 slide switches
*   3 - LEDG_BASE:        8 green LEDs
*   4 - LEDR_BASE:        10 red LEDs
*   5 - SSEG_BASE:        4 seven-segment LED displays
*   6 - SD_CARD_BASE:     SD card controller (over SPI)
*   7 - JTAG_UART_BASE:   JTAG connection from PC to core
*   8 - USR_TIMER_BASE:   1uS Timer used to set delays
* </pre>
*
* @author David L. Kempert
*
*/
//********************************************************************************
#include <stdio.h>
#include "system.h"
#include "common.h"
#include "drivers.h"
#include "sd_drivers.h"

/*********************************************************************************
* Private Variables
**********************************************************************************/
static alt_u32 loop_counter;

/*********************************************************************************
* Private Function Prototypes
**********************************************************************************/
static void sys_init(void);
static void clear_SDRAM(void);
static void delay_us(alt_u32 delay_us);
//static void led_flash(alt_u32 led_base, alt_u32 timer_base);
static void print_sector(alt_u8 *buf);

/*********************************************************************************
* int main(void)
**********************************************************************************/
/**
* @brief  This is the main function called from the HAL initialization framework.
*
* This function starts the application layer that interfaces with the user
* through the debug console and allows FAT16 file access to the SD card.
*
*--------------------------------------------------------------------------------*/
int main(void)
{
	fat_para_type fat;
	file_dp_type fd;
	char fname[15], yes[3], inputStr[64];
	const char *p;
	int sw, btn;
	unsigned int num;
	int i, j, s, status;
	alt_u32 sect, startTime, endTime, totalTime;
	alt_u8 ch, dvsr;
	alt_u8 rbuf[512], wbuf[512]; // read and write buffers
	alt_u8 disp_msg[4]={sseg_conv_hex(5), sseg_conv_hex(13), 0xff, sseg_conv_hex(12)};

  sys_init();   ///< Initialize variables, set up timer, clear SDRAM, etc.
	sseg_disp_ptn(SSEG_BASE, disp_msg); // show "Sd C" for display

  disk_initialize();

	while (1) {

    while (!btn_read(BTN_BASE)){}; // wait for button
    btn = btn_read(BTN_BASE); // read button
    if (btn & 0x02) { // keyl pressed
      sw = pio_read(SWITCH_BASE); // read switch
    }
    btn_clear(BTN_BASE);


//		switch (sw) {
//			case 0: // mount FAT16 file system
//			case 7:
        printf("Enter sd card read sector number: ");
        scanf("%u", &num);
        sect = (alt_16)num;

        loop_counter = 0;
        status = sd_read_sector(SD_CARD_BASE, sect, wbuf);
        if (status!=0) {
          printf("Could not read ref values from sd card\n\n");
          break;
        }
        printf("\nsector %d(0x%x)\n", (int)sect, (int)sect);
        print_sector(wbuf);

        printf("\nTo stop: press key0\n\n");

        while (1) {
//          startTime = timer_read_tick(USR_TIMER_BASE);
//          pio_write(LEDR_BASE, 0x7); // write LEDs
          status = sd_read_sector(SD_CARD_BASE, sect, rbuf);
//          pio_write(LEDR_BASE, 0); // write LEDs
//          endTime = timer_read_tick(USR_TIMER_BASE);
          if (status!=0) {
            printf("read sd card failed\n\n");
            btn = btn_read(BTN_BASE); // read button
            if (btn & 0x01) { // if key0 pressed, stop
              btn_clear(BTN_BASE);
              printf("\nUser pressed stop\n\n");
              break;
            }
            continue;
          }
          else {
            for (i=0; i<512; i++) {
              if (rbuf[i] != wbuf[i]) {
                printf("Compare failed at index %d\n\n", i);
                break;
              }
            }
            if (i!=512) {
              printf("\nsector %d(0x%x)\n", (int)sect, (int)sect);
              print_sector(rbuf);
              break;
            }
            loop_counter++;
            printf("Successful compare %d\n", loop_counter);
            delay_us(500);

          }
          btn = btn_read(BTN_BASE); // read button
		      if (btn & 0x01) { // if key0 pressed, stop
        		btn_clear(BTN_BASE);
            printf("\nUser pressed stop\n\n");
            break;
      		}
        }
//			  break;
//		} //end switch

	} // end while

}

/*********************************************************************************
* static void sys_init(void)
**********************************************************************************/
/**
* @brief  This function initializes system values.
*
*--------------------------------------------------------------------------------*/
static void sys_init(void)
{
  loop_counter = 0;
//  clear_SDRAM();                    ///< Clear SDRAM
  btn_clear(BTN_BASE);              ///< Clear button edge-capture register
  timer_wr_prd(USR_TIMER_BASE, 50); ///< Set Timer with a 1us timeout period
}

/*********************************************************************************
* static void clear_SDRAM(void)
**********************************************************************************/
/**
* @brief  This function clears all SDRAM cells to zero.
*
*--------------------------------------------------------------------------------*/
static void clear_SDRAM(void)
{
  alt_u32 *ramPtr;
  alt_u32 i;

  printf("Clearing all SDRAM... \n");
  ramPtr = (alt_u32*)SDRAM_BASE;
  for (i=0; i<(SDRAM_SPAN/4); i++) {
    *ramPtr = 0L;
    ramPtr++;
  }
  printf("Clearing all SDRAM...done\n");
}

/*********************************************************************************
* static void delay_us(alt_u32 delay_us)
**********************************************************************************/
/**
* @brief  This function provides a delay in microsecond resolution.
*
* @param delay_us - number of microseconds to delay.
*
*--------------------------------------------------------------------------------*/
static void delay_us(alt_u32 delay_us)
{
  alt_u32 ntick=0;

  timer_clear_tick(USR_TIMER_BASE);
  while (ntick < delay_us) {
    if (timer_read_tick(USR_TIMER_BASE)==1) {
      timer_clear_tick(USR_TIMER_BASE);
      ntick++;
    }
  }
}

/*********************************************************************************
* static void print_sector(alt_u8 *buf)
**********************************************************************************/
/**
* @brief  This function prints a 512-byte sector in hex and ASCII format.
*
* @param *buf - a pointer to the 512-byte buffer to be displayed.
*
*--------------------------------------------------------------------------------*/
static void print_sector(alt_u8 *buf)
{
	int i, j;
	alt_u8 ch;

	for (j=0; j<32; j++) {
		printf ("0x%02x- ", j);
		for (i=0; i<16; i++)
			printf("%02x ", buf[j*16+i]);
		printf("  ");
		for (i=0; i<16; i++) {
			ch = buf[j*16+i];
			if (ch>127 || ch<32) //non ascii
				ch = '.';
			printf ("%c", ch);
		} // end for i
		printf("\n");
	} //end for j
	printf("\n");
}


/*********************************************************************************
* static void led_flash(alt_u32 led_base, alt_u32 timer_base)
**********************************************************************************/
/**
* @brief  This function toggles 2 LEDs.
*
* @param led_base - the base address of the LED peripheral.
* @param timer_base - the base address of the User Timer peripheral.
*
*--------------------------------------------------------------------------------*/
/*
static void led_flash(alt_u32 led_base, alt_u32 timer_base)
{
  static alt_u8 led_pattern = 0x01;
  int ntick=0;

  led_pattern ^= 0x03; // toggle 2 LSBs of LEDs
  pio_write(led_base, led_pattern); // write LEDs
  while (ntick < 250) {
    if (timer_read_tick(timer_base)==1) {
      timer_clear_tick(timer_base);
      ntick++;
    }
  } // end while
}
*/
