#include <mega8.h>
#include <delay.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>

int duration;
int fr;
long int freq=4000000;

#define CLK_FREQ freq    //Частота генератора
#define PR 1                //Предварительный делитель МК
#define NOTE_DURATION duration  //Единица длительности звучания ноты
#define SEMITONE 1.0594631  //Разница в частотах между соседними нотами одной октавы
#define START_NOTE 16.352   //Нота начального отсчёта (нота До 0-ой октавы)
#define OCTAVE_OFFSET 3     //Смещение по октавам

#define FOSC 4000000 // Clock Speed
#define BAUD 9600
#define MYUBRR (FOSC/16/BAUD-1)

eeprom int registor;
eeprom int track;

char mel1[]={"D2(1/4) P(1/8) E2(1/8) F2(1/4) P(1/8) D2(1/8) F2(1/8) F2(1/8) E2(1/8) D2(1/8) E2(1/4) A1(1/4) E2(1/4) P(1/8) F2(1/8) G2(1/4) P(1/8) E2(1/8) G2(1/8) G2(1/8) F2(1/8) E2(1/8) D2(1/4) P(1/4) A2(1/4) D3(1/4) C3(1/4)"};
char mel2[]={"D3(1/8) C3(1/8) Ais2(1/8) Ais2(1/8) A2(1/8) G2(1/8) A2(1/4) D2(1/4) P(1/8) Ais2(1/4) G2(1/8) A2(1/4) P(1/8) F2(1/8) G2(1/8) G2(1/8) F2(1/8) E2(1/8) D2(1/2)"};                                                                                                                                                                                                                                                                              
char mel3[]={"G2(1/16) F2(1/8) D2(1/16) E2(1/16) F2(1/8) D2(1/16) E2(1/16) F2(1/8) E2(1/16) D2(1/16) C2(1/8) G2(1/16) G2(1/16) F2(1/16) F2(1/16) D2(1/16) E2(1/16) F2(1/8) D2(1/16) E2(1/16) F2(1/8) E2(1/16) D2(1/16) C2(1/8)"};                                                                                                                                                                                                                                                                            

void Dig_init(int num) //Массив для отображения цыфр на семисегментном индикаторе - OK
{
 switch(num)
  {
  case 0:{PORTD=0b00111111; break;} //0
  case 1:{PORTD=0b00000110; break;} //1
  case 2:{PORTD=0b01011011; break;} //2  
  case 3:{PORTD=0b01001111; break;} //3
  case 4:{PORTD=0b01100110; break;} //4
  case 5:{PORTD=0b01101101; break;} //5
  case 6:{PORTD=0b01111101; break;} //6
  case 7:{PORTD=0b00000111; break;} //7
  case 8:{PORTD=0b01111111; break;} //8
  case 9:{PORTD=0b01101111; break;} //9  
  }
}

//Функция расчёта в октаве номера каждой из 12+1 нот 
unsigned char note_to_num (int note)
  {
    unsigned char nt=note & 0x07;
    unsigned char temp=0;

    switch(nt)
      {
        case 1: temp=1; break;
        case 2: temp=3; break;
        case 3: temp=5; break;
        case 4: temp=6; break;
        case 5: temp=8; break;
        case 6: temp=10; break;
        case 7: temp=12; break;
      }

    if ( (temp) && (note & 0x08) )
      temp++;

    return (temp);
  }
      
  
//Функция извлечения из ноты частоты
unsigned int note_to_freq (int note)
  {
    float temp=START_NOTE;
    unsigned int oct=(note & 0x00F0)>>4;  
    unsigned char i;

    if (oct>9) return (0);

    for (i=1; i<(12*oct + note_to_num(note)); i++)
      {
        temp*=SEMITONE;
      }

    return ((unsigned int)temp);      
  }
        
  
//Функция извлечения из ноты длительности
unsigned int note_to_duration (int note)
  {
    switch ( (note & 0x0F00) >>8 )
      {
        case  0: return (NOTE_DURATION*8);    //32/4
        case  1: return (NOTE_DURATION*4);    //16/4      
        case  2: return (NOTE_DURATION*2);    //8/4 
        case  3: return (NOTE_DURATION*1);    //4/4
        case  4: return (NOTE_DURATION/2);    //1/2
        case  5: return (NOTE_DURATION/4);    //1/4
        case  6: return (NOTE_DURATION/8);    //1/8
        case  7: return (NOTE_DURATION/16);   //1/16
        case  8: return (NOTE_DURATION/32);   //1/32
        case  9: return (NOTE_DURATION/64);   //1/64
        case 10: return (NOTE_DURATION/128);  //1/128
        default: return (0);
      }
  }
       
  
//Функция перевода псевдонима ноты в порядковое число 
unsigned char note_name(char c)
  {
    switch (c)
      {
        case 'P': return (0);
        case 'C': return (1);
        case 'D': return (2);
        case 'E': return (3);
        case 'F': return (4);
        case 'G': return (5);
        case 'A': return (6);
        case 'H': return (7);
        default : return (8);
      }
  }

//Воспроизведение ноты заданной частоты и длительности
void sound (int note)
  {
    if (!note_to_num(note))                    //Если пауза
      {
        delay_ms(note_to_duration(note));
        return;
      }
  
    OCR1A=CLK_FREQ/2/PR/note_to_freq(note)-1;

    TCCR1A=0x40;
    delay_ms(note_to_duration(note));
    TCCR1A=0x00;
  }


