// File: Servo_control_send.c
//
// Description:
// Controls 2 servos and 1 remote switch through rs232
// sends 1 byte commands for vertical and horizontal position in%, remote switch on/off
// range 0-100: horizontal, 101-200: vertical position
// remote switch: 254:on, 255 off

//   
// Tested on 16F688
// Requirements:
//    
//////////////////////////////////////////////////////////////////////
//#define DEBUG
//////////////////////////////////////////////////////////////////////
//**********************************************
#include <16F688.h>
#device *=16            // 16 bits pointers
#device adc=8           //ADC bit number

#use delay(clock=8000000)

//#use rs232(BAUD=9600,XMIT=PIN_A0, RCV=PIN_A1)    // interrupt disable while reading,DISABLE_INTS
#use rs232(BAUD=9600,XMIT=PIN_C4, RCV=PIN_C5)      // for sending commands

#FUSES       HS, PUT, NOWDT, INTRC, NOPROTECT, BROWNOUT, MCLR, NOCPD, IESO, FCMEN  // internal clock
//  #FUSES   HS, PUT, NOWDT,        NOPROTECT, BROWNOUT, MCLR, NOCPD, IESO, FCMEN  //ext clock

//*****************    Hardware setup
// pickit ICSP PINs
//  P1 Vpp:             RA3   !!!!!!
//  P2 VDD
//  P3 GND
//  P4 DAT:             RA0, xmit
//  P5 Clock:           RA1, rcv
//  P6 T1G:             RA4, idle
 
// PIC PIN functions
//                      RA_0           XMIT pickit
//                      RA_1           RCV   pickit
//                      RA_2           ADC horizontal INPUT analog
//                      RA_3           VPP!!!
//                      RC_0           ADC vertical   INPUT analog
//                      RC_3           swith input
//                      RC-4           XMIT
//                      RC_5           RCV            INPUT digital

#define hor_pos 2              //ADC: horizontal port number A.2
#define hor_port sAN2
#define ver_pos 4              //ADC: vertical port number C.0 
#define ver_port sAN4
//#define power_pin  PIN_C3    // power-switch input
#define power_pos  7           // power-switch input
#define power_pin  sAN7       // power-switch input
//===========================================================================
// global variables
//********************************************
void main_init()                 
{
//******************************************************************************
// INITIALIZATION
//    PIC INIT
setup_oscillator( OSC_8MHZ );
setup_comparator(NC_NC_NC_NC);

//   PINs init
   output_low(power_pin);      //base state is switched off
}
void adc_init()
{
//ADC
setup_adc(ADC_CLOCK_INTERNAL);      //
//setup_adc_ports(hor_port|ver_port|VSS_VDD);
setup_adc_ports(hor_port|ver_port|power_pin|VSS_VDD);

set_tris_a(4);     //A.2 A/D input
set_tris_c(1);     //C.0 A/D input
}
//****************************************************

//*****************
analog_control_read()
{
int ratio;

   delay_us(20);
   ratio = read_adc();                 // Built-in A/D read function
   return(ratio);
}
position_read_set(int prev_ratio, unsigned int direction)   // directin is 0 if hor, 101 if ver
{
int16 ratio;
unsigned int command_text;          //
signed int16 temp;

      ratio=analog_control_read(); // read ratio from analog port
 
      temp=(100*ratio)/255;
      if ( ((temp - prev_ratio)>1)   ||
           ((prev_ratio - temp)>1) )       //new poition
          {
            prev_ratio=temp;
            command_text=direction+temp ;
            printf("%c", command_text ); //send new position        
            #IFDEF DEBUG //for debug
//               printf("\r\n command ratio temp prev_ratio:  %3u %4lu %4ld %4d \r\n", command_text, ratio temp, prev_ratio );  
            #ENDIF
          }
return(prev_ratio);
}
void read_switch(int *power_state)                    // reading/sending local switch state
{
int sw;

   set_adc_channel(power_pos);  // reading power switch
   sw=analog_control_read();
   if (sw>100)
      sw=TRUE;
   else
      sw=FALSE;
   #IFDEF DEBUG //for debug
//      printf("\r\n sw, input: %3u %3u \r\n", sw, input(power_pin)  );  
   #ENDIF

   if (sw)      // switch is on
         if(*power_state!=TRUE)  //previous state is off
            {
               #IFDEF DEBUG //for debug
//                   printf("\r\n ON power pin, power_state: %3u %3u \r\n", sw, *power_state  );  
               #ENDIF
               printf("%c", 254 ); //send remote SWITCH ON       
               *power_state=TRUE;
//               output_low(power_pin);      //base state is switched off
            }
         else
         ;
   else                       // switch is off
         if (*power_state==TRUE)  //previous state is on
            {
               #IFDEF DEBUG //for debug
                   printf("\r\n OFF power pin, power_state: %3u %3u \r\n", sw, *power_state  );  
               #ENDIF
               printf("%c", 255 ); //send remote SWITCH OFF       
               *power_state=FALSE;
            }
}


//******************************
void main()
{
int hor_ratio, ver_ratio;
int power_state;

   main_init();
   adc_init();
   
   hor_ratio=202;             // to initiate command setting
   ver_ratio=202;
   power_state=2;             // to initiate power switch sending
   delay_ms(100);              // 

   #IFDEF DEBUG //for debug
         printf("\r\n START...\r\n" );  
   #ENDIF



   while (TRUE)                  // repeats A/D reading
      {
//        reading/sending local switch state
        read_switch(&power_state);
//        reading/sending horizontal position
        set_adc_channel(hor_pos);  // reading horizontal
        hor_ratio=position_read_set(hor_ratio, 0);
//        reading/sending vertical position
        set_adc_channel(ver_pos);  // reading vertical
        ver_ratio=position_read_set(ver_ratio, 101);
    }
}
////////////////////////////////////////////////////////////////////////

   
