#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
#include "lcd.h"//knihovna pro ovládání LCD displeje
//#define lownible(v)  ((unsigned char) (((unsigned char) (v)) << 4))



                                ////////////////////////////////////////
                                //   deklarace potřebných proměnných  //
                                ////////////////////////////////////////
extern UINT8 timerLCD;
unsigned char i;
unsigned char tlacitko;           //dekadická hodnota stisknuté klávesy
unsigned char kod_klavesy;
//unsigned char hodnota_klavesy = 0;  
float FSW1;                         //slovo nastavující DDS syntezátor
float FSW2;                         
float cas1;
float cas2;                         //doba, po kterou se nebude generovat signál, nastavit na ni časovač
float del1;
float del2;
float del;
char doba;                          //doba trvání terapie
unsigned char kontrola=1;           //chybová proměnná
float frekvence;
unsigned char str1=0;               //střída impulzů
unsigned char str2=20;
byte adresa;
byte data;
unsigned char unst_chr [4];
byte opakovani;
int T_crit = 43 / 0.0625;              //kritická teplota tkáně, při překročení se resetuje systém
char chybove_pocitadlo=0;
float davka1 = 0;
float davka2 = 0;
int davka = 0;



                                 //////////////////////////////////////////////////
                                 // funkce CPU delay převzatá z processor expert //
                                 //////////////////////////////////////////////////

#pragma NO_ENTRY
#pragma NO_EXIT
#pragma MESSAGE DISABLE C5703
void Cpu_Delay100US(word us100)
{
  asm {
loop:
    pshh                               
    pshx                               
    ldhx #$007A                         
label0:
    aix #-1                            
    cphx #0                            
    bne label0                         
    pulx                               
    pulh                               
    nop                                
    nop                                
    nop                                
    aix #-1                            
    cphx #0
    bne loop                           
    rts                               
  }
}


                                 //////////////////////////////////////////////////
                                 // funkce převádějící čislo v BDC kódu na char  //
                                 //////////////////////////////////////////////////
 
 byte BCD_2_char (char doba){  
 char temp = 0;
 temp = doba>>4;
 temp = temp*10;
 temp += doba & 0x0f;
 return temp;       //funguje     
 }

                                 //////////////////////////////////////////////////
                                 // funkce převádějící char na číslo v BCD kódu  //
                                 //////////////////////////////////////////////////
 
 byte char_2_BCD (char doba){  
 char temp = 0;
 temp = doba/10;
 temp = temp<<4;
 temp += doba%10;
 return temp;    //funguje
 }
  
                       /////////////////////////////////////////////////////////
                       // Obsluha přerušení od interního čítače reálného času //
                       /////////////////////////////////////////////////////////


__interrupt void isrVrti(void) //pokud se kousne RTC resetuje se celý systém
{
  chybove_pocitadlo ++;
  if (chybove_pocitadlo==3)    //watchdog se nezresetuje až pokud se RTC 3x po sobě neozve
  while (1);                   //->reset systému, přetečením watchdog
  else 
  __RESET_WATCHDOG();          //pokud to ještě nebylo potřetí resetuje se warchdog
   SRTISC_RTIACK = 1;          //nulování interrupt flag
}


                       ///////////////////////////////////////////////////////////////
                       // Obsluha externího přerušení (vyvolané RTC každou vteřinu) //
                       ///////////////////////////////////////////////////////////////



