#include <pic.h>
 // Шаблон прогрыммы для контроллера

/*
Программа часы пропеллер.
Показывает время при вращении вертикальной панельки светодиодов.
Выводит поочереди две надписи.
Имеет предустановку времени кнопками час и мин. 
При одновременном нажатии на кнопку час + мин или на час + дес мин устанавливаеться 
корректировка веремни. 
Любая корректировка выводиться на светодиоды в виде 2 кода.
Для начала отсчетаи исполузуетсья инфра датчик.
При прогрмамировании нужно зенести начальное значение коррекции
хода чосов в EEPROM память по адресу 0x00.
Желательно использывать значения от 24 до 124.

Программа написана 20.06.08
Автор Mizar

*/
// типа записывает данные в еепром
//#pragma romdata eedata = 0xf00000 
//rom unsigned char St0[]= __DATE__;
//rom unsigned char St1[]= __TIME__;
//#pragma romdata eedata

	__CONFIG(0x03FF1);

//#pragma psect 



// глобальные переменные
volatile unsigned int RTC = 0; 	// счетчик реального времени
unsigned char cor; // число корректирования 24 спешат 124 отстают
bit key1, key2, key3, iled; //флаги кнопок и инфра датчик
bit fv, ft,ftt;		// флаг смены индикации флаг номера текста
unsigned int Dfv; // длительность индикации
unsigned int Dlay; // длительность задержки
unsigned char sec=0, min=0, hour=0,thk=11;  //разряды времни
unsigned char edsec, edmin, edhour, dessec, desmin, deshour;  //разряды времни
unsigned char mess; // номер символа в тексте
char   message1 [9] = "lena+jeny";
char   message2 [12] = "y teby lublu";




// процедуры и функции
void Delay (int T)  // процедура задержки. 1 == 160млсек
{	Dlay = RTC + T;
	while (Dlay != RTC);
}

void corr () // запись значение корректировки в энергонезависимую память
{	eeprom_write(0x00 ,cor);
	PORTB = cor;	// показать двоичное значение
}
void key () // опрос состояния кнопок
{	if ((RA2 == 0) || (RA3 == 0) || (RA4 == 0)){
		if ((RA4 == 0) & (RA2 == 1) & (RA3 == 1)){//нажжата только одна кнопка
			hour++;			// пирбавить час
			if (hour > 23) hour = 0;
			PORTB = hour;	// показать двоичное значение
		}
//		if ((RA3 == 0) & (RA2 == 1) & (RA4 == 1)){//нажжата только одна кнопка
//			min = min +10;			// пирбавить 10 мин
//			if (min > 59) min = 0;
//			PORTB = min;	// показать двоичное значение
//		}
		if ((RA2 == 0) & (RA3 == 1) & (RA4 == 1)){//нажжата только одна кнопка
			min++;			// пирбавить 1 мин
			if (min > 59) min = 0;
			PORTB = min;	// показать двоичное значение
		}
	// корректировка хода часов
		if ((RA4 == 0) & (RA3 == 0)) {cor++; corr();} // если нажата кнопка час + дес мин
		if ((RA4 == 0) & (RA2 == 0)) {cor--; corr();}
	}
}


