#include "iostm8l152k6.h"
//#include "stm8l15x.h"
#define DEBUD 0
#define RS PD_ODR_bit.ODR1
#define E PD_ODR_bit.ODR2
#define LED ODR_bit.ODR5
#define COM 0
#define DATA 1
#define str1 0x80
#define str2 0xC0
#define WAIT_SECONDS_ON_INIT  3
////////////////////////////////////////////////////////////////////////////////
//#define LCDDISP 1// устанавливается 1, если LCD
//#define SEVENSEG 1//устанавливается 1, если семисегментный индикатор
///////////////////////////////////////////////////////////////////////////////
#define task 1 //Количество минут до смены надписи
#define save 1 //Период сохранения данных в минутах
#define DB0 PC_ODR_bit.ODR5
#define DB1 PC_ODR_bit.ODR6
#define DB2 PA_ODR_bit.ODR4
#define DB3 PA_ODR_bit.ODR5
#define WR1 PA_ODR_bit.ODR6
#define A0 PB_ODR_bit.ODR2//0-адрес, 1-данные
#define RES PB_IDR_bit.IDR3
#define flag_res 1////устанавливается 0 для сброса, после этого должен быть установлен в 1 с последующей перепрошивкой контроллера
char num_array[] = {0x77, 0x60, 0x4F, 0x6B, 0x78, 0x3B, 0x3F, 0x61, 0x7F, 0x7B, 0x00, 0xFF};
int i=0;
int count=0;
int timeinit = WAIT_SECONDS_ON_INIT;
typedef unsigned long     uint32_t;
uint32_t sec=0;
uint32_t upsec=0;
uint32_t min=0;
uint32_t upmin=0;
uint32_t hour=0;
uint32_t uphour=0;
uint32_t uphours=0;
uint32_t uphourt=0;
uint32_t uphourdt=0;
uint32_t uphourst=0;

// Ниже указаны области в eeprom для всех переменных от минут до сотен тысяч часов

#pragma location =0x1030 //адрес для минут в EEPROM
__no_init uint32_t Emin;

#pragma location =0x1050 //адрес для десятков минут в EEPROM
__no_init uint32_t Eupmin;

#pragma location =0x1070 // адрес для часов в EEPROM
__no_init uint32_t Ehour;

#pragma location =0x1090
__no_init uint32_t Euphour;

#pragma location =0x10B0 //адрес для сотен часов в EEPROM
__no_init uint32_t Euphours;

#pragma location =0x10D0 //адрес для тысяч часов в EEPROM
__no_init uint32_t Euphourt;

#pragma location =0x10F0 //адрес для десятков тысяч часов в EEPROM
__no_init uint32_t Euphourdt;

#pragma location =0x1110 //адрес для сотен тысяч часов в EEPROM
__no_init uint32_t Euphourst;


// Прерывание по переполнению Timer1

#define STRINGVECTOR(x) #x
 #define ISR( a, b )  \
 _Pragma( STRINGVECTOR( vector = (b) ) )        \
 __interrupt void (a)( void )

ISR(TIM1_OVF, TIM1_OVR_UIF_vector)
{
    PD_ODR_bit.ODR5 ^= 1; //Инвертируем пин с тестовым светодиодом
    i = 1;
    TIM1_SR1_bit.UIF = 0; // сброс флага для выхода из прерывания
};
void Delay() // функция задержки
{
    for (unsigned long delay_count=0; delay_count<300; delay_count++);
};

void SomeDelay() // функция задержки
{
    for (unsigned long delay_count=0; delay_count<20; delay_count++);
};
void SaveTime () // Сохранение данных раз в указанное время
{
    Emin      = min;
    Eupmin    = upmin;
    Ehour     = hour;
    Euphour   = uphour;
    Euphours  = uphours;
    Euphourt  = uphourt;
    Euphourdt = uphourdt;
    Euphourst = uphourst;
};

// инициализация и настройка Timer1