__interrupt void isrVirq(void)   
{
    int RD_data;
    float teplota;
    char teplota_cela;
    char teplota_desetinna;
    char j;
    char sekundy;
    char minuty;
    float time;
    __RESET_WATCHDOG();
    chybove_pocitadlo = 0;      //reset chybového počítadla
    SRTISC_RTIS0 = 0;
    SRTISC_RTIS1 = 0;
    SRTISC_RTIS2 = 0;           //reset a zastavení interního čítače reálného času     
    
    
    while(1)  {                 // načtení teploty z LM92                      
    IIC1C_MST = 1;              // MASTER mód - generování START
    IIC1C_TX = 1;               // TRANSMIT mód (odesílám adresu)
    IIC1D  =0b10010001;         // zapsání adresy LM32 do datového registru + osmý vyslaný bit je R/W - nevím, jestli se to dělá automaticky - otestovat reálně
    while (!IIC1S_TCF);         // počkání na odeslání adresy
    for (j=5;j>0;j--);          // zpoždění aby stačíl SLAVE (respektive IIC je pomalejší, než procesor) poslat ACK nebo NACK
      if (!IIC1S_RXAK){         // pokud byl přijat ACK od SLAVE
        IIC1C_TX = 0;           // RECIEVE mód
        IIC1C_TXAK  = 0;     //povolení generování ACK
        RD_data = IIC1D;     //dummy read
        while (!IIC1S_TCF);
        RD_data = IIC1D;    //platná data
        RD_data = RD_data<<8;
        while (!IIC1S_TCF);
        IIC1C_TXAK  = 1;    //zakázání ACK
        IIC1C_MST = 0;      //generování stop
        RD_data += IIC1D;    //platná data
        __RESET_WATCHDOG();
        break;
      }
      __RESET_WATCHDOG();
      for (j=5;j>0;j--);
    } 
      
      RD_data = RD_data>>3;
      teplota = RD_data*0.0625; // zkontolováno v pořádku
      
      while(1)  {               // nasatavení pointeru RTC na vteřinové počítadlo                     
    IIC1C_MST = 1;              // MASTER mód - generování START
    IIC1C_TX = 1;               // TRANSMIT mód 
    IIC1D  =0b10100010;         // zapsání adresy RTC do datového registru + osmý vyslaný bit je R/W
    while (!IIC1S_TCF);         // počkání na odeslání adresy
    for (j=5;j>0;j--);          // zpoždění aby stačíl SLAVE (respektive IIC je pomalejší, než procesor) poslat ACK nebo NACK
      if (!IIC1S_RXAK){         // pokud byl přijat ACK od SLAVE
        IIC1D = 0x02;           // nastavení pointeru na 0x02 -> vteřiny
          while (!IIC1S_TCF);       // počkání na odeslání dat
          for (j=5;j>0;j--);        // zpoždění aby stačil SLAVE (respektive IIC je pomalejší, než procesor) poslat ACK nebo NACK
            if (!IIC1S_RXAK){       // pokud byl přijat ACK od SLAVE
              IIC1C_MST = 0;        // generování STOP signálu
              for (j=5;j>0;j--);
              __RESET_WATCHDOG();
              break;  
            }
      }
      __RESET_WATCHDOG(); 
      for (j=5;j>0;j--); 
    }
 
     while(1)  {                // načtení minut a vteřin z RTC                      
    IIC1C_MST = 1;              // MASTER mód - generování START
    IIC1C_TX = 1;               // TRANSMIT mód 
    IIC1D  =0b10100011;         // zapsání adresy RTC do datového registru + osmý vyslaný bit je R/W
    while (!IIC1S_TCF);         // počkání na odeslání adresy
    for (j=5;j>0;j--);          // zpoždění aby stačíl SLAVE (respektive IIC je pomalejší, než procesor) poslat ACK nebo NACK
      if (!IIC1S_RXAK){         // pokud byl přijat ACK od SLAVE
        IIC1C_TX = 0;           // RECIEVE mód 
        IIC1C_TXAK  = 0;        //povolení generování ACK
        sekundy = IIC1D;        //dummy read
        while (!IIC1S_TCF);
        sekundy = IIC1D;        //platná data -> sekundy se formátu BCD
        while (!IIC1S_TCF);
        IIC1C_TXAK  = 1;        //zakázání ACK 
        IIC1C_MST = 0;
        minuty = IIC1D;        //platná data -> minuty ve formátu BCD
        for (j=5;j>0;j--);
        __RESET_WATCHDOG();
        break;
      }
      __RESET_WATCHDOG();
      for (j=5;j>0;j--);
    } 
    minuty = BCD_2_char(minuty);
    LCDCursor(0x4d);
    LCDPrint(&minuty,2);
    sekundy = BCD_2_char(sekundy);
    LCDCursor(0x4f);
    LCDPrint(&sekundy,2);
    time =(float)minuty/60;
    time +=(float)sekundy/3600;        //převod uplynulého času na hodiny
    teplota_cela = (char)teplota;      //vyselektování celé části z float hodnoty
    teplota = teplota - teplota_cela;  //v proměnné teplota je desetinná část
    teplota = teplota * 100;
    teplota_desetinna = (char)teplota; //ořezání na dvě desetinná čísla -> dvě desetinná čísla jsou zapsána jako celá
    LCDCursor(0x8a);                   
    LCDPrint(&teplota_cela,2);
    LCDCursor(0x8d);
    LCDPrint(&teplota_desetinna,2); 
    davka =(int)davka1*time;
    LCDCursor(0xca);
    LCDPrint(&davka,4);
    davka =(int)davka2*time;
    LCDCursor(0xcf);
    LCDPrint(&davka,4);   
    
  
  __RESET_WATCHDOG();
  IRQSC_IRQACK = 1; //potvrzení a smazání interrupt flagu
}

                       ////////////////////////////////////////////////////////////////
                       // unie, která zajišťuje bitové překopírování z float do long //
                       ////////////////////////////////////////////////////////////////


typedef union float_2_long {             //definice struktury UNION - slouží pro překopírování bitů z float do unsigned long (kdybych to udělal normálně překopíruje se zaokrouhlená hodnota)
    float        fp;                     //hodnota uložená v FP formátu
    unsigned long uint;                  //32 bitové slovo na stejném místě paměti ve formátu unsigned long
}float_2_long;


                       /////////////////////////////////////////////////////////////////////
                       // funkce provádějící rozdělení proměnné float na 4 proměnné char  //
                       /////////////////////////////////////////////////////////////////////

void rozdel_float(float fp){      
  float_2_long fp32;               //přiřazení jména proměnným v unii 
  fp32.fp=fp;                      //vložení vstupní hodnoty do unie
  unst_chr [0]= fp32.uint;         //nejnižších 8 bitů
  unst_chr [1]= (fp32.uint)>>8;
  unst_chr [2]= (fp32.uint)>>16;
  unst_chr [3]= (fp32.uint)>>24;   //rozdělení unsigned long na 4x unsigned char - kopíruje se pouze nejnižších 8b -> pokaždé posunout o 8 bitů doprava
  }

                           ////////////////////////////////////////////////////////////
                           // funkce realizující zpoždění o zadaný počet milisekund  //
                           ////////////////////////////////////////////////////////////

void zpozdeni_2s (void) 
{
 __RESET_WATCHDOG();
 for (i=0;i<80;i++){ 
 __RESET_WATCHDOG();
 Cpu_Delay100US(250);
 __RESET_WATCHDOG();
 }
} 




                             /////////////////////////////////////////////////////
                             //  funkce softwarově ošetřující zákmity tlačítek  //
                             /////////////////////////////////////////////////////


