#include<reg51.h>
unsigned char sem_segment[14];		//Объявляем массив кодов семисегментных индикаторов
char tsifra;				//Объявляем переменную, в которую будем помещать цифру для вывода
char chislo[6];				//Объявляем массив цифр выводимого на индикатор числа
char mem [4];				//Объявляем массив памяти для хранения введенных с клавиатуры чисел				
char alarm[4];
unsigned char znakomesto,i,j,otp,razr=1,sec,min,chas;
int chas_cor,min_cor;
unsigned int vrem, vrem_sec, vrem_cor, bud_time;
unsigned char temp,SkanCode;
char set=0;				//Признак входа в режим настройки времени или будильника
char pm;				//Указатель второй половины дня
char pm_bud;				//Указатель второй половины дня для будильника
char sekunda;				//Указатель прошедшей секунды
char dobro;				//Разрешает работу будильника

void init (void)
{
sem_segment[0]=0xfc;			//Заносим в массив коды соответствующих цифр
sem_segment[1]=0x60;
sem_segment[2]=0xda;
sem_segment[3]=0xf2;
sem_segment[4]=0x66;
sem_segment[5]=0xb6;
sem_segment[6]=0xbe;
sem_segment[7]=0xe0;
sem_segment[8]=0xfe;
sem_segment[9]=0xf6;
sem_segment[10]=0x00;			//Ничего не выводится на индикатор
sem_segment[11]=0xee;			//Код символа "А"
sem_segment[12]=0x1e;			//Код символа "t"
sem_segment[13]=0x9e;			//Код символа "Е"
SCON=0;					//Настраиваем последовательный порт на режим регистра сдвига
TMOD=0x01;
TH0=(-10000)>>8;
TL0=-10000;
TF0=0;
TR0=1;
IE=(1<<7)|
   (1<<1);
}

void prerT0 (void) interrupt 1
{
TF0=0;
TR0=1;
vrem=vrem+1;
if (vrem==7)				 
{                                       //Если прошла секунда
vrem=0;                                 //обнулить переменную vrem
sekunda=1;				//и установить в единицу указатель секунд
}
}

void vyvod (void)
{
P1=0x07+(sec%2)+dobro;	       			//Все единицы на Р1 => дешифратор не включает ни одного индикатора
tsifra=chislo[znakomesto];		//Берем цифру для вывода 
TF0=0;					//Сбрасываем флаг окончания передачи
if ((znakomesto==1)||(znakomesto==3)) 
SBUF=sem_segment[tsifra]+1;
else SBUF=sem_segment[tsifra];		//Пересылаем код цифры для отображения
while(T1==0);
P1=znakomesto+0xf0;			//очередного знакоместа
temp=P1;				//Прочитать состояние кнопок в переменную временного хранения
for(i=7;i>0;i--);			//Задержка времени для индикации
if (temp==otp) razr=1;                  //Если предыдущая нажатая кнопка отпущена, разрешить считывание следующей

if((temp !=(znakomesto+0xf0))&&(razr==1))
{
SkanCode=temp;				//Если хоть одна кнопка нажата, запомнить скан-код 
otp=znakomesto+0xf0;                    //Заносим код кнопки, которую нужно проверить на отпускание
razr=0;                                 //запретить повторное считывание нажатой кнопки
}
}
 
void time (void)
{
if (sekunda==1) 
{
vrem_sec=vrem_sec+1;
sekunda=0;
}
if (vrem_sec==43200) 
{
vrem_sec=0;
pm=pm+1;
}
sec=(vrem_sec%60);			//Получаем только секунды
chislo[5]=sec%10;                       //Получаем единицы секунд
chislo[4]=sec/10;                       //Получаем десятки секунд
min=(vrem_sec/60)%60;			//Получаем только минуты
chislo[3]=min%10;			//Получаем единицы минут
chislo[2]=min/10;			//Получаем десятки минут
chas=(vrem_sec/3600);			//Получаем только часы
if ((pm%2)==1) chas=chas+12;		//Если стоит флаг второй половины дня, добавляем еще 12 часов
chislo[1]=chas%10;			//Получаем единицы часов
chislo[0]=chas/10;                      //Получаем десятки часов
}

void setup (void)
{
SkanCode=0;
j=0;
for(znakomesto=0;znakomesto<7;znakomesto++)
chislo[znakomesto]=10;			//Забиваем все ячейки пустым значением
}
  
void time_correct (void)
{
chas_cor=(mem[0]*10+mem[1]);
min_cor=(mem[2]*10+mem[3]);
if ((chas_cor<25)&&(min_cor<60))
{
if (chas_cor>12)
{
chas_cor=chas_cor-12;			//Если количество часов превышает 12, уменьшаем на 12
pm=1;                                   //и выставляем флаг второй половины дня
}
vrem_cor=(chas_cor*60+min_cor)*60+sec;	//Подсчитываем время в секундах
vrem_sec=vrem_cor;
vrem_cor=0;
set=0;
} 
else
{
for(znakomesto=0;znakomesto<4;znakomesto++)
mem[znakomesto]=0;
chislo[0]=13;
}
}

void alarm_correct (void)
{
set=0;
for (znakomesto=0;znakomesto<4;znakomesto++)
alarm[znakomesto]=mem[znakomesto];
}

void key_enter (void)
{
switch (SkanCode)
{
case 0x70: {chislo[j+2]=1;mem[j]=1; j=j+1;SkanCode=0;} break;
case 0xB0: {chislo[j+2]=2;mem[j]=2; j=j+1;SkanCode=0;} break;
case 0xD0: {chislo[j+2]=3;mem[j]=3; j=j+1;SkanCode=0;} break;
case 0x71: {chislo[j+2]=4;mem[j]=4; j=j+1;SkanCode=0;} break;
case 0xB1: {chislo[j+2]=5;mem[j]=5; j=j+1;SkanCode=0;} break;
case 0xD1: {chislo[j+2]=6;mem[j]=6; j=j+1;SkanCode=0;} break;
case 0x72: {chislo[j+2]=7;mem[j]=7; j=j+1;SkanCode=0;} break;
case 0xB2: {chislo[j+2]=8;mem[j]=8; j=j+1;SkanCode=0;} break;
case 0xD2: {chislo[j+2]=9;mem[j]=9; j=j+1;SkanCode=0;} break;
case 0xB3: {chislo[j+2]=0;mem[j]=0; j=j+1;SkanCode=0;} break;
default: ;
}
}

void alarm_check(void)
{
if ((alarm[0]==chislo[0])&&(alarm[1]==chislo[1])&&(alarm[2]==chislo[2])&&(alarm[3]==chislo[3])&&(alarm[0]!=0)&&(alarm[1]!=0)&&(alarm[2]!=0)&&(alarm[3]!=0)) dobro=1;
if (chislo[3]>alarm[3]) dobro=0;
}

void obrab (void)
{
switch (SkanCode)
{
case 0xD3: {if (set==0){set=1;setup();chislo[0]=12;}else {time_correct();SkanCode=0;}} break;
case 0x73: {if (set==0){set=2;setup();chislo[0]=11;}else {alarm_correct();SkanCode=0;}} break;
default: ;
}
if (j<4) key_enter();
}

void indikat (void)
{
for(znakomesto=0;znakomesto<7;znakomesto++)
vyvod();
}

void main (void)
{
init();					//Вызов функции init
for(;;)
{
if (set==0) time();
indikat();
obrab();
alarm_check();
}
}