void Timer1_Init()
{
    /* 000: System clock source/1 */
    CLK_CKDIVR = 0;
    /* TIM1 */
    CLK_PCKENR2_bit.PCKEN21 = 1; //Включаем тактирование таймера 1
#if defined(DEBUD) && DEBUG==1
    PD_DDR_bit.DDR5 = 1;//Настройка вывода D5 с тестовым светодиодом
    PD_CR1_bit.C15 = 1;
#endif
    TIM1_PSCRH = (1599) >> 8; //Настройка предделителя
    TIM1_PSCRL = (1599)& 0xFF;
    TIM1_ARRH = (10000) >> 8; //Настройка предустановки
    TIM1_ARRL = (10000)& 0xFF;

    TIM1_CR1_bit.URS = 1; //Прерывание только по переполнению счетчика
    TIM1_EGR_bit.UG = 1;  //Вызов Update Event

    TIM1_IER_bit.UIE = 1; //Разрешение прерываний
    TIM1_CR1_bit.CEN = 1; //Запуск таймера
};

/*
void LCD_WR (char instr, char com_val) // функция вывода на дисплей требует инструкции команды или данные и значений для них
{
   RS = instr;
   SomeDelay();
   
   E = 0;
   PB_ODR = com_val;
   E = 1;
   SomeDelay();
   
   E = 0;
   SomeDelay();
   
};

void init_LCD () // функция инициализации
{
    PB_DDR = 0xFF; //все порты B настраиваются на вход в режиме push-pull
    PB_CR1 = 0xFF;
    PD_DDR_bit.DDR1 = 1;// порты D1 и D2 настраиваются на выход в режиме push-pull
    PD_DDR_bit.DDR2 = 1;
    PD_CR1_bit.C11  = 1;
    PD_CR1_bit.C12  = 1;
    RS = 0; //D1=0
    E  = 0; //D2=0

    LCD_WR(COM,0x30);// инициализация дисплея 
    LCD_WR(COM,0x20); 
    LCD_WR(COM,0x20);  
    LCD_WR(COM,0x80); 
    LCD_WR(COM,0x00);
    LCD_WR(COM,0x80);
    LCD_WR(COM,0x00);
    LCD_WR(COM,0x60);
    LCD_WR(COM,0x00);
    LCD_WR(COM,0xC0);
};

void WRITE_LCD(char line_num, char line_symbol, char place1, char num)//запись символа на дисплей в конкретное место
{
    char new_num = num<<4;
    LCD_WR(COM,  line_num);
    LCD_WR(COM,  place1);
    LCD_WR(DATA, line_symbol);
    LCD_WR(DATA, new_num);
};
*/

void WRITE_SEVENSEG(char a)
{
    //write low
    DB0 = (num_array[a]&0x08)>>3;
    DB1 = (num_array[a]&0x04)>>2;
    DB2 = (num_array[a]&0x02)>>1;
    DB3 = (num_array[a]&0x01);
    WR1 = 1;
    Delay();

    WR1 = 0;
    
    //write high
    DB0 = 0;
    DB1 = (num_array[a]&0x40)>>6;
    DB2 = (num_array[a]&0x20)>>5;
    DB3 = (num_array[a]&0x10)>>4;
    WR1 = 1;
    Delay();
    
    WR1 = 0;
};

void WRITE_SEVENSEG_dot(char a)
{
    //write low
    DB0 = (num_array[a]&0x08)>>3;
    DB1 = (num_array[a]&0x04)>>2;
    DB2 = (num_array[a]&0x02)>>1;
    DB3 = (num_array[a]&0x01);
    WR1 = 1;
    Delay();
    
    WR1 = 0;
    
    //write high
    DB0 = 1;
    DB1 = (num_array[a]&0x40)>>6;
    DB2 = (num_array[a]&0x20)>>5;
    DB3 = (num_array[a]&0x10)>>4;
    WR1 = 1;
    Delay();

    WR1 = 0;
};