unsigned char antizakmit(void) 
{
      unsigned char dolni_nibl1;              // deklarace proměnné horni_nibl1
      unsigned char dolni_nibl2;              // deklarace proměnné horni_nibl2
      dolni_nibl1 = PTBD & 0x0f;          // do proměnné horni nibl_1 se zapíše hodnota na bitech PTB4-PTB7, která je na portu bezprostředně pó detekci stisknutí tlačítka
      Cpu_Delay100US(100);                     // volání funkce zpoždění - pro překonání zákmitů tlačítka a vyfiltrování falešné detekce stisku
      __RESET_WATCHDOG(); 
      dolni_nibl2 = PTBD & 0x0f;          // zápis hodnoty horního niblu z portuB do proměnné horni_nibl2 po uplynutí zpozdeni
        if (dolni_nibl1 == dolni_nibl2){      // jestliže je stisknuto tlačítko ješte po zpozdeni od objevení se nuly - překonání zákmitů a vyfitrování falešné první detekce
            kod_klavesy=dolni_nibl1;
            return 1;}                        // pokud je tlačítko pravdu stisknuto, funkce vrátí hodnotu 1 
        else return 0;                        // pokud se jedná o falešnou detekci, funkce vrátí hornotu 0
}



                            ///////////////////////////////////////////////////////////
                            //   funkce provádějící skenování maticové klvásnice     //
                            //  a navracející numerickou hodnotu stisknuté klávesy   //
                            ///////////////////////////////////////////////////////////


 unsigned char sken (void) 
{
    while (1){                    //zacyklení - klávesnice se cyklicky skenuje ve smyčce, která končí po stisku klávesy
      
    PTDD =0x03;                   //na dolní nibl portuB se pošle posloupnost 110 (horní nibl je definován, jako vstup -> zapsání nuly BY NEMĚLO mít vliv)
      if (PTBD != 0x0f){          //pokud hodnota na portuB není rovna 11110110 bylo stisknuto nějaké tlačítko (369#) v příslušném (posledním) sloupci
            if (antizakmit()){    //pokud funkce vrátí 1 - vykoná se rozpoznání stisknuté klávesy, pokud nula - falešná detekce a skenuje se dál bez rozpoznání klávesy a ukončení podprogramu scan
              switch(kod_klavesy){
                case 0x07: return 0x0a;          //rozpoznání, která klávesa byla stisknuta a zapsání její hodnoty do proměnné, křížek nahrazuje a 
                case 0x0b: return 0x09;          //
                case 0x0d: return 0x06;          //
                case 0x0e: return 0x03;          //
                default:kontrola=1;              //pokud je stisknuto více kláves najednou - nastaví se chybová proměnná 
                        LCDClear;                //vymazání displeje
                        LCDCursor(0x00);
                        LCDPrint("Stisknete pouze",15);
                        LCDCursor(0x40);
                        LCDPrint("jednu klavesu",13);   //zápis chyby na displej
                        zpozdeni_2s();          //zpoždění o 2s
                        return;                         //výstup z funkce
              }
            }
          }
    PTDD =0x05;
    if (PTBD != 0x0f){
          if (antizakmit()){
              switch(kod_klavesy){
                case 0x07: return 0x00;          //
                case 0x0b: return 0x08;          //
                case 0x0d: return 0x05;          //
                case 0x0e: return 0x02;          // křížek
                default:kontrola=1;              //pokud je stisknuto více kláves najednou - nastaví se chybová proměnná 
                        LCDClear;                //vymazání displeje
                        LCDCursor(0x00);
                        LCDPrint("Stisknete pouze",15);
                        LCDCursor(0x40);
                        LCDPrint("jednu klavesu",13);   //zápis chyby na displej
                        zpozdeni_2s();                 //zpoždění o 2s
                        return;                         //výstup z funkce
              }
            }
          }
    PTDD =0x06;
    if (PTBD != 0x0f){
          if (antizakmit()){ 
              switch(kod_klavesy){ 
                case 0x07: return 0x0b;          //  hvězdička
                case 0x0b: return 0x07;          //
                case 0x0d: return 0x04;          //
                case 0x0e: return 0x01;          //
                default:kontrola=1;              //pokud je stisknuto více kláves najednou - nastaví se chybová proměnná 
                        LCDClear;                //vymazání displeje
                        LCDCursor(0x00);
                        LCDPrint("Stisknete pouze",15);
                        LCDCursor(0x40);
                        LCDPrint("jednu klavesu",13);   //zápis chyby na displej
                        zpozdeni_2s();                 //zpoždění o 2s
                        return;                         //výstup z funkce
              }     
            }
          }
   __RESET_WATCHDOG();  
   }                                                 
}


                                 //////////////////////////////////////////////////
                                 // funkce provádějící inicializaci I2C sběrnice //
                                 //////////////////////////////////////////////////


void I2C_init (void)
{
IIC1F_MULT = 0b00;  //nastavení MULT na 1
IIC1F_ICR =  0x0b;  //nastavení clock rate -> baud rate = 250 kbps a SDA hold time = 0,9 us
IIC1C_IICEN = 1;    //povolení IIC
IIC1C_MST = 0;      //prozatím slave mode, mění se při generování START
}



                                 //////////////////////////////////////////////////////
                                 // funkce zapisující 16b hodnotu do registru v LM32 //
                                 //////////////////////////////////////////////////////
                                 
                                 
                                 
