/*
Ovladani domu rozvadec 2. n.p.

Syntaxe prikazu:

<Roleta/Svetlo><#patro><#mistnost><Nord/Jih/Vychod/Zapad/A/B><Up/Down>
R2aNU - roleta, 2. n.p., mistnost 10, sever, nahoru
S12A  - svetlo, 1. n.p., mistnost 2, prostredni

Rozmisteni desek:

  [CAN]
                 [IN J]     [IN D]
[OUT A]   [CPU]

[OUT F]     [OUT B]      [OUT E]

*/
#include "main.h"

#case
#use fast_io(A)      // Aby se neztracely znaky pri cteni prikazu
#use fast_io(B)
#use fast_io(E)
#use fast_io(F)
#use fast_io(D)
#use fast_io(J)

#define  REVERS      3     // 3*256 ms = 0,75 s
#define  GO          117   // 117*256 ms = 30 s
#define  GO_ZALUZIE  6     // cca 1,5 s
#define  RECEIVE     10    // cca 2,6 s
#define  ZAKMIT      2000  // pocet pruchodu hlavni smyckou pred opetovnou detekci prepnuti vypinace

#define OR110NU PIN_A0  // t1 Zaluzie koupelna dole
#define OR110ND PIN_A1  // t2
#define OR207VU PIN_A2  // t3 Roleta klubovna
#define OR207VD PIN_A3  // t4
#define OR103VU PIN_A4  // t5 Roleta loznice
#define OR103VD PIN_A5  // t6
#define OR104JU PIN_A6  // t7 Roleta laborator jih
#define OR104JD PIN_A7  // t8

#define OS103J  PIN_B0  // t1 Svetla loznice
#define OS105Z  PIN_B1  // t2 Svetlo kuchyn nad lavici
#define OS110N  PIN_B2  // t3 Svetlo koupelna dole zachod a sprhca
#define OS106A  PIN_B3  // t4 Svetlo trucovna stred
#define OS107A  PIN_B4  // t5 Svetlo satna
#define OS109A  PIN_B5  // t6 Svetlo technologicka mistnost
#define OS205A  PIN_B6  // t7 Svetlo puda
#define OS204A  PIN_B7  // t8 Svetlo radiomistnost

//#define OS105C PIN_C2 
//#define PIN_C3  31763
//#define PIN_C4  31764
//#define PIN_C5  31765
//#define PIN_C6  31766 //TX
//#define PIN_C7  31767 //RX

#define OS102A  PIN_E0  // t1 Svetlo chodba
#define OS105A  PIN_E1  // t2 Svetlo kuchyne stred
#define OS207A  PIN_E2  // t3 Svetlo klubovna
#define OS104A  PIN_E3  // t4 Svetlo laborator
#define OS202A  PIN_E4  // t5 Svetlo Kaklik stred
#define OS209A  PIN_E5  // t6 Svetlo Zizala koupelna
#define OS203A  PIN_E6  // t7 Svetlo Kaklik koupelna
//#define O... PIN_E7  // t8 

#define OR104VU PIN_F0   // t1 Roleta laborator vychod
#define OR104VD PIN_F1   // t2 
#define OR202JU PIN_F2   // t3 Roleta Kaklik 
#define OR202JD PIN_F3   // t4 
#define OR204ZU PIN_F4   // t5 Roleta radiomistnost
#define OR204ZD PIN_F5   // t6
//#define O... PIN_F6   // t7
//#define O... PIN_F7   // t8

//#define I.... input(PIN_D0)  // A
#define IS201AZ   input(PIN_D1)  // B Vypinac chodba 2.n.p. zapad u Kaklika
#define IS207AJ   input(PIN_D2)  // C Vypinac klubovna
#define IR207VD   input(PIN_D3)  // D Vypinac roleta klubovna dolu
#define IR207VU   input(PIN_D4)  // E Vypinac roleta klubovna nahoru
#define IS201AV   input(PIN_D5)  // F Vypinac chodba 2.n.p. vychod
#define IS209AJ   input(PIN_D6)  // G Vypinac koupelna Zizala
#define IS203AJ   input(PIN_D7)  // H Vypinac koupelna Kaklik