void set_addr0()
{
    WR1 = 0;
    A0  = 1;
    DB0 = 0;
    DB1 = 0;
    DB2 = 0;
    DB3 = 0;
    A0  = 0;
    WR1 = 1;
    Delay();
    
    WR1 = 0;
    A0  = 1;
};

void init_SEVENSEG()
{
  PC_DDR = 0xFF; //все пины C настраиваются на выход в режиме push-pull
  PC_CR1 = 0xFF;
  PA_DDR = 0x70;
  PA_CR1 = 0x70;
  PB_DDR_bit.DDR2=1;
  PB_CR1_bit.C12=1;
  /*
  WR1=0;
  A0=1;
  DB0=0;
  DB1=0;
  DB2=0;
  DB3=0;
  A0=0;
  WR1=1;
  Delay();
  WR1=0;
  A0=1;
  WRITE_SEVENSEG(10);
  WRITE_SEVENSEG(10);
  */
  set_addr0();
  WRITE_SEVENSEG(0);
  WRITE_SEVENSEG(0);
  WRITE_SEVENSEG(0);
  WRITE_SEVENSEG(0);
  WRITE_SEVENSEG(0);
  WRITE_SEVENSEG(0);
  WRITE_SEVENSEG(0);
  WRITE_SEVENSEG(0);
  WRITE_SEVENSEG(0);
  WRITE_SEVENSEG(0);
};

void zero_SEVENSEG()
{
    set_addr0();
    WRITE_SEVENSEG(0);
    WRITE_SEVENSEG(0);
    WRITE_SEVENSEG(0);
    WRITE_SEVENSEG(0);
    WRITE_SEVENSEG(0);
    WRITE_SEVENSEG(0);
    WRITE_SEVENSEG(0);
    WRITE_SEVENSEG(0);
    WRITE_SEVENSEG(0);
    WRITE_SEVENSEG(0);
}


void set_addr()
{
  WR1=0;
  A0=1;
  DB0=0;
  DB1=1;
  DB2=0;
  DB3=0;
  A0=0;
  WR1=1;
  Delay();
  WR1=0;
  A0=1;
};

void WatchDog_ON()
{
  IWDG_KR=0xCC;
  IWDG_KR=0x55;
  IWDG_PR=0x04;
  IWDG_RLR=0xC0;
};

void refreshDisplay()
{
    double curtimes;
    curtimes = ((uphourst*100000 + uphourdt*10000 + uphourt*1000 + uphours*100 + uphour*10 + hour)*60 + upmin*10 + min);
    //
    //if (SEVENSEG)
    //{    
    set_addr();
    if (curtimes >= 6000000) {
        WRITE_SEVENSEG(uphourst);
    }
    else {
        WRITE_SEVENSEG(10);
    }
    //
    if (curtimes >= 600000) { 
        WRITE_SEVENSEG(uphourdt);
    }
    else {
        WRITE_SEVENSEG(10);
    }
    //
    if (curtimes >= 60000) {
        WRITE_SEVENSEG(uphourt);
    }
    else {
        WRITE_SEVENSEG(10);
    }
    //
    if (curtimes >= 6000) {
        WRITE_SEVENSEG(uphours);
    }
    else {
        WRITE_SEVENSEG(10);
    }
    //
    WRITE_SEVENSEG(uphour);
    WRITE_SEVENSEG_dot(hour);
    WRITE_SEVENSEG(upmin);
    WRITE_SEVENSEG(min);
    //}
}