void I2C_write_LM92 (byte addr_reg, int wr_data) { //  vstup je adresa registru a datová hodnota 
      char j;
      while(1)  {                                       
        IIC1C_MST = 1;              // MASTER mód - generování START
        IIC1C_TX = 1;               // TRANSMIT mód 
        IIC1D  =0b10010000;         // zapsání adresy LM32 do datového registru + osmý vyslaný bit je R/W - nevím, jestli se to dělá automaticky - otestovat reálně
        while (!IIC1S_TCF);         // počkání na odeslání adresy
        for (j=5;j>0;j--);          // zpoždění aby stačil SLAVE (respektive IIC je pomalejší, než procesor) poslat ACK nebo NACK
          if (!IIC1S_RXAK){         // pokud byl přijat ACK od SLAVE
          IIC1D = addr_reg;         // nastavení pointeru na adresu požadovaného registru  
          while (!IIC1S_TCF);       // počkání na odeslání dat
          for (j=5;j>0;j--);        // zpoždění aby stačil SLAVE (respektive IIC je pomalejší, než procesor) poslat ACK nebo NACK
            if (!IIC1S_RXAK){       // pokud byl přijat ACK od SLAVE
            IIC1D = wr_data>>5;     //první se posílá nejvýznamnější Byte (do IIC1D se zapíše nižší Byte -> prakticky jako převod INT na CHAR), musí se počítat s tím, že registr je 13B a 3 nejnižší nejsou definovány -> posun o 5 vpravo bit 12 se posne na bit 7 a bit 5 na 0
            while (!IIC1S_TCF);
              for (j=5;j>0;j--);
                if (!IIC1S_RXAK){  
                IIC1D = wr_data<<3; //zbylých 5 bitů se posune o tři pozice doleva
                while (!IIC1S_TCF);
                for (j=5;j>0;j--); 
                  if (!IIC1S_RXAK){
                  IIC1C_MST = 0;    // generování STOP signálu
                  for (j=5;j>0;j--);
                  __RESET_WATCHDOG();
                  break;            // včechno proběhlo v pořádku ->ukončení cyklu vysílání
                  }
                }    
              }
            }
        __RESET_WATCHDOG();         
        for (j=5;j>0;j--);        //SLAVE generoval NACK -> čeká se na generování STOP a cyklus se bude vykonávat znovu
      } 
} 




                                 //////////////////////////////////////////////////
                                 // funkce vysílající 32bitovou hodnotu do SLAVE //
                                 //////////////////////////////////////////////////

    void I2C_write_32bit (byte addr, float wr_data) {    //Funkce, která zejištuje odeslání 32b slova do zařízení SLAVE
    char j;
    rozdel_float(wr_data);
      while(1){
      IIC1C_MST = 1;            // MASTER mód - generování START
      IIC1C_TX = 1;             // TRANSMIT mód 
      IIC1D  = (addr)<<1;       // zapsání adresy slave do datového registru + osmý vyslaný bit je R/W - nevím, jestli se to dělá automaticky - otestovat reálně
      while (!IIC1S_TCF);       // počkání na odeslání adresy
      for (j=5;j>0;j--);        // zpoždění aby stačíl SLAVE (respektive IIC je pomalejší, než procesor) poslat ACK nebo NACK
        if (!IIC1S_RXAK){       // pokud byl přijat ACK od SLAVE
        IIC1D = unst_chr[3];    //nejvyšších 8 bitů
        while (!IIC1S_TCF);
        for (j=5;j>0;j--);
          if (!IIC1S_RXAK){ 
          IIC1D = unst_chr[2];
          while (!IIC1S_TCF);
          for (j=5;j>0;j--);
            if (!IIC1S_RXAK){ 
            IIC1D = unst_chr[1];
            while (!IIC1S_TCF);
            for (j=5;j>0;j--);
              if (!IIC1S_RXAK){ 
              IIC1D = unst_chr[0];   //nejnižších 8 bitů
              while (!IIC1S_TCF);
              for (j=5;j>0;j--);
                if (!IIC1S_RXAK){   // pokud byl přijat ACK od SLAVE
                IIC1C_MST = 0;      // generování STOP signálu
                 for (j=5;j>0;j--);
                 __RESET_WATCHDOG();
                 break;
                }
              }
            }
          }
        }
        __RESET_WATCHDOG(); 
       for (j=5;j>0;j--); 
      }
    }
    
                                  //////////////////////////////////////////////////
                                 //   funkce nastavující jeden registr v RTC     //
                                 //////////////////////////////////////////////////
                                 
                                 