#define IS202AN   input(PIN_J0)  // A Vypinac svetlo Kaklik stred u dveri na chodbu
#define IR202ND   input(PIN_J1)  // B Vypinac roleta Kaklik dolu u dveri
#define IR202NU   input(PIN_J2)  // C Vypinac roleta Kaklik nahoru u dveri
#define IS205A    input(PIN_J3)  // D Vypinac svetlo puda
#define IS204AJ   input(PIN_J4)  // E Vypinac svetlo radiomistnost u dveri na chodbu
#define IR204ZD   input(PIN_J5)  // F Vypinac roleta radiomistnost dolu
#define IR204ZU   input(PIN_J6)  // G Vypinac roleta radiomistnost nahoru
//#define I.... input(PIN_J7)  // H 

int1  s201AV;
int1  s201AZ;
int1  s207AJ;
int1  s203AJ;
int1  s209AJ;
int1  r207VU;
int1  r207VD;
int1  s202AN;
int1  r202ND;
int1  r202NU;
int1  s205A; 
int1  s204AJ;  
int1  r204ZD;  
int1  r204ZU; 

#bit CREN = 0xFAB.4      // USART enable register

#define LED1 PIN_C0
#define LED2 PIN_C1 

#define ON(port)  output_low(port);
#define OFF(port) output_high(port);

typedef enum {GO_UP, GO_DOWN, REVERS_UP, REVERS_DOWN, STOP} state;

state r103V, r110N, r104V, r104J, r207V, r202J, r204Z;      // Stavy rolet
int8 tr103V, tr110N, tr104V, tr104J, tr207V, tr202J, tr204Z;   // Casovace rolet
int8 timer;                            // Casovac komunikace

#int_TIMER0
void  TIMER0_isr(void) 
{
   if(tr103V>0) tr103V--;
   if(tr110N>0) tr110N--;
   if(tr104V>0) tr104V--;
   if(tr104J>0) tr104J--;
   if(tr207V>0) tr207V--;
   if(tr202J>0) tr202J--;
   if(tr204Z>0) tr204Z--;
   if(timer>0) timer--;
output_toggle(LED2);
}

void up(state *status, int8 *timer) // Zmena stavu rolety smer nahoru
{
   switch (*status)
   {
      case STOP:
      case GO_DOWN:
         *status=REVERS_UP;
         *timer=REVERS;
         break;
      case REVERS_UP:
      case GO_UP:
         *status=STOP;
         *timer=0;
         break;
   }
}

void down(state *status, int8 *timer) // Zmena stavu rolety smer dolu
{
   switch (*status)
   {
      case STOP:
      case GO_UP:
         *status=REVERS_DOWN;
         *timer=REVERS;
         break;
      case REVERS_DOWN:
      case GO_DOWN:
         *status=STOP;
         *timer=0;
         break;
   }
}