int main( void )
{
	// PB_CR1_bit.CR11=1; // PB_ICR_bit.ICR10 = 1;
	//PB_DDR_bit.DDR3 = 0;   // ����� PB0 ��������������� �� ����
	//PB_CR1_bit.C11 = 1;   // ����� ��������� - � ���� ���������� ������������� ��������
	//PB_CR2_bit.C20 = 0;   // ���������� ���������
	//  PB_CR1_bit.C11 = 1;

	//  PB_DDR_DDR3 = 0; //��������� ����� PB7 ������
	//  PB_CR1_bit.C17 = 0;
	//  PB_CR2_bit.C27 = 0;
	WatchDog_ON();
    
	/*if (LCDDISP)
	{
	init_LCD();
	}
	if (SEVENSEG)
	{*/
	init_SEVENSEG();
	//}
    
    FLASH_DUKR = 0xAE; //разрешение записи в EEPROM
	FLASH_DUKR = 0x56;
	//double curtimes;
	if (flag_res==0)
	{
		Emin        = min;
		Eupmin      = upmin;
		Ehour       = hour;
		Euphour     = uphour;
		Euphours    = uphours;
		Euphourt    = uphourt;
		Euphourdt   = uphourdt;
		Euphourst   = uphourst;
	}
	sec=0;
	upsec=0;
	min=Emin;
	upmin=Eupmin;
	hour=Ehour;
	uphour=Euphour;
	uphours=Euphours;
	uphourt=Euphourt;
	uphourdt=Euphourdt;
	uphourst=Euphourst;
    
	// ������������� ���� PA3
    PB_DDR_DDR3 = 0;        // input
    PB_CR1_C13 = 1;         // Pull-up
    PB_CR2_C23 = 0;         // ��������� ��������� ����� �� ���������� ����������
    
	Timer1_Init();
	asm("rim");

    while (timeinit > 0)
    {
        IWDG_KR = 0xAA;
        // Wait on init
        if (i == 1)
        {
            i = 0;
            sec++;
            timeinit -= 1;
            zero_SEVENSEG();
        }
    }

    // Clear leading Zeroes
    set_addr0();
    WRITE_SEVENSEG(10);
    WRITE_SEVENSEG(10);
    // Refresh normally
    refreshDisplay();

	while(1) {
        IWDG_KR=0xAA;
		if(PB_IDR_IDR3 == 0)  { // default 0
			// ������ ��, ��� ������� ������,
			// ����� �� PA3 ����������� ������� �������
			  if(i==1) //�������� ��������
			  {
				i=0;
				sec++;
			  }
			if (RES != 1) { // checkit // default 1
			  if (sec>=10) //проверка секунд
			  {
				sec=0;
				upsec++;
			  }
			  if (upsec>=6) //проверка десятков секунд
			  {
				upsec=0;
				min++;
				count++;
				if (count==save)
				{
				 SaveTime();
				 count=0;
				}
			  }
			  if (min>=10) //проверка минут
			  {
				min=0;
				upmin++;
			  }
			  if (upmin>=6) //проверка десятков минут
			  {
				upmin=0;
				hour++;
			  }
			  if (hour>=10) //проверка часов
			  {
				hour=0;
				uphour++;
			  }
			  if (uphour>=10) //проверка десятков часов
			  {
				uphour=0;
				uphours++;
			  }
			  if (uphours>=10) //проверка сотен часов
			  {
				uphours=0;
				uphourt++;
			  }
			  if (uphourt>=10) //проверка тысяч часов
			  {
				uphourt=0;
				uphourdt++;
			  }
			  if (uphourdt>=10) //проверка десятков тысяч часов
			  {
				uphourdt=0;
				uphourst++;
			  }
#if 0
			curtimes=(uphourst*100000+uphourdt*10000+uphourt*1000+uphours*100+uphour*10+hour)*60+upmin*10+min;// ������ �������� ���������� �����
			if (LCDDISP)
			{
			  WRITE_LCD(str1,0x20,0x00, 0x00);
			  WRITE_LCD(str1,0x20,0x10, 0x00);
			  WRITE_LCD(str1,0x20,0x20, 0x00);
			  WRITE_LCD(str1,0x20,0x30, 0x00);
			  WRITE_LCD(str1,0x20,0x40, 0x00);
			  WRITE_LCD(str1,0x40,0x50,0x3);
			  WRITE_LCD(str1,0x50,0x60,0x4);
			  WRITE_LCD(str1,0xA0,0x70,0x0);
			  WRITE_LCD(str1,0x20,0x80,0xD);
			  WRITE_LCD(str1,0x30,0x90,0x2);
			  WRITE_LCD(str1,0x30,0xA0,0x3);
			  WRITE_LCD(str1,0x30,0xB0,0x1);
			  WRITE_LCD(str1,0x20,0xC0, 0x00);
			  WRITE_LCD(str1,0x20,0xD0, 0x00);
			  WRITE_LCD(str1,0x20,0xE0, 0x00);

				if ((uphourdt<2)&&(uphourt<7)) { //������� ����� ������� �� ������ ������
				  // ������� "������ � �����"
				  WRITE_LCD(str2,0x30,0xF0,min);
				  WRITE_LCD(str2,0x30,0xE0, upmin);
				  WRITE_LCD(str2,0x30,0xD0, 0xA);
				  WRITE_LCD(str2,0x30,0xC0,hour);
				  WRITE_LCD(str2,0x30,0xB0, uphour);
				  if (curtimes>=6000)
					{WRITE_LCD(str2,0x30,0xA0, uphours);}
				  else {WRITE_LCD(str2,0x20,0xA0, 0x00);}
				  if (curtimes>=60000)
					{WRITE_LCD(str2,0x30,0x90,uphourt);}
				  else {WRITE_LCD(str2,0x20,0x90, 0x00);}
				  if (curtimes>=600000)
					{WRITE_LCD(str2,0x30,0x80, uphourdt);}
				  else {WRITE_LCD(str2,0x20,0x80, 0x00);}
				  if (curtimes>=6000000)
					{WRITE_LCD(str2,0x30,0x70, uphourst);}
				  else {WRITE_LCD(str2,0x20,0x70, 0x00);}
				  WRITE_LCD(str2,0x20,0x60, 0x00);
				  WRITE_LCD(str2,0x40,0x50, 0x1);
				  WRITE_LCD(str2,0x50,0x40, 0x4);
				  WRITE_LCD(str2,0x40,0x30, 0xF);
				  WRITE_LCD(str2,0xA0,0x20, 0x00);
				  WRITE_LCD(str2,0x40,0x10, 0x1);
				  WRITE_LCD(str2,0x50,0x00, 0x00);
				}
				else
				{
				  WRITE_LCD(str2,0x30,0xF0,min);
				  WRITE_LCD(str2,0x30,0xE0, upmin);
				  WRITE_LCD(str2,0x30,0xD0, 0xA);
				  WRITE_LCD(str2,0x30,0xC0,hour);
				  WRITE_LCD(str2,0x30,0xB0, uphour);
				  if (curtimes>=6000)
					{WRITE_LCD(str2,0x30,0xA0, uphours);}
				  else {WRITE_LCD(str2,0x20,0xA0, 0x00);}
				  if (curtimes>=60000)
					{WRITE_LCD(str2,0x30,0x90,uphourt);}
				  else {WRITE_LCD(str2,0x20,0x90, 0x00);}
				  if (curtimes>=600000)
					{WRITE_LCD(str2,0x30,0x80, uphourdt);}
				  else {WRITE_LCD(str2,0x20,0x80, 0x00);}
				  if (curtimes>=6000000)
					{WRITE_LCD(str2,0x30,0x70, uphourst);}
				  else {WRITE_LCD(str2,0x20,0x70, 0x00);}
				  WRITE_LCD(str2,0x20,0x60, 0x00);
				  WRITE_LCD(str2,0x40,0x50, 0x3);
				  WRITE_LCD(str2,0x50,0x40, 0x0);
				  WRITE_LCD(str2,0xA0,0x30, 0x9);
				  WRITE_LCD(str2,0x40,0x20, 0x3);
				  WRITE_LCD(str2,0x40,0x10, 0x5);
				  WRITE_LCD(str2,0x50,0x00, 0x00);
				}
			  }
#endif			  
			/*	if (SEVENSEG)
			  { */
				refreshDisplay();
			  //}
				}

		} // ���������� �������� ������ �� PA3 - �����
  } // Loop - End
}