void I2C_write_RTC (byte addr_reg,byte wr_data) {
    char j;
      while(1)  {  
        IIC1C_MST = 1;            // MASTER mód - generování START
        IIC1C_TX = 1;             // TRANSMIT mód 
        IIC1D  = (0b10100010);    // zapsání adresy slave do datového registru + osmý vyslaný bit je R/W - nevím, jestli se to dělá automaticky - otestovat reálně
        while (!IIC1S_TCF);       // počkání na odeslání adresy
        for (j=5;j>0;j--);        // zpoždění aby stačíl SLAVE (respektive IIC je pomalejší, než procesor) poslat ACK nebo NACK
          if (!IIC1S_RXAK){
          IIC1D = addr_reg;
          while (!IIC1S_TCF);
          for (j=5;j>0;j--);
            if (!IIC1S_RXAK){ 
            IIC1D = wr_data;
            while (!IIC1S_TCF);
            for (j=5;j>0;j--);
              if (!IIC1S_RXAK){       // pokud byl přijat ACK od SLAVE
                IIC1C_MST = 0;      // generování STOP signálu
                for (j=5;j>0;j--); //aby se stihl vagenerovat STOP signál např před voláním další funkce ->další START
                __RESET_WATCHDOG();
                break;
              }
            }
          } 
      __RESET_WATCHDOG(); 
      for (j=5;j>0;j--);
      }                           
}    
    
    
    
    
                                 //////////////////////////////////////////////////
                                 //   funkce inicializující obvod reálného času  //
                                 //////////////////////////////////////////////////
                                 
 void RTC_init(byte time_bcd){   //zatím void, pak dodělat vstupy - čas od 1 do 59 minut, budu používat alarmové registry 
  while(1){
      char j=0;
      IIC1C_MST = 1;            // MASTER mód - generování START
      IIC1C_TX = 1;             // TRANSMIT mód 
      IIC1D  = (0b10100010);    // zapsání adresy slave do datového registru + osmý vyslaný bit je R/W - nevím, jestli se to dělá automaticky - otestovat reálně
      while (!IIC1S_TCF);       // počkání na odeslání adresy
      for (j=5;j>0;j--);        // zpoždění aby stačil SLAVE poslat ACK nebo NACK
        if (!IIC1S_RXAK){
        IIC1D  = (0b00000000);  // zapsání adresy prvního registru v RTC control/status register 1
        while (!IIC1S_TCF);     // počkání na odeslání adresy
        for (j=5;j>0;j--);      // zpoždění aby stačil SLAVE poslat ACK nebo NACK
          if (!IIC1S_RXAK){  
          IIC1D = 0b00100000;   //vyslání dat - STOP bit - zastavení interního čítače - asi bude resetovat adresní pointer teď je ale na nule - vyzkoušet v praxi
          while (!IIC1S_TCF);
          for (j=5;j>0;j--);
            if (!IIC1S_RXAK){ 
            IIC1D = 0b0000010;  //zapisovat data do dalšího registru ->adresa se inkrementuje automaticky; TI/TP = 0-> povolení přerušení od alarmu AIE =1 -> povolení alarmu          
            while (!IIC1S_TCF);
            for (j=5;j>0;j--);
              if (!IIC1S_RXAK){
              IIC1C_MST = 0;    // generování STOP signálu
              for (j=5;j>0;j--);
              __RESET_WATCHDOG();
              break;  
              }
            }
          }
        }
        __RESET_WATCHDOG(); 
       for (j=5;j>0;j--);
  }                             //jsou nastaveny registry control/status 1 a control/status2
 
                                //další registry jsou počítací - u těch se nenastavuje nic, bude se z nich číst 
 
 I2C_write_RTC(0x09,time_bcd);  //nastavení minutového alarm registru na dobu terapie - ještě zařídit povolení -> sedmý bit a převod do bcd kód
 I2C_write_RTC(0x0d,0b10000011);//nastavení CLKOUT na 1Hz
  }
  
  
    
 
 
                                        //////////////////////////////////////////
                                        // funkce inicializující teplotní čidlo //
                                        //////////////////////////////////////////

  void LM92_init (int T_crit){   // vstup je kritická teplota
  int T_high = T_crit-(20/0.0625);        // teplota pro horní komparátor, k ničemu to není, jenom nesmí být vyšší, než T_crit a je defaultně na 64°C, proto T_crit -20
                                 // T_hyst může je defaultně na 2°C -> může zůstat
                                 // T_low = 10°C  -> (defaultně) může zůstat
    char RD_data;               
    char j;
    int teplota;                               
    while(1)  {                                       
    IIC1C_MST=1;              // MASTER mód - generování START
    IIC1C_TX=1;               // TRANSMIT mód 
    IIC1D  =0b10010000;         // zapsání adresy LM32 do datového registru + osmý vyslaný bit je R/W - nevím, jestli se to dělá automaticky - otestovat reálně
    while (!IIC1S_TCF);         // počkání na odeslání adresy
    for (j=5;j>0;j--);          // zpoždění aby stačíl SLAVE (respektive IIC je pomalejší, než procesor) poslat ACK nebo NACK
      if (!IIC1S_RXAK){         // pokud byl přijat ACK od SLAVE
        IIC1D = 0x01;           // nastavení pointeru na 0x01 - konfigurační registr 
          while (!IIC1S_TCF);       // počkání na odeslání dat
          for (j=5;j>0;j--);        // zpoždění aby stačil SLAVE (respektive IIC je pomalejší, než procesor) poslat ACK nebo NACK
            if (!IIC1S_RXAK){       // pokud byl přijat ACK od SLAVE
            IIC1D = 0x10;           // nastavení konfiguračního registru -> povolení fault queue 
            while (!IIC1S_TCF);     // počkání na odeslání dat
            for (j=5;j>0;j--);      // zpoždění aby stačil SLAVE (respektive IIC je pomalejší, než procesor) poslat ACK nebo NACK
              if (!IIC1S_RXAK){     // pokud byl přijat ACK od SLAVE
              IIC1C_MST = 0;        // generování STOP signálu
              for (j=5;j>0;j--);
              __RESET_WATCHDOG();
              break;  
              }
            }
      }
      __RESET_WATCHDOG(); 
      for (j=5;j>0;j--);
    }
   I2C_write_LM92 (0x05,T_high);   //maximum pro okno  -> jenom protože musí být menší, než T_crit
   I2C_write_LM92 (0x03,T_crit);   //maximální teplota, po překročení se bude generovat reset
   I2C_write_LM92 (0x02,1/0.0625); //hystereze, po překročení T_crit musí teplota klesnout pod T_crit - T_hyst aby se výstup překlopil zpátky do jedničky
   
  
                                //nastavení pointeru na teplotní registr -> pokud se to udělá teď, nebudu to muset dělat pokaždé ve funkci načítání teploty
    while(1)  {                 //pošle se jenom slave adresa LM32 a nastaví se pointer aby ukazoval na adresu teplotního registru 0x00                      
    IIC1C_MST = 1;              // MASTER mód - generování START
    IIC1C_TX = 1;               // TRANSMIT mód 
    IIC1D  =0b10010000;         // zapsání adresy LM32 do datového registru + osmý vyslaný bit je R/W - nevím, jestli se to dělá automaticky - otestovat reálně
    while (!IIC1S_TCF);         // počkání na odeslání adresy
    for (j=5;j>0;j--);          // zpoždění aby stačíl SLAVE (respektive IIC je pomalejší, než procesor) poslat ACK nebo NACK
      if (!IIC1S_RXAK){         // pokud byl přijat ACK od SLAVE
        IIC1D = 0x00;           // nastavení pointeru na 0x00 - teplotní registr -> kvůli tomu to dělám tady -> nemusím to dělat v každé obsluze
          while (!IIC1S_TCF);       // počkání na odeslání dat
          for (j=5;j>0;j--);        // zpoždění aby stačil SLAVE (respektive IIC je pomalejší, než procesor) poslat ACK nebo NACK
            if (!IIC1S_RXAK){       // pokud byl přijat ACK od SLAVE
              IIC1C_MST = 0;        // generování STOP signálu
              for (j=5;j>0;j--);
              __RESET_WATCHDOG();
              break;  
            } 
          }
      __RESET_WATCHDOG(); 
      for (j=5;j>0;j--);
     
    }
  }
        ////////////////////////////////////////////////////////////////////////////////////////////////////////
        // funkce provádějící počáteční inicializaci v souboru MCUinit.c - generovaná pomocí Processor Expert //
        ////////////////////////////////////////////////////////////////////////////////////////////////////////



