/*
 * mega8_wav.c
 *
 *  Created on: 11.07.2013
 *      Author: Apparatchik
 */

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>
#include "diskio.h"
#include "pff.h"
#include "integer.h"

#define LED_ON PORTB |= 0x01
#define LED_OFF PORTB &= 0xFE

uint8_t wave_play(char *FileName);

uint8_t DAC_Buff[512];                   //буфер данных ЦАПа
volatile uint16_t count_buff;
FATFS fs;           //понадобится для работы с диском
FRESULT res;                        //для возвращаемого функциями результата
DIR dir; // объект каталог
FILINFO fno; // информационная структура файла

// Timer 2 output compare A interrupt service routine
ISR (TIMER2_COMP_vect) {
	OCR1A = DAC_Buff[count_buff];
	if (++count_buff >= 512)
		count_buff = 0;
}

int __attribute__((OS_main)) main(void) {
	// Input/Output Ports initialization
	DDRB = 0x03;

	// Timer/Counter 1 initialization
	// Clock value: 16000,000 kHz
	// Mode: Fast PWM top=00FFh
	TCCR1A=0x81; // OC1A output: Non-Inv.
//	TCCR1A=0xC1; // OC1A output: Inverted
	TCCR1B=0x09;

	// Timer/Counter 2 initialization
	// Mode: CTC top=OCR2
//	TCCR2=0x0C; // Clock value: 250,000 kHz
	TCCR2=0x0A; // Clock value: 2000,000 kHz
//	OCR2=0x07; // 8 - 1 = 7 для частоты дискритизации 31250 Гц
	OCR2=0x2C; // 45 - 1 = 44 для частоты дискритизации 44100 Гц

	// Analog Comparator: Off
	ACSR = 0x80;

	LED_ON;
	_delay_ms (1000);
	LED_OFF;
	_delay_ms(1000);

	sei();

	BYTE status = disk_initialize(); //инициализируем карточку

	if (status) {
		while (status) {
			LED_ON;
			_delay_ms(250);
			LED_OFF;
			_delay_ms(250);
			status--;
		}
	} else {
		LED_ON;

//		if (!(pf_opendir(&dir, "/"))) { //Открываем директорию
//
//			do {
//				if (pf_readdir(&dir, &fno) == FR_OK) {
//					if (!(fno.fattrib & AM_DIR) && fno.fname[0] != 0) {	//Если объект не директория
//						wave_play(fno.fname);
//					}
//				}
//			} while (fno.fname[0] != 0);
//
////			while (pf_readdir(&dir, &fno) == FR_OK && fno.fname[0] != 0) {
////				if (!(fno.fattrib & AM_DIR)) {	//Если объект не директория
////					wave_play(fno.fname);
////				}
////			}
//		}


		wave_play ("44100.wav");
		LED_OFF;
	}

	_delay_ms(1000);

	while (1) {
		LED_ON;
		_delay_ms(100);
		LED_OFF;
		_delay_ms(100);
	}
}

//*********************************************************************************************
//function воспроизвести wave-файл                                                           //
//argument имя файла                                                                         //
//result   0 - все нормально, иначе - ошибка                                                 //
//*********************************************************************************************
uint8_t wave_play(char *FileName) {
	WORD cnt;                              //количество реально прочитанных байт
	uint8_t buf = 0;

	pf_mount(&fs);           //монтировать диск

	res=pf_open(FileName); //Откроем файл
	if (res)
		return 1;

//	res=pf_lseek (0x2C); //переместить указатель на начало полезных данных
//	if (res)
//		return 2;
//-------------------------------------------------------------------------------------
	res = pf_read (&DAC_Buff[0], 64, &cnt);  //загрузить первые 64 байт
	if (res || cnt != 64)
		return 4;
	else {
		  //байты 0..3 - должен быть маркер "RIFF"
		  if(DAC_Buff[0]!='R' || DAC_Buff[1]!='I' || DAC_Buff[2]!='F' || DAC_Buff[3]!='F')     res = 2;

		  //байты 8..11 - должен быть маркер "WAVE"
		  if(DAC_Buff[8]!='W' || DAC_Buff[9]!='A' || DAC_Buff[10]!='V' || DAC_Buff[11]!='E')   res = 2;

		  //байты 12..15 - должен быть маркер "fmt "
		  if(DAC_Buff[12]!='f' || DAC_Buff[13]!='m' || DAC_Buff[14]!='t' || DAC_Buff[15]!=' ') res = 2;

		  //байты 20,21  - 1 и 0
		  if(DAC_Buff[20]!=1 || DAC_Buff[21]!=0) res = 2;

//		  //вычислить размер чанка "fmt "
//		  i = DAC_Buff[16] | (DAC_Buff[17]<<8) | (DAC_Buff[18]<<16) | (DAC_Buff[19]<<24);
//
//		  //после чанка "fmt " должен следовать чанк "data"
//		  if(DAC_Buff[20+i]!='d' || DAC_Buff[21+i]!='a' || DAC_Buff[22+i]!='t' || DAC_Buff[23+i]!='a') res = 2;

		  if (res == 2) {
			pf_mount(0x00);
			return 5;                   //ошибка формата файла
		}
	}
//--------------------------------------------------------------------------------------------
	res = pf_read(&DAC_Buff[0], 512, &cnt);//Считаем первые 512 байт
	if (res)
		return 3;

	TIMSK = 0x80;                   //запустить преобразование

	/*                        воспроизведение                              */
	while (1) {
		if (!buf && count_buff > 255) { //ждем освобождение первой части буфера
			pf_read(&DAC_Buff[0], 256, &cnt);    //загрузить ее данными
			buf = 1;
			if (cnt < 256)
				break;                        //если конец файла
		}

		if (buf && count_buff < 256) { //ждем освобождение второй части буфера
			pf_read(&DAC_Buff[256], 256, &cnt);  //загрузить ее данными
			buf = 0;
			if (cnt < 256)
				break;                        //если конец файла
		}
	}

	TIMSK = 0x00;                  //остановить преобразование

	res=pf_mount(0x00); //Демонтируемt FAT
	return 0;                                   //успешное завершение ф-ии
}