void symbol (char CH)	// процедура конвертирования
{	PORTB = 0;		// раздел
	Delay (2);		// задержка перед началом индикации
	switch (CH){	// символ конвертирования
		case 0 : 
			PORTB = 126;	Delay (1);
			PORTB = 129;	Delay (2);
	//		PORTB = 129;	Delay (1);
			PORTB = 126;	Delay (1);
		break;
	    case 1 : 
			PORTB = 128;	Delay (1);
			PORTB = 255;	Delay (1);
			PORTB = 130;	Delay (1);
			PORTB = 0;		Delay (1);
		break;			
       	case 2 : 
			PORTB = 142;	Delay (1);
			PORTB = 145;	Delay (1);
			PORTB = 161;	Delay (1);
			PORTB = 194;	Delay (1);
		break;			
       	case 3 :
			PORTB = 110;	Delay (1);
			PORTB = 145;	Delay (2);
	//		PORTB = 145;	Delay (1);
			PORTB = 66;		Delay (1);
		break;			
       	case 4 :
			PORTB = 255;	Delay (1);
			PORTB = 18;		Delay (1);
			PORTB = 20;		Delay (1);
			PORTB = 24;		Delay (1);
		break;			
       	case 5 :
			PORTB = 97;		Delay (1);
			PORTB = 145;	Delay (2);
	//		PORTB = 145;	Delay (1);
			PORTB = 159;	Delay (1);
		break;  
     	case 6 :
			PORTB = 98;		Delay (1);
			PORTB = 145;	Delay (2);
	//		PORTB = 145;	Delay (1);
			PORTB = 126;	Delay (1);
		break;  
     	case 7 :
			PORTB = 31;		Delay (1);
			PORTB = 33;		Delay (1);
			PORTB = 65;		Delay (1);
			PORTB = 129;	Delay (1);
		break;
     	case 8 :
			PORTB = 110;	Delay (1);
			PORTB = 145;	Delay (2);
	//		PORTB = 145;	Delay (1);
			PORTB = 110;	Delay (1);
		break;  
     	case 9 :
			PORTB = 126;	Delay (1);
			PORTB = 145;	Delay (2);
	//		PORTB = 145;	Delay (1);
			PORTB = 78;		Delay (1);
		break;
	    case 'l' : // Л
			PORTB = 255;	Delay (1);
			PORTB = 1;		Delay (1);
			PORTB = 2;		Delay (1);
			PORTB = 252;	Delay (1);
		break;
	    case 'e' : // Е
			PORTB = 129;	Delay (1);
			PORTB = 145;	Delay (2);
	//		PORTB = 145;	Delay (1);
			PORTB = 255;	Delay (1);
		break;			
       	case 'n' : // Н
			PORTB = 255;	Delay (1);
			PORTB = 16;		Delay (2);
	//		PORTB = 16;		Delay (1);
			PORTB = 255;	Delay (1);
		break;			
       	case 'a' :// А
			PORTB = 255;	Delay (1);
			PORTB = 17;		Delay (1);
			PORTB = 18;		Delay (1);
			PORTB = 252;	Delay (1);
		break;			
       	case 'j' :// Ж
			PORTB = 199;	Delay (1);
			PORTB = 40;		Delay (1);
			PORTB = 255;	Delay (1);
			PORTB = 40;		Delay (1);
			PORTB = 199;	Delay (1);
		break;			
      	case 'y' :// Я
			PORTB = 255;	Delay (1);
			PORTB = 17;		Delay (1);
			PORTB = 49;		Delay (1);
			PORTB = 206;	Delay (1);
		break;  
		case 't' :// Т
			PORTB = 1;		Delay (2);
			PORTB = 255;	Delay (1);
			PORTB = 1;		Delay (2);
		break;  
		case 'b' :// Б
			PORTB = 97;		Delay (1);
			PORTB = 145;	Delay (2);
			PORTB = 255;	Delay (1);
			
		break;  
		case 'u' :// Ю
			PORTB = 126;	Delay (1);
			PORTB = 129;	Delay (1);
			PORTB = 126;	Delay (1);
			PORTB = 16;		Delay (2);
			PORTB = 255;	Delay (1);
		break;  

		case ' ' : // пробел
		//	PORTB = 0;		Delay (1);
		//	PORTB = 0;		Delay (1);
	//		PORTB = 0;		Delay (1);
			PORTB = 0;		Delay (2);
		break;		
		case '+' : // +
		//	PORTB = 0;		Delay (1);
			PORTB = 16;		Delay (1);
			PORTB = 56;		Delay (1);
			PORTB = 16;		Delay (1);
		break;	
		case 12 : // двоеточие точка вверху
		//	PORTB = 0;		Delay (1);
			PORTB = 6;		Delay (1);
		//	PORTB = 0;		Delay (1);
		//	PORTB = 0;		Delay (1);
		break;	
		case 13 : // двоеточие две точки
		//	PORTB = 0;		Delay (1);
			PORTB = 102;	Delay (1);
		//	PORTB = 0;		Delay (1);
		//	PORTB = 0;		Delay (1);
		break;
		case 14 : // двоеточие точка внизу
		//	PORTB = 0;		Delay (1);
			PORTB = 96;		Delay (1);
		//	PORTB = 0;		Delay (1);
		//	PORTB = 0;		Delay (1);
		break;
			case 15 : // сердце
			PORTB = 0;		Delay (1);
			PORTB = 24;		Delay (1);
			PORTB = 36;		Delay (1);
			PORTB = 72;		Delay (1);
			PORTB = 36;		Delay (1);
			PORTB = 24;		Delay (1);
			PORTB = 0;		Delay (1);
		break;
	}
	PORTB = 0; // после индикации выключаем диоды.
}