void MCU_init(void); 


                                 ////////////////////////////////////////////
                                 //   nekonečná smyčka hlavního programu   //
                                 ////////////////////////////////////////////


void main(void) {
  MCU_init();LCDInit();
  DisableInterrupts;
  PTBDD = 0xf0;
  PTDDD = 0xff;
                          ///////////////////////////////////////////////////////////
                          //     provedení resetu generujících mikrokontrolérů     //
                          // (při strartu zbytečné,prvádí se pro zastavení terapie)//
                          ///////////////////////////////////////////////////////////
                          
                          
                          
                                                 
  PTAD_PTAD0 = 0;            //zapsání nul na piny, které jsou připojené k pinům /RESET generujících MCU (/RESET je aktivní v nule)  pozn.po resetu jsou piny definovány jako vstupní, ve stavu vysoké impedance s vypnutým vnitřním pullup rezistorem 
  PTAD_PTAD1 = 0;            //reset obou generujících procesorů - při strartu zbytečné - pro zastavení terapie
  for (i=0;i<5;i++);         //zpoždění - min 34 cyklů - provádí reset a po dalších 38 testuje jestli je ještě reset v nízké úrovni - pozná, že reset byl extermí
  PTAD_PTAD0 = 1;                                        
  PTAD_PTAD1 = 1;            //vypnutí resetu
  
  for(opakovani=1;opakovani<=2;opakovani++) {   //zadáván parametrů se bude rovádět 2x - jednou s parametrem opakovani=1 a pak opakovani = 2
    

  kontrola=1;
  while(kontrola){ 
    kontrola=0;
    LCDClear;                             //vymzání displeje
    LCDCursor(0x00);                      //posun kuzroru na začátek displeje
    LCDPrint("Vyberte program",15);       //zápis na LCD displej
    LCDCursor(0x40);
    if (opakovani == 1) 
    LCDPrint("pro solenoidalni",16);
    if (opakovani == 2)
    LCDPrint("pro plochy",16);
    LCDCursor(0x80);
    LCDPrint("aplikator a stisknte",20);
    LCDCursor(0xc0);                      //posun na čtvrtý řádek
    LCDPrint("libovolnou klavesu",18);

    sken ();                              //začne se skenovat klávesnice - zacyklení do doby, než bude stisknuto tlačítko. Hodnota stisknutého tlačítka je zahozena 
  }
  
  
   kontrola=1;
   while(kontrola){                     //cyklus se bude vykonávat pokud kontrola bude jedničková (jednička se nastaví po chybě obsluhy) - vygeneruje se hláška a musí se celý cyklus zápisu opakovat
      kontrola = 0;                     //kontrola je nulová - při správném stisku tlačítka (1 až 4) a pokud obsluha nestiskne 2 tlačítka najednou se cyklus přeruší (vykoná se 1x)
      LCDClear;                         
      LCDCursor(0x00);                 
      LCDPrint("1 - program 1",13);     //zápis výzvy ke stisku tlačítka na LCD displej
      LCDCursor(0x40);
      LCDPrint("2 - program 2",13);
      LCDCursor(0x80);                  //nejspíš posuna na třetí řádek - není čas to hledat - zjistím, až budu mít displej
      LCDPrint("3 - program 3",13);
      LCDCursor(0xc0);
      LCDPrint("4 - individualni",16);
  
  
      tlacitko = sken();                //podprogram provádějíci skenování maticové klávesnice a vracející dekadickou hodnotu stisknuté klávesy
  
        switch(tlacitko){               //podle stiskutého tlačítka se nastaví parametry jednotlivých programů
          case 0x01:if (opakovani == 1){
                    cas1=0.0095;
                    FSW1=1310.72;
                    del1=10;
                    doba=15;
                    frekvence = 100;
                    davka1=frekvence*(del1/0.01)*(del1/1000);}//předpřipravení terapeutické dávky podle vzorce -> bude se každou vteřinu aktualizovat s časem
                    if (opakovani == 2) { 
                    cas2=0.0095;
                    FSW2=1310.72;
                    del2=10;
                    doba=15;
                    frekvence = 100;
                    davka2=frekvence*(del2/0.01)*(del2/1000);}//první program s nejkratší délkou impulzu
                    
          break;      
          case 0x02:if (opakovani == 1){
                    cas1=0.05;
                    FSW1=0.6898;
                    del1=10;
                    doba=30;
                    frekvence = 1;
                    davka1=frekvence*(del1/0.01)*(del1/1000);}
                    if (opakovani == 2){
                    cas2=0.05;
                    FSW2=0.6898;
                    del2=10;
                    doba=30;
                    frekvence = 1;
                    davka2=frekvence*(del2/0.01)*(del2/1000);}//druhý program s nejdelší délkou impulzu
              
          break;     
          case 0x03:if (opakovani == 1){
                    cas1=0.01;             //poloviční frekvence i sřída z rozsahu
                    FSW1=655.36;
                    del1=10;
                    doba=20;
                    frekvence = 50;
                    davka1=frekvence*(del1/0.01)*(del1/1000);}
                    if (opakovani == 2){
                    cas2=0.01;
                    FSW2=655.36;
                    del2=10;
                    doba=20;
                    frekvence = 50;
                    davka2=frekvence*(del2/0.01)*(del2/1000);}
          break;                       //individuální nastavení 
          case 0x04:              
                           
                               kontrola=1;
                                while(kontrola){
                                  kontrola=0;
                                  LCDClear;
                                  LCDCursor(0x00);
                                  LCDPrint("Zadejte frekvenci",17);
                                  LCDCursor(0x40);
                                  LCDPrint("impulzu:___ Hz",14);
                                  LCDCursor(0x48);
                                      tlacitko=sken();                  //načtení hodnoty stisknutého tlačítka
                                      frekvence+=100*tlacitko;          //první stisknuté tlačítko má váhu stovky (násobené 100 a přičtení od proměnné frekvence)
                                      LCDPrint(&tlacitko,1);            //zápis stisknutého tlačítka na řád sto na displeji
                                      tlacitko=sken();                  
                                      frekvence+=10*tlacitko;           //desítky
                                      LCDPrint(&tlacitko,1);
                                      tlacitko=sken();
                                      frekvence+=tlacitko;              //jednotky
                                      LCDPrint(&tlacitko,1);
                                      __RESET_WATCHDOG();
                                        if (frekvence>100 | frekvence<1){      //generovaná frekvence musí být z rozsahu 1-100Hz. Pokud nebude, na LCD se zapše chyba, vynuluje se proměnná frekvence a znovu začne zadávání frekvence
                                             kontrola=1;
                                             frekvence=0;
                                             LCDClear;
                                             LCDCursor(0x00);
                                             LCDPrint("Maximalni frekvence",19);
                                             LCDCursor(0x40);
                                             LCDPrint("je 100 Hz",9);
                                             __RESET_WATCHDOG();
                                             zpozdeni_2s();
                                            }         
                                            
                                }
                    
                                kontrola=1;       //algoritmus podobný zadávání frekvence - kontroluje se pouze první číslice střídy - druhá je konstanta 20
                                while(kontrola){
                                  kontrola=0;
                                  LCDClear;
                                  LCDCursor(0x00);
                                  LCDPrint("Zadejte stridu",14);
                                  LCDCursor(0x40);
                                  LCDPrint("impulzu:__:20",13);
                                  LCDCursor(0x48);
                                      tlacitko=sken();
                                      str1+=10*tlacitko;
                                      LCDPrint(&tlacitko,1);
                                      tlacitko=sken();
                                      str1+=tlacitko;
                                      LCDPrint(&tlacitko,1);
                                      __RESET_WATCHDOG();
                                        if (str1>19 | str1<1){
                                             kontrola=1;
                                             str1=0;
                                             LCDClear;
                                             LCDCursor(0x00);
                                             LCDPrint("Strida musi byt",15);
                                             LCDCursor(0x40);
                                             LCDPrint("v rozsahu",9);
                                             LCDCursor(0x80);
                                             LCDPrint("od 01:20 do 19:20",15);
                                             __RESET_WATCHDOG();
                                             zpozdeni_2s();
                                        }
                                }
                                
                                
                                kontrola=1;       
                                while(kontrola){
                                  kontrola=0;
                                  LCDClear;
                                  LCDCursor(0x00);
                                  LCDPrint("Zadejte indukci",15);
                                  LCDCursor(0x40);
                                  LCDPrint("mag. pole:__mT",14);
                                  LCDCursor(0x4a);
                                      tlacitko=sken();
                                      del+=10*tlacitko;
                                      LCDPrint(&tlacitko,1);
                                      tlacitko=sken();
                                      del+=tlacitko;
                                      LCDPrint(&tlacitko,1);
                                      __RESET_WATCHDOG();
                                        if (del>20 | del<1){
                                             kontrola=1;
                                             del=0;
                                             LCDClear;
                                             LCDCursor(0x00);
                                             LCDPrint("Indukce musi byt",16);
                                             LCDCursor(0x40);
                                             LCDPrint("v rozsahu",9);
                                             LCDCursor(0x80);
                                             LCDPrint("od 1 do 20 mT",13);
                                             __RESET_WATCHDOG();
                                             zpozdeni_2s();
                                        }
                                }  
                    
                   
//následuje zpracování individuálně zadaných parametrů - výpočet veličin, které se budou posílat generujícím mikrokontrolerům

                                             if(opakovani==1) {
                                              davka1=frekvence*(del/0.01)*(del/1000);//každou vteřinu vynásobit zvyšujícím se časem terapie
                                              cas1 = (str2-str1)/(frekvence*str2);   //(vyjde v sekundách)jmenovatel - doba trvání jedné dvacetiny signálu. Čitatel - část periody po kterou se negeneruje signál. Celý podíl - doba po kterou se negeneruje signál 
                                              frekvence = 1/frekvence;               //výpočet periody impulzů
                                              frekvence = frekvence*str1/str2;       //výpočet časového údaje, po který se bude generovat signál (doba trvání ipmulzu)
                                              frekvence = 1/frekvence;               //skutečná frekvence, se kterou se generují impulzy
                                              FSW1 = frekvence*65536/10000;          //výpočet slova FSW1
                                              del1 = 20/del;                        //výpočet čísla, kterým se bude dělit každý vzorek - pro řízení velikosti indukce - 20 - maximální indukce
                                              }
                                             if(opakovani==2) {
                                              davka2=frekvence*(del/0.01)*(del/1000);//každou vteřinu vynásobit zvyšujícím se časem terapie
                                              cas2 = (str2-str1)/(frekvence*str2);   //jmenovatel - doba trvání jedné dvacetiny signálu. Čitatel - část periody po kterou se negeneruje signál. Celý podíl - doba po kterou se negeneruje signál 
                                              frekvence = 1/frekvence;               //výpočet periody impulzů
                                              frekvence = frekvence*str1/str2;       //výpočet časového údaje, po který se bude generovat signál (doba trvání ipmulzu)
                                              frekvence = 1/frekvence;               //skutečná frekvence, se kterou se generují impulzy
                                              FSW2 = frekvence*65536/10000;          //výpočet slova FSW1
                                              del2 = 20/del;                        //výpočet čísla, kterým se bude dělit každý vzorek - pro řízení velikosti indukce - 20 - maximální indukce.
                                              //  Dávka = dB/dt*Bmax*doba_expozice*f [T/s,T,Hz,hod]
                                              }
          break;                              
          default:kontrola=1;
                  LCDClear;
                  LCDCursor(0x00);
                  LCDPrint("Vyberte pouze",14);
                  LCDCursor(0x40);
                  LCDPrint("z dostupnych",12);
                  LCDCursor(0x80);
                  LCDPrint("programu",8);
                  __RESET_WATCHDOG();
                  zpozdeni_2s();    
        }
   }
  }
  
                                kontrola=1;  
                                while(kontrola){
                                  kontrola=0;
                                  LCDClear;
                                  LCDCursor(0x00);
                                  LCDPrint("Zadejte dobu",12);
                                  LCDCursor(0x40);
                                  LCDPrint("trvani terapie",14);
                                  LCDCursor(0x4e);
                                      tlacitko=sken();
                                      doba+=10*tlacitko;
                                      LCDPrint(&tlacitko,1);
                                      tlacitko=sken();
                                      doba+=tlacitko;
                                      LCDPrint(&tlacitko,1);
                                      __RESET_WATCHDOG();
                                        if (doba>59 | doba<1){
                                             kontrola=1;
                                             doba=0;
                                             LCDClear;
                                             LCDCursor(0x00);
                                             LCDPrint("Doba musi byt",16);
                                             LCDCursor(0x40);
                                             LCDPrint("v rozsahu",9);
                                             LCDCursor(0x80);
                                             LCDPrint("od 1 do 59 min",14);
                                             __RESET_WATCHDOG();
                                             zpozdeni_2s();
                                        }
                                }  
  
   I2C_init(); 
   I2C_write_32bit(0x42,FSW1);
   I2C_write_32bit(0x42,del1);
   I2C_write_32bit(0x42,cas1); 
   I2C_write_32bit(0x43,FSW2);
   I2C_write_32bit(0x43,del2);
   I2C_write_32bit(0x43,cas2); //vyslání řídících hodnot pro generující MCU
   
   doba = char_2_BCD(doba);
   doba = doba | 0b10000000;                //prní bit musí být jedna -> povolení alarmu
   RTC_init (doba);                         //V RTC je nastaven alarm na požedovaný čas, je nastaveno generování přerušení každou sekundu ale hodiny zatím stojí - zastavení hodin resetuje počítací registry. Odsimulováno, vypadá dobře.
   LM92_init(T_crit);                       //je nastaveno teplotní čidlo na alarm při požadované teplotě a pointer je nastaven na teplotní registr -> neinkrementuje se po čtení -> jednodušeji se čte
                                         
   while (!PTFD_PTFD1);                      //potvrzení dokončení výpočtu od generátoru
   while (!PTFD_PTFD4);                      //potvrzení dokončení výpočtu od generátoru

   IRQSC_IRQIE = 1;  //povolení externího přerušení -> ostatní nastavení je provedeno pomocí device initialization 
  
 
    LCDClear;                             //vymazání displeje
    LCDCursor(0x00);                      //posun kuzroru na začátek displeje
    LCDPrint("Probiha terapie",15);       //zápis na LCD displej
    LCDCursor(0x40);                      //posun na druhý řádek
    LCDPrint("Doba trvani 00:00",17);
    LCDCursor(0x80);
    LCDPrint("Teplota 00.00°C",15);
    LCDCursor(0x80);
    LCDPrint("Davka 0000;0000",15); // maximální terapeutická dávka = dB/dt*Bmax*doba_expozice*f = 0,02/(10*10^-6)*0,02*100*(59/60)=cca 3933[T/s,T,Hz,hod]
    //jednotka dávky je (T/s)^2*hod

   
    
     while(1){
      char j=0;
      IIC1C_MST = 1;            // MASTER mód - generování START
      IIC1C_TX = 1;             // TRANSMIT mód 
      IIC1D  = (0b10100010);    // zapsání adresy slave do datového registru + osmý vyslaný bit je R/W - nevím, jestli se to dělá automaticky - otestovat reálně
      while (!IIC1S_TCF);       // počkání na odeslání adresy
      for (j=5;j>0;j--);        // zpoždění aby stačil SLAVE poslat ACK nebo NACK
        if (!IIC1S_RXAK){
        IIC1D  = (0b00000000);  // zapsání adresy prvního registru v RTC control/status register 1
        while (!IIC1S_TCF);     // počkání na odeslání adresy
        for (j=5;j>0;j--);      // zpoždění aby stačil SLAVE poslat ACK nebo NACK
          if (!IIC1S_RXAK){  
          IIC1D = 0b00000000;   //nulování STOP bitu -> rozběhne se čítač
          while (!IIC1S_TCF);
          for (j=5;j>0;j--);
            if (!IIC1S_RXAK){ 
            IIC1C_MST = 0;        // generování STOP signálu
            for (j=5;j>0;j--);
            __RESET_WATCHDOG();
            break;  
            }
      for (j=5;j>0;j--);
      __RESET_WATCHDOG();
      }
    }
  }
    PTFD_PTFD5 = 1;                           //vyslání startovacího signálu pro generátor
    PTFD_PTFD0 = 1;                           //vyslání startovacího signálu pro generátor data direction je nastavený
     
  //reset pokud se kousne RTC
  //watchdog resetuje MCU max.po 26ms -> tady se mi to nehodí
  //udělám  pomocí čítače reálného času -> má zdroj hodinového signálu nezávislý na bus clock
  //RTI (generované čítačem reálného času) se resetuje nulováním předděličky

  
  TPM1SC_TOIE=0;  
  EnableInterrupts;// povolení všech přerušení
  while (1) {
  SRTISC_RTIS0 = 1;
  SRTISC_RTIS1 = 1;
  SRTISC_RTIS2 = 1; // po 1,024 s se generuje přerušení a  pokud se RTC 3x za sebou neozve -> reset
  __RESET_WATCHDOG();//pokud běží RTC resetuje se watchdog 
 
  } 
  
}//konec main