//*********************************************************************
//
//    MMC/SD ЗАГРУЗЧИК версия 1.0.
// 
// 1. Добавляем makefile.mak в проект. Идем 
//    Project ->Configuration options. 
//    На вкладке General устанавливаем галку Use external makefile. 
//    Нажмаем "…" находим makefile.mak.
//
// 2. В makefile.mak настраиваем параметры компиляции загрузчика: 
//    MCU - модель процессора
//    F_CPU - рабочая частота процессора
//    BOOTLDRSIZE - размер загрузчика 
//    BOOTLOADERSTARTADR - стартовый адрес загрузчика
//    TARGET - имя *.hex файла, получаемого при компиляции
//    OBJDIR - директория, в которую происходит компиляция загрузчика
//
// 3. В mmc.h в секции, соответствующей модели процессора 
//    (см. makefile.mak, параметр MCU) настраиваем ноги, на которые 
//    вешается SD карта. Ноги SPI_DI, SPI_DO, SPI_Clock должны быть 
//    стандартными для интерфейса SPI т.к. программная реализация SPI 
//    отсутствует. Ноги MMC_Chip_Select и SPI_SS настраиваются в 
//    соответствии со схемной реализацией. 
//    Для SD карты MMC_Chip_Select  = SPI_SS.
//
// 4. В megavar.h, если модель процессора отсутствует, настраиваем
//    размеры EEPROM и FLASH памяти в секторах для программирования: 
//    EE_SECTOR_FOR_READ и FL_SECTOR_FOR_READ для EEPROM и FLASH памяти
//    соответственно. 
// 
// 5. В main.с в процедуре int main(void) настраиваем условие сработки 
//    bootloader-a (например низкий сигнал на PINC) и имя файла для 
//    загрузки без расширения (переменная filename[]), например "boot".
// 
// 6. SD карта должна быть отформатирована в системе FAT16. 
//    На карточке должны размещаться bin-файлы EEPROM и FLASH. 
//    Например "boot.ee" и "boot.fl" Расширение файла EEPROM - "ee", 
//    расширение FLASH - "fl". Файл FLASH может отсутствовать. 
//    Файл EEPROM должен быть всегда. Размеры файлов - постоянная 
//    величина равная EE_SECTOR_FOR_READ*512 и FL_SECTOR_FOR_READ*512 
//    для EEPROM и FLASH соответственно.
// 
// 7. В версии 1.0 программирование FLASH отсутствует из-за не хватки 
//    памяти загрузчика.
// 
// 8. Для программирования чипа используйте 
//    progeeprom32.bat (программирование загрузчика) и 
//    progHfuse32.bat (программирование фьюзов). 
//    Для программатора отличного usbasp 
//    скорректировать указанные файлы.
//
// 9. Со всеми вопросами обращаетесь на адрес matrex@rambler.ru.
// 
// 10. При написании программы использовались следующие материалы:
//     http://www.mikrocontroller.net/articles/MMC/SD_Bootloader_f%C3%BCr_AT_Mega
//     http://www.ulrichradig.de/home/index.php/avr/mmc-sd
//
//*********************************************************************

#include <avr/boot.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "mmc.h"
#include "fat.h"
#include "megavar.h"

void (*app_start)(void) = 0x0000;

void upload(char *filename, unsigned char memtype)
{
	unsigned char Buffer[512];
	unsigned int tmp;
	unsigned int Clustervar=0;
	unsigned char Dir_Attrib = 0;
	unsigned long Size = 0;
	uint16_t filesector, j;
	uint8_t i;
	uint16_t *lpword;
	uint16_t adr;
	uint8_t gBuffer[SPM_PAGESIZE];
	if (mmc_init() !=0) return; // не смогли инициализировать карту
	fat_init();
	if (fat_search_file(filename,&Clustervar,&Size,&Dir_Attrib,Buffer) != 1) return; // файл отсутствует
	switch (memtype) // Какую память будем программировать
	{
	case 0:
		// программируем EEPROM
		for (filesector = 0; filesector < EE_SECTOR_FOR_READ ; filesector++)
		{
		lpword = (uint16_t*) Buffer;
		fat_read_file (Clustervar,Buffer,filesector);
		for (i=0; i<(512 / SPM_PAGESIZE); i++)
			{
			adr = (filesector * 512) + i * SPM_PAGESIZE;
			boot_page_erase(adr);
			while (boot_rww_busy())
				boot_rww_enable();
			for (j=0; j<SPM_PAGESIZE; j+=2)
				boot_page_fill(adr + j, *lpword++);
			boot_page_write(adr);
			while (boot_rww_busy())
				boot_rww_enable();
			}; 
		 };break;


	default:
		// программируем FLASH
		for (filesector = 0; filesector < FL_SECTOR_FOR_READ ; filesector++)
		{
		lpword = (uint16_t*) Buffer;
		fat_read_file (Clustervar,Buffer,filesector);
		for (i=0; i<(512 / SPM_PAGESIZE); i++)
			{
			adr = (filesector * 512) + i * SPM_PAGESIZE;
			//  Здесь должен быть загрузчик FLASH.
			}; 
		 };break;
	}
}


void loadmemory(char *filename)
{
char f[13];
char ee=".ee";
char fl=".fl";
memset(f,0,sizeof(f));
strcat(f,filename);
strcat(f,ee);
upload(f,0); // загрузить EEPROM
memset(f,0,sizeof(f));
strcat(f,filename);
strcat(f,fl);
upload(f,1); // загрузить FLASH
}




int main(void)
{
char filename[]="boot";     // имя файла, который будет загружатся если 
							// сработает условие загрузки
cli();						// запрет прерываний
PORTC = 0xFF; 				// настройка порта С
DDRC  = 0x00;				// настройка порта С
if (PINC!=255) 			    // условие
	loadmemory(filename);   // сработки bootloader-а
app_start();				// запуск приложения
}