void time ()		// вычисление времени
{ 
	if (sec > 59){	// если сек 60 то ставим 0 и прибавляем минуту
		sec = 0;
		min++;
	}
	if (min > 59){	// если мин 60 то ставим 0 и прибавляем час
		min = 0;
		hour++;
	}
	if (hour > 23){ //если 24 часа то ставим 0 и ничего не прибавляем
		hour = 0;
	}
}
void Rtime ()  // вычисление разрядов времени
{ 	
	dessec = sec/10;				// вычисление десятков сек
	edsec = (sec - (dessec*10));	// вычисление единиц сек
	
	desmin = min/10;				// вычисление десятков мин
	edmin = (min - (desmin*10));	// вычисление единиц мин

	deshour = hour/10;				// вычисление десятков час
	edhour = (hour - (deshour*10));	// вычисление единиц час
	if (deshour == 0) deshour = 11; // если десятки часов=0 то пробел
}

void interrupt tmr0_int (void) // обработчик прерывания от таймера
{	
	if (T0IF) { // если запрос на прерывание посупил от таймера TMR0
		T0IF = 0;  // то сбросить флаг прерывания
	 	RTC++;     //  и выполнить инкремент счетчика реального времени
// здесь можно описать дополнительные действия
// для обработки прерывания от таймера
		if ((RTC % 512) == 0){ 
			thk++;
			key();
		}
		if ((RTC % (1000+cor)) == 0){
			sec++;				// счетчик секунд
			time();
			Dfv++;
		}
//		if ((RTC %512) == 0) 			//начало условия
//		{	// операторы каждую секунду
//
//		}  	// конец условия	выполнения кажд сек
//			// операторы каждую секунду
	} 	// конец условного оператора
	
// здесь можно разместить код для обработки прерываний
// от других источников

} // конец обработчика прерываний
// служебная программа

// главная программа
void main (void)
{
	TMR0 = 0; 			// начальное значение счетчика реального времени
	OPTION = 0x0D1; 	// предделитель совместно с TMR0 К.Д. 4
//	OPTION = 0x051;
	T0IE = 1;			// разрешить прерывания от таймера
	GIE = 1;			// разрешить обработку прерываний
	// здесь надо выполнить инициализацию переферийных устройств
	TRISB = 0;   // настраиваем порт В на выход
	TRISA = 255;	// настраиваем порт A на вход
//	PORTB = 0;
	EEADR = 0x00;  // считываем из памяти  значение короректировки.
		RD = 1;
	cor = EEDATA;	

	while (1 == 1) { 	// бесконечный цикл
	// здесь располагаеться код основной программы.
	
		if (thk == 15) thk = 11;  // сброс мигания точки
		// переключение между индикациями 
		if ((Dfv > 10 ) & (fv == 1)){ 	// ждем 10 сек время
			Dfv = 0; 					// сбрасываем счетчик вермени
			fv = 0;} 					// переключаем флаг индикации
		if ((Dfv > 6 ) & (fv == 0)){ 	// ждем 6 сек текст
			Dfv = 0; 					// сбрасываем счетчик вермени
			fv = 1;
			if ((ft == 1) & (ftt == 1)) ft = 0; // операции с флагами текста
			if ((ft == 0) & (ftt == 0)) ft = 1;	// для поочередного переключения
		} //  переключаем флаг индикации

//		if (RA1 == 1) PORTB = 0;	// выключаем диоды если нет вращения
		if (RA1 == 0){				// индицируем если сраб датчик
			if (fv == 1) { // индикация времени 4 сек
				Rtime();
				Delay(15);  // отступаем от начала для центровки относительно надписи
				symbol(edsec);				// индицируем 6 разряд сек 
				symbol(dessec);				// индицируем 5 разряд дес сек
				symbol(thk);				// индицируем раздел точки :
				symbol(edmin);				// индицируем 4 разряд мин
				symbol(desmin);				// индицируем 3 разряд дес мин
				symbol(thk);				// индицируем раздел точки :
				symbol(edhour);				// индицируем 2 разряд час
				symbol(deshour);			// индицируем 1 разряд дес час 
			}
			if (fv == 0) { // индикация текста 6 сек
				if (ft == 1){ // если текст первый
					symbol(15);		// сердечко
					for (mess = 0; mess < 9; mess++){  // генерация текста
						symbol(message1[8-mess]);		// вывод текста
					}
					symbol(15);		// сердечко
					ftt = 1;  // после индикации сменим на 2 текст
				}// конец первого текста
				if (ft == 0){ // если текст второй
					for (mess = 0; mess < 12; mess++){  // генерация текста
						symbol(message2[11-mess]);		// вывод текста
					}
					ftt = 0;  // после индикации сменим на 1 текст
				}// конец второго текста
			}
		}		// конец условия датчика.

	}			// конец цикла
}				// конец программы