#define run(x) {                                \
   switch(r##x)                                 \
   {                                            \
      case STOP:                                \
         OFF(OR##x##U);                          \
         OFF(OR##x##D);                          \
         break;                                 \
      case GO_UP:                               \
         OFF(OR##x##D);                          \
         ON(OR##x##U);                           \
         if(tr##x==0) {r##x=STOP;}              \
         break;                                 \
      case GO_DOWN:                             \
         OFF(OR##x##U);                          \
         ON(OR##x##D);                           \
         if(tr##x==0) {r##x=STOP;}              \
         break;                                 \
      case REVERS_UP:                           \
         OFF(OR##x##U);                          \
         OFF(OR##x##D);                          \
         if(tr##x==0) {r##x=GO_UP; tr##x=GO;}   \
         break;                                 \
      case REVERS_DOWN:                         \
         OFF(OR##x##U);                          \
         OFF(OR##x##D);                          \
         if(tr##x==0) {r##x=GO_DOWN; tr##x=GO;} \
         break;                                 \
   }                                            \
}      

void main()
{
   char buf[10];                 // Buffer pro prijem prikazu
   unsigned int16 zakmity=0;      // Osetreni zakmitu vypinacu
   
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_2);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   
   set_tris_a(0);    // Vystupy
   set_tris_b(0);
   set_tris_e(0);
   set_tris_f(0);
   set_tris_d(0xFF); // Vstupy
   set_tris_j(0xFF);

   output_a(0xFF);    // Vsechno zhasni a zastav
   output_b(0xFF);    
   output_f(0xFF);    
   output_e(0xFF);    

   r103V=STOP;    // Rolety jsou zastaveny
   r110N=STOP;
   r104V=STOP;
   r104J=STOP;  
   r207V=STOP;  
   r202J=STOP;  
   r204Z=STOP;  
   tr103V=0;
   tr110N=0;
   tr104V=0;
   tr104J=0;
   tr207V=0;
   tr202J=0;  
   tr204Z=0;  
   
   {
      int n;
      
      for(n=0;n<10;n++)
      {
         output_low(LED1); // Indikace restartu (pockame na nabiti kondenzatoru ve vstupnich obvodech)
         delay_ms(100);   
         output_high(LED1);  
         delay_ms(100);
         restart_wdt();
      }
   }
   
   s201AV=IS201AV;    // Precteme vychozi stav vypinacu
   s201AZ=IS201AZ;
   s207AJ=IS207AJ;
   s203AJ=IS203AJ;
   s209AJ=IS209AJ;
   r207VU=IR207VU;
   r207VD=IR207VD;
   s202AN=IS202AN;
   r202ND=IR202ND;
   r202NU=IR202NU;
   s205A=IS205A; 
   s204AJ=IS204AJ;  
   r204ZD=IR204ZD;  
   r204ZU=IR204ZU; 
     
   CREN=0; CREN=1;               // Reinitialise USART
   
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);

   while(TRUE)
   {
      restart_wdt();

      if(kbhit()) // Chce po nas nekdo neco?
      {
         buf[0]=getc();
         if((buf[0]=='S')||(buf[0]=='R')) // Jinym znakem nesmi zacinat prikaz
         {
            int8 n=0;      // Ukazatel do prijimaciho bufferu         
            timer=RECEIVE; // Timeout pro prijem znaku
            
            do
            {
               if(kbhit())   // Je dalsi znak?
               {
                  n++;
                  buf[n]=getc();
               }
            } while ((buf[n]!='\r')&&(timer>0)&&(n<7));
            
            if (timer==0) { CREN=0; CREN=1; }   // Reinitialise USART

            output_toggle(LED1);  // Ukonceni prijimani prikazu
            
            if((timer>0))
            {

               if((buf[0]=='S')&&(n>=4))  // Zmena stavu svetla
               {
                  if(buf[1]=='1')
                  {
                     switch(buf[2])
                     {
                        case '2':
                           output_toggle(OS102A);
                           break;
                        case '3':
                           output_toggle(OS103J);
                           break;
                        case '4':
                           output_toggle(OS104A);
                           break;
                        case '5':
                           if(buf[3]=='A') {output_toggle(OS105A);}
                           if(buf[3]=='Z') {output_toggle(OS105Z);}
                           break;
                        case '6':
                           output_toggle(OS106A);
                           break;
                        case '7':
                           output_toggle(OS107A);
                           break;
                        case '8':
//                           output_toggle(OS108A);
                           break;
                        case '9':
                           output_toggle(OS109A);
                           break;
                        case 'a':
//                           output_toggle(OS110J);
                           output_toggle(OS110N);
                           break;
                     }
                  }
               }
               
               if((buf[0]=='R')&&(n>=5))  // Zmena stavu rolety
               {
                  if(buf[1]=='1')
                  {
                     switch(buf[2])
                     {
                        case '3':
                           if(buf[4]=='U') {up(&r103V,&tr103V);} else {down(&r103V,&tr103V);}
                           break;
                        case '4':
                           if(buf[3]=='V') if((buf[4]=='U')) {up(&r104V,&tr104V);} else {down(&r104V,&tr104V);}
                           if(buf[3]=='J') if((buf[4]=='U')) {up(&r104J,&tr104J);} else {down(&r104J,&tr104J);}
                           break;
                        case 'a':
                           if((buf[4]=='U')) {up(&r110N,&tr110N);} else {down(&r110N,&tr110N);}
                           break;
                     }
                  }
               }
      
            }
         }
      }
            
      run(103V);     // Rizeni rolet za behu
//      run(104V);
      run(104J);
      run(207V);
      run(202J);
      run(204Z);

      switch(r110N)  // Zaluzie ma specielni rizeni                                 
      {                                            
         case STOP:                                
            OFF(OR110NU);                          
            OFF(OR110ND);                          
            break;
         case GO_UP:                               
            OFF(OR110ND);                          
            ON(OR110NU);                           
            if(tr110N==0) {r110N=STOP;}              
            break;                                 
         case GO_DOWN:                             
            OFF(OR110NU);                          
            ON(OR110ND);                           
            if(tr110N==0) {r110N=STOP;}              
            break;                                 
         case REVERS_UP:                           
            OFF(OR110NU);                          
            OFF(OR110ND);                          
            if(tr110N==0) {r110N=GO_UP; tr110N=GO_ZALUZIE;}   // Nahoru pouze kratce na otevreni zaluzie
            break;                                 
         case REVERS_DOWN:                         
            OFF(OR110NU);                          
            OFF(OR110ND);                          
            if(tr110N==0) {r110N=GO_DOWN; tr110N=GO_ZALUZIE;} // Dolu take kratce pouze na zaklopeni zaluzie
            break;                             
      }                                                    

      // mistni vypinace z 2. n.p.
      if (0==zakmity)
      {
         if(s201AV!=IS201AV) {s201AV=IS201AV; output_toggle(OS102A); zakmity=ZAKMIT;}
         if(s201AZ!=IS201AZ) {s201AZ=IS201AZ; output_toggle(OS102A); zakmity=ZAKMIT;}
         if(s207AJ!=IS207AJ) {s207AJ=IS207AJ; output_toggle(OS207A); zakmity=ZAKMIT;}
         if(s203AJ!=IS203AJ) {s203AJ=IS203AJ; output_toggle(OS203A); zakmity=ZAKMIT;}
         if(s209AJ!=IS209AJ) {s209AJ=IS209AJ; output_toggle(OS209A); zakmity=ZAKMIT;}
         if(s205A!=IS205A) {s205A=IS205A; output_toggle(OS205A); zakmity=ZAKMIT;}
         if(s204AJ!=IS204AJ) {s204AJ=IS204AJ; output_toggle(OS204A); zakmity=ZAKMIT;}
         if(s202AN!=IS202AN) {s202AN=IS202AN; output_toggle(OS202A); zakmity=ZAKMIT;}
    
         if(r207VU!=IR207VU) {r207VU=IR207VU; up(&r207V,&tr207V); zakmity=ZAKMIT;}
         if(r207VD!=IR207VD) {r207VD=IR207VD; down(&r207V,&tr207V); zakmity=ZAKMIT;}
         if(r202NU!=IR202NU) {r202NU=IR202NU; up(&r202J,&tr202J); zakmity=ZAKMIT;}
         if(r202ND!=IR202ND) {r202ND=IR202ND; down(&r202J,&tr202J); zakmity=ZAKMIT;}
         if(r204ZU!=IR204ZU) {r204ZU=IR204ZU; up(&r204Z,&tr204Z); zakmity=ZAKMIT;}
         if(r204ZD!=IR204ZD) {r204ZD=IR204ZD; down(&r204Z,&tr204Z); zakmity=ZAKMIT;}
      }
      else zakmity--;
   }
}