/*
 * kabo1.c
 * Manual Control Program via terminal connection
 * c:\mc\cc51 %1 -ilp h=c:\mc m=s s=c52robot.asm  < need new startup file
 * that uses timer2 for PWM generation
 * Copyright (c) 2000 by Wichit Sirichote
 */

#include "c:\mc\8051io.h"  /* include i/o header file */
#include "c:\mc\8051reg.h"
#include "c:\mc\8051bit.h"

extern register char cputick;
extern register int  PWM1,PWM2;

register char i,j,temp,flag1,flag2,speed1,speed2,led,step,index;
unsigned register char command,buffer[5];
register int count1,counter1,counter2;

unsigned int power[] = {0x0000,0x0001,0x0101,0x0841,0x1111,0x1249,0x2949,0x2A93,
0x5555,0xD555,0xD5D5,0xEDB6,0xEEEE,0xF7BE,0xFEFE,0xFFFE,0xFFFF};

/* Power Bit Hexadecimal Level Pattern Value by Fred Martin for MIT's MiniBoard */
/* the output P1.7 and P1.6 are connected to inverter, thus the power level
   is then be in reverse order, i.e., $0000 is top speed while the $FFFF is
   lowest speed (motors are stopped), however, user can use -16 to 16, for full
   reverse and full forward in program, since motor1() and motor2() functions
   will provide the proper value for PWM1 and PWM2. see below;

        0  0000000000000000 $0000   <--- top
        1  0000000000000001 $0001
        2  0000000100000001 $0101
        3  0000100001000001 $0841
        4  0001000100010001 $1111
        5  0001001001001001 $1249
        6  0010100101001001 $2949
        7  0010101010010101 $2A93
        8  0101010101010101 $5555
        9  1101010101010101 $D555
        10 1101010111010101 $D5D5    
        11 1110110110110110 $EDB6
        12 1110111011101110 $EEEE
        13 1111011110111110 $F7BE
        14 1111111011111110 $FEFE
        15 1111111111111110 $FFFE
        16 1111111111111111 $FFFF    <--- stop 

*/

/* constants definition */

#define LED P1.3
#define blink_every 10
#define right_period 10
#define left_period 10


#define forward_speed 15
#define back_speed -15

#define SCLK P3.5
#define SDA P3.4


main()

{
   flag1 = 0;
   flag2 = 0;
   index = 0;
   stop_both();
   clrbit(LED)
   counter1 = 0;
   counter2 = 200;
   printf("\n KABO's Manual Control Program\n\
           \n command keys: i,j,k,m or Arrows, p (print ADC0,1,2,3,port_B)\
           \n\
           \n             I (forward)\
           \n (left)  J       K (right)\
           \n             M (backward)\
           \n\
           \n SPACE bar (stop)\n");

   while(1)
   {
      while( cputick <10)
      ;
      cputick = 0;
// execute following tasks every 100ms
      command = chkch();  // soon emitted from sensoring decision
 //     command_emitter();
      print_ADC();
      cpubeat();
      forward();
      backward();
      turn_right();
      turn_left();
      stop();
      run_motor();
      timer();

   }
}

/*   robot_behaviors
     sleep();
     forward();
     backward();
     stop();
     forward_left();
     backward_right();
     backward_left();

     sensor tasks
     follow_line();
     seeking_line();
*/


/* motor1(int s)  s -16 to 16 */

motor1(int s)
{
     if (s < 0)
       setbit(P1.5)
       else clrbit(P1.5)
       clrbit(IE.7)
       PWM1 = power[16-abs(s)];
       setbit(IE.7)
}


/* motor2(int s)  s -16 to 16 */

motor2(int s)
{
    if (s < 0)
      setbit(P1.4)
      else clrbit(P1.4)
      clrbit(IE.7)
      PWM2 = power[16-abs(s)];
      setbit(IE.7)
}

run_motor(){

    if((flag1 & 0x01) != 0){
          stop_both();
          delay(3);
          motor1(speed1);
          motor2(speed2);
          flag1 &= ~0x01;
          flag2 |= 0x01;   // run timer
          }
}

timer()
{
    if((flag2 & 0x01) != 0){
        count1--;
        if(count1 == 0)
           {
           stop_both();
           flag2 |= 0x80;   // timer done flag
           flag2 &= ~0x01;   // disable entering timer execution
           }
                            }
}

stop_both()
{
    motor1(0);
    motor2(0);
}

forward()
{
   if(command == 'i' || command == 0x0b){
   count1 = 500;
   speed1 = forward_speed-1;
   speed2 = forward_speed;
   flag1 |= 0x01;  // run forward
                     }
}

backward()
{
   if(command == 'm'|| command == 0x16){   
   count1 = 500;
   speed1 = back_speed;
   speed2 = back_speed;
   flag1 |= 0x01;  // run motor
                     }
}

stop(){
   if (command == ' '){
   stop_both();
   }
}

turn_right(){
  if(command == 'k'|| command == 0x0c){ 
   count1 = right_period;
   speed1 = 13;
   speed2 = -13;
   flag1 |= 0x01; // run motor
   }
}

turn_left(){
  if(command == 'j'|| command == 0x08){ 
   count1 = left_period;
   speed1 = -13;
   speed2 = 13;
   flag1 |= 0x01; // run motor
   }
}

cpubeat()
{
    beat5sec();
    livecpu();

}

beat5sec()  /* set bit P1.3 every counter1 > blink_every */

{
       counter1++;
        if (counter1 > blink_every )
        {
           counter1 = 0;
           flag1 |= 0x40; /* set bit 6 of flag1 to signal livecpu task */
           setbit(LED) 
           led = 1;      /* 3*100ms = 300ms LED on */
        }

}

livecpu()

{
    if ((flag1 & 0x40) != 0)
      {
        if (led == 0)
           {
           clrbit(LED) 
           flag1 &= ~0x40;
           }
           led--;
    }
}

char sequence[5] = {'i','j','i','j',' '}

command_emitter(){
    counter2--;
    if (counter2 < 0){
      counter2 = 300;
      if (index < 5)
      command = sequence[index++];
      else (index=0);
      putch(command);
      }
}

pause(int j)
{
   int i;
   for (i = 0; i < j; i++)
   ;
}

read_ADC()  //use rrc instruction shifting SDA in 40-bit register
{
        disable();
//        setbit(LED)
        clrbit(SCLK)       // start bit
        pause(10);
        for(i=0;i<40;i++)    /* loop 40-bit */
        {
         clrbit(SCLK)
         pause(3);
         setbit(SCLK)        /* produce rising edge pulse */
         pause(3);
       asm{          // 40-bit SIPO register using buffer[5]
       setb  SDA
       mov   C,SDA
       mov   A,buffer+4
       rrc   A
       mov   buffer+4,A
       mov   A,buffer+3
       rrc   A
       mov   buffer+3,A
       mov   A,buffer+2
       rrc   A
       mov   buffer+2,A
       mov   A,buffer+1
       rrc   A
       mov   buffer+1,A
       mov   A,buffer
       rrc   A
       mov   buffer,A
       }
         }
//       clrbit(LED)
       enable();
}

print_ADC(){
   if (command == 'p'){
     read_ADC();
     putch(13);
     printf("                        ");
     putch(13);
     printf("%u %u %u %u %08b",buffer[0],buffer[1],buffer[2],buffer[3],buffer[4]);
   }
}
