//******** Mrakomer2 - stepper motor control *****************
#define VERSION "3.0"  // Special version for BART
#define ID "$Id: irmrak.c 420 2006-12-29 21:43:11Z kakl $"
//************************************************************

#include "irmrak.h"
#include <string.h>

char VER[4]=VERSION;
char REV[50]=ID;

#bit CREN = 0x18.4      // USART registers
#bit SPEN = 0x18.7
#bit OERR = 0x18.1
#bit FERR = 0x18.2

#define HALL   PIN_A4      // Hallova sonda pro zjisteni natoceni dolu
// vykonovy FET je na RB3 (vystup PWM)

int port;   // stav brany B pro krokove motory
int j;      // pro synchronisaci fazi
unsigned int8  uhel;   // prijaty znak
unsigned int8  i;      // pro cyklus for

// --- Kroky krokoveho motoru ---
void krok(int n)
{
   while((n--)>0)
   {
      if (1==(j&1)) {port^=0b11000000;} else {port^=0b00110000;};
      output_B(port);
      delay_ms(20);     // Nutno nastavit podle dynamiky systemu.
      j++;
   }
}

// --- Dojet dolu magnetem na cidlo ---
void dolu()
{
   unsigned int8 err;   // pocitadlo pro zjisteni zaseknuti otaceni

   err=0;
   while(!input(HALL))  // otoceni trubky dolu az na hall
   {
      krok(1);
      err++;
      if(40==err)       // do 40-ti kroku by se melo podarit otocit dolu
      {
         output_B(0);   // vypnuti motoru
         printf("E");   // Hlasime chybu
         err=0;
      }
   };
   delay_ms(500);    // cas na ustaleni trubky
   output_B(0);      // vypnuti motoru
}

// --- Najeti na vychozi polohu dole ---
void nula()
{
   port=0b10100000;  // vychozi nastaveni fazi pro rizeni motoru
   output_B(port);
   j=0;              // smer dolu
   delay_ms(500);
}


//------------------------------------------------
void main()
{
   setup_oscillator(OSC_8MHZ|OSC_INTRC);     // 8 MHz interni RC oscilator

   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF);
   setup_spi(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);  
   setup_timer_1(T1_DISABLED);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);  
   setup_vref(FALSE); 

   output_B(0);               // vypnuti motoru a topeni
   set_tris_B(0b00000111);    // faze a topeni jako vystupy  


   while(true)
   {
      nula();
      dolu();           // otoc trubku do vychozi pozice dolu

      CREN=0; CREN=1;               // Reinitialise USART

      while(!kbhit())
      {
         if (!input(HALL)) // znovuotoceni trubky dolu, kdyby ji vitr otocil
         {
            dolu();
         }
      }; // pokracuj dal, kdyz prisel po RS232 znak


      uhel=getc();   // prijmi znak
      if ('m'==uhel) // standardni mereni ve trech polohach
      {
         nula();
         j++;    // reverz, nahoru

         krok(18);
         printf("A");   // mereni teploty 45° nad obzorem
         delay_ms(200);
         krok(7);
         printf("B");   // mereni teploty v zenitu
         delay_ms(200);
         krok(7);
         printf("C");  // mereni teploty 45° nad obzorem na druhou stranu
         delay_ms(200);

         j++;     // reverz
         dolu();
         printf("G");  // mereni teploty Zeme (<G>round)

         continue;
      }
      
      if ('i'==uhel) {printf("I"); continue;} // Predani prikazu pro Info
      if ('h'==uhel) {printf("H"); continue;} // Predani prikazu pro Topeni  
      if ('c'==uhel) {printf("C"); continue;} // Predani prikazu pro vypnuti topeni  
      if ('x'==uhel)                          // Zjisteni verze FW
      {
         printf("Mrakomer - Motor  V%s (C) 2006 KAKL\n\r", VER);
         printf("%s\n\r", REV);
      }

      if ((uhel>='0') && (uhel<='@')) // mereni v pozadovanem uhlu [0..;]=(0..11)
      {
         uhel-='0';
      };

      if(uhel>11) continue;   // ochrana, abysme neukroutili draty

      nula();
      j++;     // reverz, nahoru

      krok(12);      // odkrokuj do roviny
      for(i=0; i<uhel; i++) // dale odkrokuj podle pozadovaneho uhlu
      {
         krok(2);
      };
      printf("S");
      delay_ms(200);

      j++;     // reverz
      dolu();
      printf("G");  // mereni teploty Zeme (<G>round)
   }
}