//Воспроизведение мелодии
int read_mel(char *mel)
  {
    int note=0;               //Собираемая нота
    char i, num, denum;

    for (i=0; i<strlen(mel); i++)               
      { 
        if (isalpha(mel[i]))            //Начало ноты
          {          
            note=note_name(mel[i]);     //Код ноты
            
            if (mel[i]-'P')           //Если именно нота, а не пауза
                {
                  i++;

                  if (isalpha(mel[i]))    //Проверяем на диез #
                    {
                      note+=1*8; 
                      i+=2;
                    }              
              
                    note+=(mel[i]-'0'+OCTAVE_OFFSET)*16; //Помещаем октаву на 7-4 разряды 
                    i+=2;                                //Переходим сразу на длительность              
                }
            
              else                                       //Если пауза
                {
                  i+=2;                                  //Сразу перешагиваем через диез и октаву
                } 
            
            num=(mel[i]-'0');
            i+=2;
            denum=(mel[i]-'0');
            i++;
                
            if (isdigit(mel[i]))         //Считываем знаменатель
              {
                denum=denum*10+(mel[i]-'0');
                i++;
                    
                if (isdigit(mel[i]))
                  denum=denum*10+(mel[i]-'0');
              } 

            if (num==1)              //Дробь не больше единицы
                {
                  switch(denum)        //Знаменатель
                    {
                      case   1: note+= 3*256; break;
                      case   2: note+= 4*256; break;
                      case   4: note+= 5*256; break;
                      case   8: note+= 6*256; break;
                      case  16: note+= 7*256; break;
                      case  32: note+= 8*256; break;
                      case  64: note+= 9*256; break;
                      case 128: note+=10*256; break;
                    }
                }
              else                       //Дробь больше единицы
                {
                  switch (num)
                    {
                      case 8: note+=0*256;
                      case 4: note+=1*256;
                      case 2: note+=2*256;
                    }
                }
            
            
            sound(note);   //Воспроизведение считанной ноты 
          }   
      } 
      
    return (1);  
  }
void main(void)
{

PORTB=0xFF;
DDRB=0x02;

PORTC=0xFF;
DDRC=0x00;

PORTD=0x00;
DDRD=0xFF;

ACSR=0x80;

TCCR1A=0x00;
TCCR1B=0x09;   //CTC + Делитель 1

//UCSRA=0x00;             //Одинарная скорость
UCSRA=0x02;   //Double USART transmission speed               
//UCSRB=0x08;             //Transmitter Enable
//UCSRB=0x10;   //Receiver Enable
//UCSRB=0x12;   //Transmitter and Receiver Enable
UCSRC=0x86;             //8-bit Character

UBRRH = (unsigned char)(MYUBRR>>8);   //Запись в старший байт
UBRRL = (unsigned char)(MYUBRR);      //Записть в младший байт
track=1;
freq=4000000;
//registor=0;
  
while (1)
{
Dig_init(registor);

 if(PINC.1==0) //Желтая кнопка, PC1, Выбор режимов мелодии
  {
  if(track>=5) {track=0;} 
  track=track+1;
  Dig_init(track);
  delay_ms(300);
  }
 if(PINC.2==0) //Серая кнопка, PC2, Выбор частоты
 {
 if(fr>=8) {fr=0;}
 fr=fr+1;
  switch(fr)
  {
  case 0:{freq=900000; Dig_init(fr);  delay_ms(200); break;} 
  case 1:{freq=1000000; Dig_init(fr);  delay_ms(200); break;} 
  case 2:{freq=2000000; Dig_init(fr);  delay_ms(200); break;} 
  case 3:{freq=3000000; Dig_init(fr);  delay_ms(200); break;}
  case 4:{freq=4000000; Dig_init(fr);  delay_ms(200); break;} 
  case 5:{freq=5000000; Dig_init(fr);  delay_ms(200); break;} 
  case 6:{freq=6000000; Dig_init(fr);  delay_ms(200); break;} 
  case 7:{freq=7000000; Dig_init(fr);  delay_ms(200); break;} 
  case 8:{freq=8000000; Dig_init(fr);  delay_ms(200); break;}
  }
 }  
 
 if(PINC.5==0) //Синяя кнопка СБРОС
 {
 registor=0;
 }

if(PINC.0==0) //Кнопка звонка, PC0
{  
    registor=registor+1;
	if(track==1) { duration=500; read_mel(mel1); read_mel(mel2);} else
    if(track==2) { duration=700; read_mel(mel3); } else
    if(track==3) 
    { duration=500; 
      read_mel(mel1); read_mel(mel2); 
      delay_ms(10);
      read_mel(mel1); read_mel(mel2);
    } else
    if(track==4) 
    {  
      duration=700; 
      read_mel(mel3);
      delay_ms(10);
      read_mel(mel3);  
    } else
    if(track==5) 
    {  
      duration=500; 
      read_mel(mel1); read_mel(mel2); 
      delay_ms(50);
      duration=700;
      read_mel(mel3);  
    }        
    delay_ms(100);
}
if(registor>=10) { registor=0; } else {}
}   
	};
