// Black and white NTSC video game generation with fixed point animation
// Design Project by Lu Liu and Xu Chen
// Referenced from Mega644 version by Shane Pryor 
// mod by brl4@cornell.edu:
//    for mega1284
//    for resolution 160 horizontal x 200 vertical

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <stdlib.h> 
#include <stdio.h>
#include <math.h> 
#include <util/delay.h>  
#include <avr/sleep.h>
#include "uart.h"

// optional, if preferred///
#define begin {
#define end   }
////////////////////////////

// ADC
int Ain1, Ain2, Ain3 ,Ain4 ;         //raw A to D number
///////////////////////////            

// UART file descriptor
// putchar and getchar are in uart.c
FILE uart_str = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);

//cycles = 63.625 * 16 Note NTSC is 63.55 
//but this line duration makes each frame exactly 1/60 sec
//which is nice for keeping a realtime clock 
// video timing
#define LINE_TIME 1018 // 20 MHz 1271
#define SLEEP_TIME 999 // 20 MHz 1250
#define bytes_per_line 20
#define screen_width (bytes_per_line*8)
#define screen_height 200
#define screen_array_size screen_width*screen_height/8 
#define ScreenTop 30
#define ScreenBot (ScreenTop+screen_height)

//sync
char syncON, syncOFF;

//current line number in the current frame
volatile int LineCount;

//160h x 160v - screen buffer and pointer
char screen[screen_array_size];
int* screenindex;

//One bit masks
char pos[8] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};

//=== fixed conversion macros ========================================= 
#define int2fix(a)   (((int)(a))<<8)            //Convert char to fix. a is a char
#define fix2int(a)   ((signed char)((a)>>8))    //Convert fix to int. a is an int
#define float2fix(a) ((int)((a)*256.0))         //Convert float to fix. a is a float
#define fix2float(a) (((float)(a))/256.0)       //Convert fix to float. a is an int   

// Car Variable
unsigned int vcar_unit[] = {float2fix(0.03), float2fix(0.06),float2fix(0.1)}; // car move distance in unit time
unsigned int fix_minus_1 = int2fix(-1);
unsigned int fix_zero = int2fix(0);
unsigned int fix_200 = int2fix(200);
unsigned int fix_160 = int2fix(160);
unsigned int fix_1_30 = float2fix(1.0/30);
unsigned int fix_2_30 = float2fix(2.0/30);
unsigned int fix_3_30 = float2fix(3.0/30);
unsigned int fix_20 = int2fix(20);
unsigned int fix_0_coord = int2fix(0-128);
unsigned int fix_160_coord = int2fix(160-128);
int angle_state = 54;
int angle_state_2 = 18;
int car_gas = 0;
int car_gas_flt[] = {0, 0.05, 0.10, 0.15};
int last_wheel_angle, car_angle = 0;
int wheel_angle,  rela_car_angle, last_abs_wheel_angle;
int angle_count = 0;
int limit = 0;
int reverse = 0;
int car_width = 20;
int car_length = 50;
unsigned int x0_fix, x1_fix, y0_fix, y1_fix;

// Driver Function
int potentiometer(int voltage)
begin

   // user define voltage reading
   int max_voltage = 255;
   int min_voltage = 0;
   int voltage_level_1 = 120;
   int voltage_level_2 = 180;

   if (voltage > max_voltage) {
      return 3;
   } else if (voltage < min_voltage) {
      return 0;
   } else {
      if (voltage > min_voltage && voltage < voltage_level_1)
         return 1;
      else if (voltage > voltage_level_1 && voltage < voltage_level_2)
         return 2;
      else if (voltage > voltage_level_2)
         return 3;
   }
   return 0;
end

// this function accepts two 0-255 adc accelerometer readings
// returns an absolute angle of the steering wheel (0-359)
int abs_wheel_angle (char acc_0, char acc_1, int prev_wheel_angle)
begin
   int angle = 0;
   char acc_0_int = 0;
   char acc_1_int = 0;
   char acc = 0;

   // 0: 221
   // 45: 200
   // 90: 150
   // 135: 95
   // 180: 75
   // 225: 95
   // 270: 150
   // 315: 200
   int level_1 = 85;
   int level_2 = 122;
   int level_3 = 175;
   int level_4 = 210;

   // set acc_0 reading range
   if (acc_0 < level_1)
      acc_0_int = 0; // -1
   else if (acc_0 >= level_1 && acc_0 < level_2)
      acc_0_int = 1; // -0.7
   else if (acc_0 >= level_2 && acc_0 < level_3)
      acc_0_int = 2; // 0
   else if (acc_0 >= level_3 && acc_0 < level_4)
      acc_0_int = 3; // 0.7
   else //if (acc_0 >= level_4)
      acc_0_int = 4; // 1

   // set acc_1 reading range
   if (acc_1 < level_1)
      acc_1_int = 0; // -1
   else if (acc_1 >= level_1 && acc_1 < level_2)
      acc_1_int = 1; // -0.7
   else if (acc_1 >= level_2 && acc_1 < level_3)
      acc_1_int = 2; // 0
   else if (acc_1 >= level_3 && acc_1 < level_4)
      acc_1_int = 3; // 0.7
   else //if (acc_1 > level_4)
      acc_1_int = 4; // 1

   acc = acc_1_int * 10 + acc_0_int;
   
   switch (acc)
   begin
     case 42:
        angle = 0;
     break;
     case 33:
        angle = 45;
     break;
     case 24:
        angle = 90;
     break;
     case 13:
        angle = 135;
     break;
     case 2:
        angle = 180;
     break;
     case 11:
        angle = 225;
     break;
     case 20:
        angle = 270;
     break;
     case 31:
        angle = 315;
     break;
     default :
        angle = prev_wheel_angle;
     break;
   end

   return angle;
end

// this function receives an initial absolute angle of the steering wheel
// returns a relative wheel angle (btw -360 to +360)
int relative_wheel_angle (int init_angle, int acc_0, int acc_1)
begin

   int relative_angle;//, temp;

   relative_angle = abs_wheel_angle(acc_0, acc_1, init_angle) - init_angle;

   if (relative_angle == 315) relative_angle = -45;
   if (relative_angle == -315) relative_angle = 45;
   if (relative_angle == 270) relative_angle = -90;
   if (relative_angle == -270) relative_angle = 90;

   if (relative_angle >= 360 || relative_angle <= -360)
      relative_angle = 0;

   return relative_angle;
end

int car_angle_compute (int wheel_angle)
begin

   int car_angle;

   car_angle = 0.1 * wheel_angle;
   if(car_angle>45) car_angle=45;
   if(car_angle<-45) car_angle=-45;

   return car_angle;
end

//================================ 
//3x5 font numbers, then letters
//packed two per definition for fast 
//copy to the screen at x-position divisible by 4
prog_char smallbitmap[39][5] = { 
    //0
    0b11101110,
    0b10101010,
    0b10101010,
    0b10101010,
    0b11101110,
    //1
    0b01000100,
    0b11001100,
    0b01000100,
    0b01000100,
    0b11101110,
    //2
    0b11101110,
    0b00100010,
    0b11101110,
    0b10001000,
    0b11101110,
    //3
    0b11101110,
    0b00100010,
    0b11101110,
    0b00100010,
    0b11101110,
    //4
    0b10101010,
    0b10101010,
    0b11101110,
    0b00100010,
    0b00100010,
    //5
    0b11101110,
    0b10001000,
    0b11101110,
    0b00100010,
    0b11101110,
    //6
    0b11001100,
    0b10001000,
    0b11101110,
    0b10101010,
    0b11101110,
    //7
    0b11101110,
    0b00100010,
    0b01000100,
    0b10001000,
    0b10001000,
    //8
    0b11101110,
    0b10101010,
    0b11101110,
    0b10101010,
    0b11101110,
    //9
    0b11101110,
    0b10101010,
    0b11101110,
    0b00100010,
    0b01100110,
    //:
    0b00000000,
    0b01000100,
    0b00000000,
    0b01000100,
    0b00000000,
    //=
    0b00000000,
    0b11101110,
    0b00000000,
    0b11101110,
    0b00000000,
    //blank
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //A
    0b11101110,
    0b10101010,
    0b11101110,
    0b10101010,
    0b10101010,
    //B
    0b11001100,
    0b10101010,
    0b11101110,
    0b10101010,
    0b11001100,
    //C
    0b11101110,
    0b10001000,
    0b10001000,
    0b10001000,
    0b11101110,
    //D
    0b11001100,
    0b10101010,
    0b10101010,
    0b10101010,
    0b11001100,
    //E
    0b11101110,
    0b10001000,
    0b11101110,
    0b10001000,
    0b11101110,
    //F
    0b11101110,
    0b10001000,
    0b11101110,
    0b10001000,
    0b10001000,
    //G
    0b11101110,
    0b10001000,
    0b10001000,
    0b10101010,
    0b11101110,
    //H
    0b10101010,
    0b10101010,
    0b11101110,
    0b10101010,
    0b10101010,
    //I
    0b11101110,
    0b01000100,
    0b01000100,
    0b01000100,
    0b11101110,
    //J
    0b00100010,
    0b00100010,
    0b00100010,
    0b10101010,
    0b11101110,
    //K
    0b10001000,
    0b10101010,
    0b11001100,
    0b11001100,
    0b10101010,
    //L
    0b10001000,
    0b10001000,
    0b10001000,
    0b10001000,
    0b11101110,
    //M
    0b10101010,
    0b11101110,
    0b11101110,
    0b10101010,
    0b10101010,
    //N
    0b00000000,
    0b11001100,
    0b10101010,
    0b10101010,
    0b10101010,
    //O
    0b01000100,
    0b10101010,
    0b10101010,
    0b10101010,
    0b01000100,
    //P
    0b11101110,
    0b10101010,
    0b11101110,
    0b10001000,
    0b10001000,
    //Q
    0b01000100,
    0b10101010,
    0b10101010,
    0b11101110,
    0b01100110,
    //R
    0b11101110,
    0b10101010,
    0b11001100,
    0b11101110,
    0b10101010,
    //S
    0b11101110,
    0b10001000,
    0b11101110,
    0b00100010,
    0b11101110,
    //T
    0b11101110,
    0b01000100,
    0b01000100,
    0b01000100,
    0b01000100, 
    //U
    0b10101010,
    0b10101010,
    0b10101010,
    0b10101010,
    0b11101110, 
    //V
    0b10101010,
    0b10101010,
    0b10101010,
    0b10101010,
    0b01000100,
    //W
    0b10101010,
    0b10101010,
    0b11101110,
    0b11101110,
    0b10101010,
    //X
    0b00000000,
    0b10101010,
    0b01000100,
    0b01000100,
    0b10101010,
    //Y
    0b10101010,
    0b10101010,
    0b01000100,
    0b01000100,
    0b01000100,
    //Z
    0b11101110,
    0b00100010,
    0b01000100,
    0b10001000,
    0b11101110
};

//===============================================
// Full ascii 5x7 char set
// Designed by: David Perez de la Cruz,and Ed Lau      
// see: http://instruct1.cit.cornell.edu/courses/ee476/FinalProjects/s2005/dp93/index.html

prog_char ascii[128][7] = {
    //0
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //1
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //2
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //3
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //4
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //5
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //6
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //7
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //8
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //9
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //10
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //11
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //12
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //13
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //14
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //15
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //16
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //17
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //18
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //19
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //20
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //21
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //22
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //23
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //24
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //25
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //26
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //27
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //28
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //29
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //30
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //31
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //32 Space
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //33 Exclamation !
    0b01100000,
    0b01100000,
    0b01100000,
    0b01100000,
    0b00000000,
    0b00000000,
    0b01100000,
    //34 Quotes "
    0b01010000,
    0b01010000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //35 Number #
    0b00000000,
    0b01010000,
    0b11111000,
    0b01010000,
    0b11111000,
    0b01010000,
    0b00000000,
    //36 Dollars $
    0b01110000,
    0b10100000,
    0b10100000,
    0b01110000,
    0b00101000,
    0b00101000,
    0b01110000,
    //37 Percent %
    0b01000000,
    0b10101000,
    0b01010000,
    0b00100000,
    0b01010000,
    0b10101000,
    0b00010000,
    //38 Ampersand &
    0b00100000,
    0b01010000,
    0b10100000,
    0b01000000,
    0b10101000,
    0b10010000,
    0b01101000,
    //39 Single Quote '
    0b01000000,
    0b01000000,
    0b01000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //40 Left Parenthesis (
    0b00010000,
    0b00100000,
    0b01000000,    
    0b01000000,
    0b01000000,
    0b00100000,
    0b00010000,
    //41 Right Parenthesis )
    0b01000000,
    0b00100000,
    0b00010000,
    0b00010000,
    0b00010000,
    0b00100000,
    0b01000000,
    //42 Star *
    0b00010000,
    0b00111000,
    0b00010000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //43 Plus +
    0b00000000,
    0b00100000,
    0b00100000,
    0b11111000,
    0b00100000,
    0b00100000,
    0b00000000,
    //44 Comma ,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00010000,
    0b00010000,
    //45 Minus -
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b11111000,
    0b00000000,
    0b00000000,
    //46 Period .
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00010000,
    // 47 Backslash /
    0b00000000,
    0b00001000,
    0b00010000,
    0b00100000,
    0b01000000,
    0b10000000,
    0b00000000,
    // 48 Zero
    0b01110000,
    0b10001000,
    0b10011000,
    0b10101000,
    0b11001000,
    0b10001000,
    0b01110000,
    //49 One
    0b00100000,
    0b01100000,
    0b00100000,
    0b00100000,
    0b00100000,
    0b00100000,
    0b01110000,  
    //50 two
    0b01110000,
    0b10001000,
    0b00001000,
    0b00010000,
    0b00100000,
    0b01000000,
    0b11111000,
     //51 Three
    0b11111000,
    0b00010000,
    0b00100000,
    0b00010000,
    0b00001000,
    0b10001000,
    0b01110000,
    //52 Four
    0b00010000,
    0b00110000,
    0b01010000,
    0b10010000,
    0b11111000,
    0b00010000,
    0b00010000,
    //53 Five
    0b11111000,
    0b10000000,
    0b11110000,
    0b00001000,
    0b00001000,
    0b10001000,
    0b01110000,
    //54 Six
    0b01000000,
    0b10000000,
    0b10000000,
    0b11110000,
    0b10001000,
    0b10001000,
    0b01110000,
    //55 Seven
    0b11111000,
    0b00001000,
    0b00010000,
    0b00100000,
    0b01000000,
    0b10000000,
    0b10000000,
    //56 Eight
    0b01110000,
    0b10001000,
    0b10001000,
    0b01110000,
    0b10001000,
    0b10001000,
    0b01110000,
    //57 Nine
    0b01110000,
    0b10001000,
    0b10001000,
    0b01111000,
    0b00001000,
    0b00001000,
    0b00010000,
    //58 :
    0b00000000,
    0b00000000,
    0b00100000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00100000,
    //59 ;
    0b00000000,
    0b00000000,
    0b00100000,
    0b00000000,
    0b00000000,
    0b00100000,
    0b00100000,
    //60 <
    0b00000000,
    0b00011000,
    0b01100000,
    0b10000000,
    0b01100000,
    0b00011000,
    0b00000000,
    //61 =
    0b00000000,
    0b00000000,
    0b01111000,
    0b00000000,
    0b01111000,
    0b00000000,
    0b00000000,
    //62 >
    0b00000000,
    0b11000000,
    0b00110000,
    0b00001000,
    0b00110000,
    0b11000000,
    0b00000000,
    //63 ?
    0b00110000,
    0b01001000,
    0b00010000,
    0b00100000,
    0b00100000,
    0b00000000,
    0b00100000,
    //64 @
    0b01110000,
    0b10001000,
    0b10111000,
    0b10101000,
    0b10010000,
    0b10001000,
    0b01110000,
    //65 A
    0b01110000,
    0b10001000,
    0b10001000,
    0b10001000,
    0b11111000,
    0b10001000,
    0b10001000,
    //B
    0b11110000,
    0b10001000,
    0b10001000,
    0b11110000,
    0b10001000,
    0b10001000,
    0b11110000,
    //C
    0b01110000,
    0b10001000,
    0b10000000,
    0b10000000,
    0b10000000,
    0b10001000,
    0b01110000,
    //D
    0b11110000,
    0b10001000,
    0b10001000,
    0b10001000,
    0b10001000,
    0b10001000,
    0b11110000,
    //E
    0b11111000,
    0b10000000,
    0b10000000,
    0b11111000,
    0b10000000,
    0b10000000,
    0b11111000,
    //F
    0b11111000,
    0b10000000,
    0b10000000,
    0b11111000,
    0b10000000,
    0b10000000,
    0b10000000,
    //G
    0b01110000,
    0b10001000,
    0b10000000,
    0b10011000,
    0b10001000,
    0b10001000,
    0b01110000,
    //H
    0b10001000,
    0b10001000,
    0b10001000,
    0b11111000,
    0b10001000,
    0b10001000,
    0b10001000,
    //I
    0b01110000,
    0b00100000,
    0b00100000,
    0b00100000,
    0b00100000,
    0b00100000,
    0b01110000,
    //J
    0b00111000,
    0b00010000,
    0b00010000,
    0b00010000,
    0b00010000,
    0b10010000,
    0b01100000,
    //K
    0b10001000,
    0b10010000,
    0b10100000,
    0b11000000,
    0b10100000,
    0b10010000,
    0b10001000,
    //L
    0b10000000,
    0b10000000,
    0b10000000,
    0b10000000,
    0b10000000,
    0b10000000,
    0b11111000,
    //M
    0b10001000,
    0b11011000,
    0b10101000,
    0b10101000,
    0b10001000,
    0b10001000,
    0b10001000,
    //N
    0b10001000,
    0b10001000,
    0b11001000,
    0b10101000,
    0b10011000,
    0b10001000,
    0b10001000,
    //O
    0b01110000,
    0b10001000,
    0b10001000,
    0b10001000,
    0b10001000,
    0b10001000,
    0b01110000,
    //P
    0b11110000,
    0b10001000,
    0b10001000,
    0b11110000,
    0b10000000,
    0b10000000,
    0b10000000,
    //Q
    0b01110000,
    0b10001000,
    0b10001000,
    0b10001000,
    0b10101000,
    0b10010000,
    0b01101000,
    //R
    0b11110000,
    0b10001000,
    0b10001000,
    0b11110000,
    0b10100000,
    0b10010000,
    0b10001000,
    //S
    0b01111000,
    0b10000000,
    0b10000000,
    0b01110000,
    0b00001000,
    0b00001000,
    0b11110000,
    //T
    0b11111000,
    0b00100000,
    0b00100000,
    0b00100000,
    0b00100000,
    0b00100000,
    0b00100000,
    //U
    0b10001000,
    0b10001000,
    0b10001000,
    0b10001000,
    0b10001000,
    0b10001000,
    0b01110000,
    //V
    0b10001000,
    0b10001000,
    0b10001000,
    0b10001000,
    0b10001000,
    0b01010000,
    0b00100000,
    //W
    0b10001000,
    0b10001000,
    0b10001000,
    0b10101000,
    0b10101000,
    0b10101000,
    0b01010000,
    //X
    0b10001000,
    0b10001000,
    0b01010000,
    0b00100000,
    0b01010000,
    0b10001000,
    0b10001000,
    //Y
    0b10001000,
    0b10001000,
    0b10001000,
    0b01010000,
    0b00100000,
    0b00100000,
    0b00100000,
    //Z
    0b11111000,
    0b00001000,
    0b00010000,
    0b00100000,
    0b01000000,
    0b10000000,
    0b11111000,
    //91 [
    0b11100000,
    0b10000000,
    0b10000000,
    0b10000000,
    0b10000000,
    0b10000000,
    0b11100000,
    //92 (backslash)
    0b00000000,
    0b10000000,
    0b01000000,
    0b00100000,
    0b00010000,
    0b00001000,
    0b00000000,
    //93 ]
    0b00111000,
    0b00001000,
    0b00001000,
    0b00001000,
    0b00001000,
    0b00001000,
    0b00111000,
    //94 ^
    0b00100000,
    0b01010000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //95 _
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b11111000,
    //96 `
    0b10000000,
    0b01000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    //97 a
    0b00000000,
    0b01100000,
    0b00010000,
    0b01110000,
    0b10010000,
    0b01100000,
    0b00000000,
    //98 b
    0b10000000,
    0b10000000,
    0b11100000,
    0b10010000,
    0b10010000,
    0b11100000,
    0b00000000,
    //99 c
    0b00000000,
    0b00000000,
    0b01110000,
    0b10000000,
    0b10000000,
    0b01110000,
    0b00000000,
    // 100 d
    0b00010000,
    0b00010000,
    0b01110000,
    0b10010000,
    0b10010000,
    0b01110000,
    0b00000000,
    //101 e
    0b00000000,
    0b01100000,
    0b10010000,
    0b11110000,
    0b10000000,
    0b01110000,
    0b00000000,
    //102 f
    0b00110000,
    0b01000000,
    0b11100000,
    0b01000000,
    0b01000000,
    0b01000000,
    0b00000000,
    //103 g
    0b00000000,
    0b01100000,
    0b10010000,
    0b01110000,
    0b00010000,
    0b00010000,
    0b01100000,
    //104 h
    0b10000000,
    0b10000000,
    0b11100000,
    0b10010000,
    0b10010000,
    0b10010000,
    0b00000000,
    //105 i
    0b00000000,
    0b00100000,
    0b00000000,
    0b00100000,
    0b00100000,
    0b00100000,
    0b00000000,
    //106 j
    0b00000000,
    0b00010000,
    0b00000000,
    0b00010000,
    0b00010000,
    0b00010000,
    0b01100000,
    //107 k
    0b10000000,
    0b10010000,
    0b10100000,
    0b11000000,
    0b10100000,
    0b10010000,
    0b00000000,
    //108 l
    0b00100000,
    0b00100000,
    0b00100000,
    0b00100000,
    0b00100000,
    0b00100000,
    0b00000000,
    //109 m
    0b00000000,
    0b00000000,
    0b01010000,
    0b10101000,
    0b10101000,
    0b10101000,
    0b00000000,
    //110 n
    0b00000000,
    0b00000000,
    0b01100000,
    0b10010000,
    0b10010000,
    0b10010000,
    0b00000000,
    //111 o
    0b00000000,
    0b00000000,
    0b01100000,
    0b10010000,
    0b10010000,
    0b01100000,
    0b00000000,
    //112 p
    0b00000000,
    0b00000000,
    0b01100000,
    0b10010000,
    0b11110000,
    0b10000000,
    0b10000000,
    //113 q
    0b00000000,
    0b00000000,
    0b01100000,
    0b10010000,
    0b11110000,
    0b00010000,
    0b00010000,
    //114 r
    0b00000000,
    0b00000000,
    0b10111000,
    0b01000000,
    0b01000000,
    0b01000000,
    0b00000000,
    //115 s
    0b00000000,
    0b00000000,
    0b01110000,
    0b01000000,
    0b00010000,
    0b01110000,
    0b00000000,
    //116 t
    0b01000000,
    0b01000000,
    0b11100000,
    0b01000000,
    0b01000000,
    0b01000000,
    0b00000000,
    // 117u
    0b00000000,
    0b00000000,
    0b10010000,
    0b10010000,
    0b10010000,
    0b01100000,
    0b00000000,
    //118 v
    0b00000000,
    0b00000000,
    0b10001000,
    0b10001000,
    0b01010000,
    0b00100000,
    0b00000000,
    //119 w
    0b00000000,
    0b00000000,
    0b10101000,
    0b10101000,
    0b01010000,
    0b01010000,
    0b00000000,
    //120 x
    0b00000000,
    0b00000000,
    0b10010000,
    0b01100000,
    0b01100000,
    0b10010000,
    0b00000000,
    //121 y
    0b00000000,
    0b00000000,
    0b10010000,
    0b10010000,
    0b01100000,
    0b01000000,
    0b10000000,
    //122 z
    0b00000000,
    0b00000000,
    0b11110000,
    0b00100000,
    0b01000000,
    0b11110000,
    0b00000000,
    //123 {
    0b00100000,
    0b01000000,
    0b01000000,
    0b10000000,
    0b01000000,
    0b01000000,
    0b00100000,
    //124 |
    0b00100000,
    0b00100000,
    0b00100000,
    0b00100000,
    0b00100000,
    0b00100000,
    0b00100000,
    //125 }
    0b00100000,
    0b00010000,
    0b00010000,
    0b00001000,
    0b00010000,    
    0b00010000,
    0b00100000,
    //126 ~
    0b00000000,
    0b00000000,
    0b01000000,
    0b10101000,
    0b00010000,
    0b00000000,
    0b00000000,
    //127 DEL
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000,
    0b00000000
};

unsigned int forward_matrix[2][72] = {
 // 0        1      2        3       4       5        6      7       8       9       10      11      12     13      14       15     16      17       18      19      20      21      22       23      24     25      26      27      28       29     30      31       32     33      34      35      36      37       38      39     40       41      42     43      44       45      46     47      48      49      50      51      52      53     54      55      56      57      58       59      60      61      62      63     64      65       66      67      68      69      70     71
   2231,    2214,    2180,    2130,    2063,    1981,    1884,    1772,    1647,    1509,    1360,    1200,    1031,    855,    672,    483,    292,    97,         0,    -292,    -483,    -672,    -855,    -1031,    -1200,    -1360,    -1509,    -1647,    -1772,    -1884,    -1981,    -2063,    -2130,    -2180,    -2214,    -2231,    -2231,    -2214,    -2180,    -2130,    -2063,    -1981,    -1884,    -1772,    -1647,    -1509,    -1360,    -1200,    -1031,    -855,    -672,    -483,    -292,    -97,    0,        292,    483,    672,    855,    1031,    1200,    1360,    1509,    1647,    1772,    1884,    1981,    2063,    2130,    2180,    2214,  2231,
   0,       -292,    -483,    -672,    -855,    -1031,    -1200,    -1360,    -1509,    -1647,    -1772,    -1884,    -1981,    -2063,    -2130,    -2180,    -2214,    -2231,    -2231,    -2214,    -2180,    -2130,    -2063,    -1981,    -1884,    -1772,    -1647,    -1509,    -1360,    -1200,    -1031,    -855,    -672,    -483,    -292,    -97,    0,      292,     483,    672,    855,    1031,    1200,    1360,    1509,    1647,    1772,    1884,    1981,    2063,    2130,    2180,    2214,    2231,    2231,    2214,    2180,    2130,    2063,    1981,    1884,    1772,    1647,    1509,    1360,    1200,    1031,    855,    672,    483,    292,    97};

unsigned int circle_matrix_30_in[2][72] = {
669,	664,	654,	639,	619,	594,	565,	532,	494,	453,	408,	360,	309,	256,	201,	145,	87,	29,	-29,	-87,	-145,	-201,	-256,	-309,	-360,	-408,	-453,	-494,	-532,	-565,	-594,	-619,	-639,	-654,	-664,	-669,	-669,	-664,	-654,	-639,	-619,	-594,	-565,	-532,	-494,	-453,	-408,	-360,	-309,	-256,	-201,	-145,	-87,	-29,	29,	87,	145,	201,	256,	309,	360,	408,	453,	494,	532,	565,	594,	619,	639,	654,	664,	669,																																																							
-29,	-87,	-145,	-201,	-256,	-309,	-360,	-408,	-453,	-494,	-532,	-565,	-594,	-619,	-639,	-654,	-664,	-669,	-669,	-664,	-654,	-639,	-619,	-594,	-565,	-532,	-494,	-453,	-408,	-360,	-309,	-256,	-201,	-145,	-87,	-29,	29,	87,	145,	201,	256,	309,	360,	408,	453,	494,	532,	565,	594,	619,	639,	654,	664,	669,	669,	664,	654,	639,	619,	594,	565,	532,	494,	453,	408,	360,	309,	256,	201,	145,	87,	29};
unsigned int circle_matrix_30_out[2][72] = {
//outside																																																																																																																														
1045,	1037,	1021,	998,	967,	928,	882,	830,	771,	707,	637,	562,	483,	400,	315,	226,	137,	46,	-46,	-137,	-226,	-315,	-400,	-483,	-562,	-637,	-707,	-771,	-830,	-882,	-928,	-967,	-998,	-1021,	-1037,	-1045,	-1045,	-1037,	-1021,	-998,	-967,	-928,	-882,	-830,	-771,	-707,	-637,	-562,	-483,	-400,	-315,	-226,	-137,	-46,	46,	137,	226,	315,	400,	483,	562,	637,	707,	771,	830,	882,	928,	967,	998,	1021,	1037,	1045,																																																							
-46,	-137,	-226,	-315,	-400,	-483,	-562,	-637,	-707,	-771,	-830,	-882,	-928,	-967,	-998,	-1021,	-1037,	-1045,	-1045,	-1037,	-1021,	-998,	-967,	-928,	-882,	-830,	-771,	-707,	-637,	-562,	-483,	-400,	-315,	-226,	-137,	-46,	46,	137,	226,	315,	400,	483,	562,	637,	707,	771,	830,	882,	928,	967,	998,	1021,	1037,	1045,	1045,	1037,	1021,	998,	967,	928,	882,	830,	771,	707,	637,	562,	483,	400,	315,	226,	137,	46};																																																							

unsigned int circle_matrix_40_in[2][72] = {
892,	886,	872,	852,	825,	792,	753,	709,	659,	604,	544,	480,	412,	342,	269,	193,	117,	39,	-39,	-117,	-193,	-269,	-342,	-412,	-480,	-544,	-604,	-659,	-709,	-753,	-792,	-825,	-852,	-872,	-886,	-892,	-892,	-886,	-872,	-852,	-825,	-792,	-753,	-709,	-659,	-604,	-544,	-480,	-412,	-342,	-269,	-193,	-117,	-39,	39,	117,	193,	269,	342,	412,	480,	544,	604,	659,	709,	753,	792,	825,	852,	872,	886,	892,																																																							
-39,	-117,	-193,	-269,	-342,	-412,	-480,	-544,	-604,	-659,	-709,	-753,	-792,	-825,	-852,	-872,	-886,	-892,	-892,	-886,	-872,	-852,	-825,	-792,	-753,	-709,	-659,	-604,	-544,	-480,	-412,	-342,	-269,	-193,	-117,	-39,	39,	117,	193,	269,	342,	412,	480,	544,	604,	659,	709,	753,	792,	825,	852,	872,	886,	892,	892,	886,	872,	852,	825,	792,	753,	709,	659,	604,	544,	480,	412,	342,	269,	193,	117,	39};																																																							
unsigned int circle_matrix_40_out[2][72] = {
1298,	1288,	1269,	1239,	1201,	1153,	1096,	1031,	958,	878,	791,	698,	600,	497,	391,	281,	170,	57,	-57,	-170,	-281,	-391,	-497,	-600,	-698,	-791,	-878,	-958,	-1031,	-1096,	-1153,	-1201,	-1239,	-1269,	-1288,	-1298,	-1298,	-1288,	-1269,	-1239,	-1201,	-1153,	-1096,	-1031,	-958,	-878,	-791,	-698,	-600,	-497,	-391,	-281,	-170,	-57,	57,	170,	281,	391,	497,	600,	698,	791,	878,	958,	1031,	1096,	1153,	1201,	1239,	1269,	1288,	1298,																																																							
-57,	-170,	-281,	-391,	-497,	-600,	-698,	-791,	-878,	-958,	-1031,	-1096,	-1153,	-1201,	-1239,	-1269,	-1288,	-1298,	-1298,	-1288,	-1269,	-1239,	-1201,	-1153,	-1096,	-1031,	-958,	-878,	-791,	-698,	-600,	-497,	-391,	-281,	-170,	-57,	57,	170,	281,	391,	497,	600,	698,	791,	878,	958,	1031,	1096,	1153,	1201,	1239,	1269,	1288,	1298,	1298,	1288,	1269,	1239,	1201,	1153,	1096,	1031,	958,	878,	791,	698,	600,	497,	391,	281,	170,	57};																																																							

unsigned int circle_matrix_60_in[2][72] = {
1339,	1329,	1308,	1278,	1238,	1189,	1130,	1063,	988,	905,	816,	720,	619,	513,	403,	290,	175,	58,	-58,	-175,	-290,	-403,	-513,	-619,	-720,	-816,	-905,	-988,	-1063,	-1130,	-1189,	-1238,	-1278,	-1308,	-1329,	-1339,	-1339,	-1329,	-1308,	-1278,	-1238,	-1189,	-1130,	-1063,	-988,	-905,	-816,	-720,	-619,	-513,	-403,	-290,	-175,	-58,	58,	175,	290,	403,	513,	619,	720,	816,	905,	988,	1063,	1130,	1189,	1238,	1278,	1308,	1329,	1339,																																																							
-58,	-175,	-290,	-403,	-513,	-619,	-720,	-816,	-905,	-988,	-1063,	-1130,	-1189,	-1238,	-1278,	-1308,	-1329,	-1339,	-1339,	-1329,	-1308,	-1278,	-1238,	-1189,	-1130,	-1063,	-988,	-905,	-816,	-720,	-619,	-513,	-403,	-290,	-175,	-58,	58,	175,	290,	403,	513,	619,	720,	816,	905,	988,	1063,	1130,	1189,	1238,	1278,	1308,	1329,	1339,	1339,	1329,	1308,	1278,	1238,	1189,	1130,	1063,	988,	905,	816,	720,	619,	513,	403,	290,	175,	58};																																																							
unsigned int circle_matrix_60_out[2][72] = {
1766,	1752,	1725,	1686,	1633,	1568,	1491,	1402,	1303,	1194,	1076,	950,	816,	676,	531,	383,	231,	77,	-77,	-231,	-383,	-531,	-676,	-816,	-950,	-1076,	-1194,	-1303,	-1402,	-1491,	-1568,	-1633,	-1686,	-1725,	-1752,	-1766,	-1766,	-1752,	-1725,	-1686,	-1633,	-1568,	-1491,	-1402,	-1303,	-1194,	-1076,	-950,	-816,	-676,	-531,	-383,	-231,	-77,	77,	231,	383,	531,	676,	816,	950,	1076,	1194,	1303,	1402,	1491,	1568,	1633,	1686,	1725,	1752,	1766,																																																							
-77,	-231,	-383,	-531,	-676,	-816,	-950,	-1076,	-1194,	-1303,	-1402,	-1491,	-1568,	-1633,	-1686,	-1725,	-1752,	-1766,	-1766,	-1752,	-1725,	-1686,	-1633,	-1568,	-1491,	-1402,	-1303,	-1194,	-1076,	-950,	-816,	-676,	-531,	-383,	-231,	-77,	77,	231,	383,	531,	676,	816,	950,	1076,	1194,	1303,	1402,	1491,	1568,	1633,	1686,	1725,	1752,	1766,	1766,	1752,	1725,	1686,	1633,	1568,	1491,	1402,	1303,	1194,	1076,	950,	816,	676,	531,	383,	231,	77};																																																							

unsigned int circle_matrix_80_in[2][72] = {
1785,	1771,	1744,	1704,	1651,	1585,	1507,	1417,	1317,	1207,	1088,	960,	825,	684,	537,	387,	233,	78,	-78,	-233,	-387,	-537,	-684,	-825,	-960,	-1088,	-1207,	-1317,	-1417,	-1507,	-1585,	-1651,	-1704,	-1744,	-1771,	-1785,	-1785,	-1771,	-1744,	-1704,	-1651,	-1585,	-1507,	-1417,	-1317,	-1207,	-1088,	-960,	-825,	-684,	-537,	-387,	-233,	-78,	78,	233,	387,	537,	684,	825,	960,	1088,	1207,	1317,	1417,	1507,	1585,	1651,	1704,	1744,	1771,	1785,																																																							
-78,	-233,	-387,	-537,	-684,	-825,	-960,	-1088,	-1207,	-1317,	-1417,	-1507,	-1585,	-1651,	-1704,	-1744,	-1771,	-1785,	-1785,	-1771,	-1744,	-1704,	-1651,	-1585,	-1507,	-1417,	-1317,	-1207,	-1088,	-960,	-825,	-684,	-537,	-387,	-233,	-78,	78,	233,	387,	537,	684,	825,	960,	1088,	1207,	1317,	1417,	1507,	1585,	1651,	1704,	1744,	1771,	1785,	1785,	1771,	1744,	1704,	1651,	1585,	1507,	1417,	1317,	1207,	1088,	960,	825,	684,	537,	387,	233,	78};																																																							
unsigned int circle_matrix_80_out[2][72] = {
2220,	2203,	2169,	2119,	2053,	1971,	1874,	1763,	1638,	1501,	1353,	1194,	1026,	850,	668,	481,	290,	97,	-97,	-290,	-481,	-668,	-850,	-1026,	-1194,	-1353,	-1501,	-1638,	-1763,	-1874,	-1971,	-2053,	-2119,	-2169,	-2203,	-2220,	-2220,	-2203,	-2169,	-2119,	-2053,	-1971,	-1874,	-1763,	-1638,	-1501,	-1353,	-1194,	-1026,	-850,	-668,	-481,	-290,	-97,	97,	290,	481,	668,	850,	1026,	1194,	1353,	1501,	1638,	1763,	1874,	1971,	2053,	2119,	2169,	2203,	2220,																																																							
-97,	-290,	-481,	-668,	-850,	-1026,	-1194,	-1353,	-1501,	-1638,	-1763,	-1874,	-1971,	-2053,	-2119,	-2169,	-2203,	-2220,	-2220,	-2203,	-2169,	-2119,	-2053,	-1971,	-1874,	-1763,	-1638,	-1501,	-1353,	-1194,	-1026,	-850,	-668,	-481,	-290,	-97,	97,	290,	481,	668,	850,	1026,	1194,	1353,	1501,	1638,	1763,	1874,	1971,	2053,	2119,	2169,	2203,	2220,	2220,	2203,	2169,	2119,	2053,	1971,	1874,	1763,	1638,	1501,	1353,	1194,	1026,	850,	668,	481,	290,	97};																																																						

int a[21] = {0, 3, 5, 8, 10, 13, 15, 18, 20, 23, 25, 28, 30, 33, 35, 38, 40, 43, 45, 48, 50};
int b[21] = {50, 50, 50, 49, 49, 48, 48, 47, 46, 45, 43, 42, 40, 38, 36, 33, 30, 26, 22, 16, 0};
int a1[17] = {0, 1, 3, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 17, 19, 20, 21};
int b1[17] = {21, 21, 21, 21, 21, 20, 20, 19, 18, 18, 17, 15, 14, 12, 10, 7, 0};


// put the MCU to sleep JUST before the CompA ISR goes off
ISR(TIMER1_COMPB_vect, ISR_NAKED)
{
    sei();
    sleep_cpu();
    reti();
}

//==================================
//This is the sync generator and raster generator. It MUST be entered from 
//sleep mode to get accurate timing of the sync pulses

ISR (TIMER1_COMPA_vect) {
    int x, screenStart ;
    //start the Horizontal sync pulse    
    PORTD = syncON;

    //update the current scanline number
    LineCount++;   
  
    //begin inverted (Vertical) synch after line 247
    if (LineCount==248) { 
        syncON = 0b00000001;
        syncOFF = 0;
      }
  
    //back to regular sync after line 250
    if (LineCount==251)    {
        syncON = 0;
        syncOFF = 0b00000001;
    }  
  
      //start new frame after line 262
    if (LineCount==263)
        LineCount = 1;
      
    //adjust to make 5 us pulses
    _delay_us(3);

    //end sync pulse
    PORTD = syncOFF;   

    if (LineCount < ScreenBot && LineCount >= ScreenTop) {
        //compute offset into screen array
        //screenindex = screen + ((LineCount - ScreenTop) << 4) + ((LineCount - ScreenTop) << 3);
        
        //compute offset into screen array
        //screenStart = ((LineCount - ScreenTop) << 4) + ((LineCount - ScreenTop) << 3) ;
        screenStart = (LineCount - ScreenTop) * bytes_per_line;
        //center image on screen
        _delay_us(7);
        //blast the data to the screen
        // We can load UDR twice because it is double-bufffered
        UDR0 = screen[screenStart] ;
        UCSR0B = _BV(TXEN0);
        UDR0 = screen[screenStart+1] ;
        for (x = 2; x < bytes_per_line; x++)
        begin
            while (!(UCSR0A & _BV(UDRE0))) ;
            UDR0 = screen[screenStart+x] ;
        end
        UCSR0B = 0 ;
    }         
}

//==================================
//plot one point 
//at x,y with color 1=white 0=black 2=invert 
void video_pt(char x, char y, char c) {
    //each line has 18 bytes
    //calculate i based upon this and x,y
    // the byte with the pixel in it
    //int i = (x >> 3) + ((int)y<<4) + ((int)y<<1);
    int i = (x >> 3) + (int)y * bytes_per_line ;

    if (c==1)
      screen[i] = screen[i] | pos[x & 7];
    else if (c==0)
      screen[i] = screen[i] & ~pos[x & 7];
    else
      screen[i] = screen[i] ^ pos[x & 7];
}

//==================================
//plot a line 
//at x1,y1 to x2,y2 with color 1=white 0=black 2=invert 
//NOTE: this function requires signed chars   
//Code is from David Rodgers,
//"Procedural Elements of Computer Graphics",1985
void video_line(char x1, char y1, char x2, char y2, char c) {
    int e;
    signed int dx,dy,j, temp;
    signed char s1,s2, xchange;
    signed int x,y;
        
    x = x1;
    y = y1;
    
    //take absolute value
    if (x2 < x1) {
        dx = x1 - x2;
        s1 = -1;
    }

    else if (x2 == x1) {
        dx = 0;
        s1 = 0;
    }

    else {
        dx = x2 - x1;
        s1 = 1;
    }

    if (y2 < y1) {
        dy = y1 - y2;
        s2 = -1;
    }

    else if (y2 == y1) {
        dy = 0;
        s2 = 0;
    }

    else {
        dy = y2 - y1;
        s2 = 1;
    }

    xchange = 0;   

    if (dy>dx) {
        temp = dx;
        dx = dy;
        dy = temp;
        xchange = 1;
    } 

    e = ((int)dy<<1) - dx;  
     
    for (j=0; j<=dx; j++) {
        video_pt(x,y,c);
         
        if (e>=0) {
            if (xchange==1) x = x + s1;
            else y = y + s2;
            e = e - ((int)dx<<1);
        }

        if (xchange==1) y = y + s2;
        else x = x + s1;

        e = e + ((int)dy<<1);
    }
}

//==================================
// put a big character on the screen
// c is index into bitmap
void video_putchar(char x, char y, char c) { 
    char i;
    char y_pos;
    uint8_t j;

    for (i=0;i<7;i++) {
        y_pos = y + i;

        j = pgm_read_byte(((uint32_t)(ascii)) + c*7 + i);

        video_pt(x,   y_pos, (j & 0x80)==0x80);  
        video_pt(x+1, y_pos, (j & 0x40)==0x40); 
        video_pt(x+2, y_pos, (j & 0x20)==0x20);
        video_pt(x+3, y_pos, (j & 0x10)==0x10);
        video_pt(x+4, y_pos, (j & 0x08)==0x08);
    }
}

//==================================
// put a string of big characters on the screen
void video_puts(char x, char y, char *str) {
    char i;
    for (i=0; str[i]!=0; i++) { 
        video_putchar(x,y,str[i]);
        x = x+6;    
    }
}
      
//==================================
// put a small character on the screen
// x-coord must be on divisible by 4 
// c is index into bitmap
void video_smallchar(char x, char y, char c) { 
    char mask;
    //int i=((int)x>>3) + ((int)y<<4) + ((int)y<<1);
    int i=((int)x>>3) + (int)y * bytes_per_line ;

    if (x == (x & 0xf8)) mask = 0x0f;     //f8
    else mask = 0xf0;
    
    uint8_t j = pgm_read_byte(((uint32_t)(smallbitmap)) + c*5);
    screen[i]    =    (screen[i] & mask) | (j & ~mask);

    j = pgm_read_byte(((uint32_t)(smallbitmap)) + c*5 + 1);
       screen[i+bytes_per_line] = (screen[i+bytes_per_line] & mask) | (j & ~mask);

    j = pgm_read_byte(((uint32_t)(smallbitmap)) + c*5 + 2);
    screen[i+bytes_per_line*2] = (screen[i+bytes_per_line*2] & mask) | (j & ~mask);
    
    j = pgm_read_byte(((uint32_t)(smallbitmap)) + c*5 + 3);
    screen[i+bytes_per_line*3] = (screen[i+bytes_per_line*3] & mask) | (j & ~mask);
       
    j = pgm_read_byte(((uint32_t)(smallbitmap)) + c*5 + 4);
    screen[i+bytes_per_line*4] = (screen[i+bytes_per_line*4] & mask) | (j & ~mask); 
}

//==================================
// put a string of small characters on the screen
// x-cood must be on divisible by 4 
void video_putsmalls(char x, char y, char *str) {
    char i;
    x = x & 0b11111100; //make it divisible by 4
    for (i = 0; str[i] != 0; i++) {
        if (str[i] >= 0x30 && str[i] <= 0x3a) 
            video_smallchar(x, y, str[i] - 0x30);

        else video_smallchar(x, y, str[i]-0x40+12);
        x += 4;    
    }
}

//==================================
//return the value of one point 
//at x,y with color 1=white 0=black 2=invert
char video_set(char x, char y) {
    //The following construction 
      //detects exactly one bit at the x,y location
    // int i = (x>>3) + ((int)y<<4) + ((int)y<<3);
    int i = (x>>3) + (int)y * bytes_per_line ;

    return (screen[i] & 1<<(7-(x & 0x7)));       
}

//==================================
//check a line at x1,y1 to x2,y2 
//and return with color 1=white 0=black 2=invert 
//Code is from Lu Liu
char video_line_set(char x1, char y1, char x2, char y2) {
    int e;
    signed int dx,dy,j, temp;
    signed char s1,s2, xchange;
    signed int x,y;
    char color = 0;
    int thresh = 0;
        
    x = x1;
    y = y1;
    
    //take absolute value
    if (x2 < x1) {
        dx = x1 - x2;
        s1 = -1;
    }

    else if (x2 == x1) {
        dx = 0;
        s1 = 0;
    }

    else {
        dx = x2 - x1;
        s1 = 1;
    }

    if (y2 < y1) {
        dy = y1 - y2;
        s2 = -1;
    }

    else if (y2 == y1) {
        dy = 0;
        s2 = 0;
    }

    else {
        dy = y2 - y1;
        s2 = 1;
    }

    xchange = 0;   

    if (dy>dx) {
        temp = dx;
        dx = dy;
        dy = temp;
        xchange = 1;
    } 

    e = ((int)dy<<1) - dx;  
     
    for (j=0; j<=dx; j++) {
        color = video_set(x, y);

        if (color != 0)    { 
           thresh ++;
        }

        if (thresh > 4)
           break;

        if (e>=0) {
             if (xchange==1) x = x + s1;
            else y = y + s2;
            e = e - ((int)dx<<1);
        }

        if (xchange==1) y = y + s2;
        else x = x + s1;

        e = e + ((int)dy<<1);
    }

   return (thresh>4);
}


//==================================
//plot a rectangle 
//at x0,y0 to x1,y1 with color 1=white 0=black 2=invert 
//NOTE: this function requires signed chars   
//Code is from Lu Liu
int video_rectangle(int x0, int y0, int x1, int y1, float length, int *coord, int plot, char c) {
   int x2,x3,y2,y3;
   float temp;
   float length_sq = length * length;
   int dx10 = x1 - x0;
   int dy10 = y1 - y0;
   int dx10_sq = dx10 * dx10;
   int dy10_sq = dy10 * dy10;
   int idx = 0;

   // calculate the coordinate of (x2,y2), (x3,y3)
   if (x0 == x1) {
      if (y0 < y1) {
         x2 = x0 - length;
         y2 = y0;
      } else {
         x2 = x0 + length;
         y2 = y0;
      }
   } else if (y0 == y1) {
      if (x0 < x1) {
         x2 = x0;
         y2 = y0 + length;
      } else {
         x2 = x0;
         y2 = y0 - length;
      }
   } else {

	  if (dy10 < -3 || dy10 > 3) {
		  temp = sqrt((length_sq * dy10_sq) / (dy10_sq + dx10_sq));

		  if (dy10 < 0)
			 x2 = temp + x0;
		  else
			 x2 = x0 - temp;

		  y2 = (-1)*(x2-x0)*dx10 / dy10 + y0;

	  } else if (dy10 >= -3 && dy10 <= 3) {
		  if (length > 40) {
			 if (dy10 < 0 && dx10 > 0) {
				idx = (-1)*dy10;
				x2 = x0 + a[idx];
				y2 = y0 + b[idx];
			 } else if (dy10 < 0 && dx10 < 0) {
				idx = (-1)*dy10;
				x2 = x0 + a[idx];
				y2 = y0 - b[idx];
			 } else if (dy10 > 0 && dx10 < 0) {
				idx = dy10;
				x2 = x0 - a[idx];
				y2 = y0 - b[idx];
			 } else if (dy10 > 0 && dx10 > 0) {
				idx = dy10;
				x2 = x0 - a[idx];
				y2 = y0 + b[idx];
			 }
		  } else {
			 if (dy10 < 0 && dx10 > 0) {
				idx = (-1)*dy10;
				x2 = x0 + a1[idx];
				y2 = y0 + b1[idx];
			 } else if (dy10 < 0 && dx10 < 0) {
				idx = (-1)*dy10;
				x2 = x0 + a1[idx];
				y2 = y0 - b1[idx];
			 } else if (dy10 > 0 && dx10 < 0) {
				idx = dy10;
				x2 = x0 - a1[idx];
				y2 = y0 - b1[idx];
			 } else if (dy10 > 0 && dx10 > 0) {
				idx = dy10;
				x2 = x0 - a1[idx];
				y2 = y0 + b1[idx];
			 }
		  }
	   }
   }

   x3 = x2 + dx10;
   y3 = y2 + dy10;

   // return coordinate
   coord[0] = x0;
   coord[1] = y0;
   coord[2] = x1;
   coord[3] = y1;
   coord[4] = x2;
   coord[5] = y2;
   coord[6] = x3;
   coord[7] = y3;

   if (x0 < 0 || x0 > 160 ||
       x1 < 0 || x1 > 160 ||
       x2 < 0 || x2 > 160 ||
       x3 < 0 || x3 > 160 ||
       y0 < 0 || y0 > 200 ||
       y1 < 0 || y1 > 200 ||
       y2 < 0 || y2 > 200 ||
       y3 < 0 || y3 > 200
   ) {
/*
      fprintf(stdout, "rectangle_plot:\n");
      fprintf(stdout, "%d, %d\n", x0, y0);
      fprintf(stdout, "%d, %d\n", x1, y1);
      fprintf(stdout, "%d, %d\n", x2, y2);
      fprintf(stdout, "%d, %d\n", x3, y3);
*/
      return 1;
   } else {

      // plot the rectangle if instructed to do so
      if (plot == 1) {
         video_line(x0,y0,x1,y1,c);
         video_line(x0,y0,x2,y2,c);
         video_line(x2,y2,x3,y3,c);
         video_line(x1,y1,x3,y3,c);
      }

      return 0;
   }
}

//==================================
//plot a rectangle with length as fix
//at x0,y0 to x1,y1 with color 1=white 0=black 2=invert 
//NOTE: this function requires signed chars   
//Code is from Lu Liu
void video_rectangle_fix(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, unsigned int length, unsigned int *coord) {
   unsigned int x2,x3,y2,y3;
   float temp;
   unsigned int length_angle = 0;

   // calculate the coordinate of (x2,y2), (x3,y3)
   x2 = x0;
   x3 = x1;
   y2 = y0;
   y3 = y1;

   // if going forward/backward
   if (car_angle >= -5 && car_angle <= 5) {
      if (reverse == 0 && car_gas != 0) {
         x2 = x0 + multfix(forward_matrix[1][angle_state], length);
         y2 = y0 + multfix(forward_matrix[0][angle_state], length);
         x3 = x1 + multfix(forward_matrix[1][angle_state], length);
         y3 = y1 + multfix(forward_matrix[0][angle_state], length);
      } else if (reverse == 1 && car_gas != 0) {
         x2 = x0 - multfix(forward_matrix[1][angle_state], length);
         y2 = y0 - multfix(forward_matrix[0][angle_state], length);
         x3 = x1 - multfix(forward_matrix[1][angle_state], length);
         y3 = y1 - multfix(forward_matrix[0][angle_state], length);
      }
   } else if (car_gas != 0) {

      //temp = 1.0/limit;
      //length_angle = float2fix(temp);

      if (car_gas != 0) {
	  	switch (car_gas)
	  	begin
	  	   case 1 : length_angle = fix_1_30; break;
	  	   case 2 : length_angle = fix_2_30; break;
	  	   case 3 : length_angle = fix_3_30; break;
	  	end
      }

      // if wheel angle is:
      if (car_angle > 5 && car_angle < 15) {
         if (reverse == 0) {
            x2 = x0 + multfix(circle_matrix_80_out[1][angle_state], length_angle);
            y2 = y0 + multfix(circle_matrix_80_out[0][angle_state], length_angle);
            x3 = x1 + multfix(circle_matrix_80_in[1][angle_state], length_angle);
            y3 = y1 + multfix(circle_matrix_80_in[0][angle_state], length_angle);
         } else {
            x2 = x0 - multfix(circle_matrix_80_out[1][angle_state], length_angle);
            y2 = y0 - multfix(circle_matrix_80_out[0][angle_state], length_angle);
            x3 = x1 - multfix(circle_matrix_80_in[1][angle_state], length_angle);
            y3 = y1 - multfix(circle_matrix_80_in[0][angle_state], length_angle);
         }
      } else if (car_angle >= 15 && car_angle < 25) {
         if (reverse == 0) {
            x2 = x0 + multfix(circle_matrix_60_out[1][angle_state], length_angle);
            y2 = y0 + multfix(circle_matrix_60_out[0][angle_state], length_angle);
            x3 = x1 + multfix(circle_matrix_60_in[1][angle_state], length_angle);
            y3 = y1 + multfix(circle_matrix_60_in[0][angle_state], length_angle);
         } else {
            x2 = x0 - multfix(circle_matrix_60_out[1][angle_state], length_angle);
            y2 = y0 - multfix(circle_matrix_60_out[0][angle_state], length_angle);
            x3 = x1 - multfix(circle_matrix_60_in[1][angle_state], length_angle);
            y3 = y1 - multfix(circle_matrix_60_in[0][angle_state], length_angle);
         }
      } else if (car_angle >= 25 && car_angle < 35) {
         if (reverse == 0) {
            x2 = x0 + multfix(circle_matrix_40_out[1][angle_state], length_angle);
            y2 = y0 + multfix(circle_matrix_40_out[0][angle_state], length_angle);
            x3 = x1 + multfix(circle_matrix_40_in[1][angle_state], length_angle);
            y3 = y1 + multfix(circle_matrix_40_in[0][angle_state], length_angle);
         } else {
            x2 = x0 - multfix(circle_matrix_40_out[1][angle_state], length_angle);
            y2 = y0 - multfix(circle_matrix_40_out[0][angle_state], length_angle);
            x3 = x1 - multfix(circle_matrix_40_in[1][angle_state], length_angle);
            y3 = y1 - multfix(circle_matrix_40_in[0][angle_state], length_angle);
         }
      } else if (car_angle >= 35 && car_angle <= 45) {
         if (reverse == 0) {
            x2 = x0 + multfix(circle_matrix_30_out[1][angle_state], length_angle);
            y2 = y0 + multfix(circle_matrix_30_out[0][angle_state], length_angle);
            x3 = x1 + multfix(circle_matrix_30_in[1][angle_state], length_angle);
            y3 = y1 + multfix(circle_matrix_30_in[0][angle_state], length_angle);
         } else {
            x2 = x0 - multfix(circle_matrix_30_out[1][angle_state], length_angle);
            y2 = y0 - multfix(circle_matrix_30_out[0][angle_state], length_angle);
            x3 = x1 - multfix(circle_matrix_30_in[1][angle_state], length_angle);
            y3 = y1 - multfix(circle_matrix_30_in[0][angle_state], length_angle);
         }

      // the other direction:
      } else if (car_angle < -5 && car_angle > -15) {
         if (reverse == 0) {
            x2 = x0 - multfix(circle_matrix_80_in[1][angle_state_2], length_angle);
            y2 = y0 - multfix(circle_matrix_80_in[0][angle_state_2], length_angle);
            x3 = x1 - multfix(circle_matrix_80_out[1][angle_state_2], length_angle);
            y3 = y1 - multfix(circle_matrix_80_out[0][angle_state_2], length_angle);
         } else {
            x2 = x0 + multfix(circle_matrix_80_in[1][angle_state_2], length_angle);
            y2 = y0 + multfix(circle_matrix_80_in[0][angle_state_2], length_angle);
            x3 = x1 + multfix(circle_matrix_80_out[1][angle_state_2], length_angle);
            y3 = y1 + multfix(circle_matrix_80_out[0][angle_state_2], length_angle);
         }
      } else if (car_angle <= -15 && car_angle > -25) {
         if (reverse == 0) {
            x2 = x0 - multfix(circle_matrix_60_in[1][angle_state_2], length_angle);
            y2 = y0 - multfix(circle_matrix_60_in[0][angle_state_2], length_angle);
            x3 = x1 - multfix(circle_matrix_60_out[1][angle_state_2], length_angle);
            y3 = y1 - multfix(circle_matrix_60_out[0][angle_state_2], length_angle);
         } else {
            x2 = x0 + multfix(circle_matrix_60_in[1][angle_state_2], length_angle);
            y2 = y0 + multfix(circle_matrix_60_in[0][angle_state_2], length_angle);
            x3 = x1 + multfix(circle_matrix_60_out[1][angle_state_2], length_angle);
            y3 = y1 + multfix(circle_matrix_60_out[0][angle_state_2], length_angle);
         }
      } else if (car_angle <= -25 && car_angle > -35) {
         if (reverse == 0) {
            x2 = x0 - multfix(circle_matrix_40_in[1][angle_state_2], length_angle);
            y2 = y0 - multfix(circle_matrix_40_in[0][angle_state_2], length_angle);
            x3 = x1 - multfix(circle_matrix_40_out[1][angle_state_2], length_angle);
            y3 = y1 - multfix(circle_matrix_40_out[0][angle_state_2], length_angle);
         } else {
            x2 = x0 + multfix(circle_matrix_40_in[1][angle_state_2], length_angle);
            y2 = y0 + multfix(circle_matrix_40_in[0][angle_state_2], length_angle);
            x3 = x1 + multfix(circle_matrix_40_out[1][angle_state_2], length_angle);
            y3 = y1 + multfix(circle_matrix_40_out[0][angle_state_2], length_angle);
         }
      } else if (car_angle <= -35 && car_angle >= -45) {
         if (reverse == 0) {
            x2 = x0 - multfix(circle_matrix_30_in[1][angle_state_2], length_angle);
            y2 = y0 - multfix(circle_matrix_30_in[0][angle_state_2], length_angle);
            x3 = x1 - multfix(circle_matrix_30_out[1][angle_state_2], length_angle);
            y3 = y1 - multfix(circle_matrix_30_out[0][angle_state_2], length_angle);
         } else {
            x2 = x0 + multfix(circle_matrix_30_in[1][angle_state_2], length_angle);
            y2 = y0 + multfix(circle_matrix_30_in[0][angle_state_2], length_angle);
            x3 = x1 + multfix(circle_matrix_30_out[1][angle_state_2], length_angle);
            y3 = y1 + multfix(circle_matrix_30_out[0][angle_state_2], length_angle);
         }
      }
   }

   // return coordinate
   coord[0] = x0;
   coord[1] = y0;
   coord[2] = x1;
   coord[3] = y1;
   coord[4] = x2;
   coord[5] = y2;
   coord[6] = x3;
   coord[7] = y3;
}

//==================================
//plot a car
//at x0,y0 to x1,y1 with color 1=white 0=black 2=invert 
//NOTE: this function requires signed chars   
//Code is from Lu Liu
int video_car(int x0, int y0, int x1, int y1, int plot, char c) {
   int x2,y2;
   int x3,y3;
   int x4,y4;
   int x5,y5;
   int x6,y6;
   int x7,y7;
   int x8,y8;
   int x9,y9;
   int x10,y10;
   int x11,y11;
   int x12,y12;
   int x13,y13;
   int x14,y14;
   int x15,y15;
   int x16,y16;
   int x17,y17;
   int x18,y18;
   int x19,y19;
   int x20,y20;
   int x21,y21;
   int vec_1_dx = x1-x0;
   int vec_1_dy = y1-y0;
   int vec_2_dx;
   int vec_2_dy;
   //float length_vec_1 = sqrt(vec_1_dx*vec_1_dx + vec_1_dy*vec_1_dy);
   //float length_vec_2 = 2.5*length_vec_1;
   int length_vec_1 = car_width;
   int length_vec_2 = car_length;
   int coord_int[8];
   int error;

   // calculate all the points
   x2 = x0 + (int)(0.3*vec_1_dx);
   y2 = y0 + (int)(0.3*vec_1_dy);
   x3 = x0 + (int)(0.7*vec_1_dx);
   y3 = y0 + (int)(0.7*vec_1_dy);
   error = video_rectangle(x0,y0,x1,y1,length_vec_2,&coord_int[0],0,0);
   if (error == 1) {
      return 1;
   }
   x4 = coord_int[4];
   y4 = coord_int[5];
   x5 = coord_int[6];
   y5 = coord_int[7];
   vec_2_dx = x4 - x0;
   vec_2_dy = y4 - y0;
   x6 = x0 + (int)(0.25*vec_2_dx);
   y6 = y0 + (int)(0.25*vec_2_dy);
   x7 = x1 + (int)(0.25*vec_2_dx);
   y7 = y1 + (int)(0.25*vec_2_dy);
   x8 = x0 + (int)(0.03125*vec_2_dx);
   y8 = y0 + (int)(0.03125*vec_2_dy);
   x9 = x1 + (int)(0.03125*vec_2_dx);
   y9 = y1 + (int)(0.03125*vec_2_dy);
   x10 = x0 + (int)(0.45*vec_2_dx);
   y10 = y0 + (int)(0.45*vec_2_dy);
   x11 = x1 + (int)(0.45*vec_2_dx);
   y11 = y1 + (int)(0.45*vec_2_dy);
   x12 = x10 + (int)(0.1*vec_1_dx);
   y12 = y10 + (int)(0.1*vec_1_dy);
   x13 = x11 - (int)(0.1*vec_1_dx);
   y13 = y11 - (int)(0.1*vec_1_dy);
   error = video_rectangle(x12,y12,x13,y13,0.425*length_vec_2,&coord_int[0],0,0);
   if (error == 1) {
      return 1;
   }
   x14 = coord_int[4];
   y14 = coord_int[5];
   x15 = coord_int[6];
   y15 = coord_int[7];
   x16 = x4 + (int)(0.4*vec_1_dx);
   y16 = y4 + (int)(0.4*vec_1_dy);
   x17 = x5 - (int)(0.4*vec_1_dx);
   y17 = y5 - (int)(0.4*vec_1_dy);
   x18 = x4 - (int)(0.03125*vec_2_dx);
   y18 = y4 - (int)(0.03125*vec_2_dy);
   x19 = x5 - (int)(0.03125*vec_2_dx);
   y19 = y5 - (int)(0.03125*vec_2_dy);
   x20 = x10 - (int)(0.1*vec_1_dx);
   y20 = y10 - (int)(0.1*vec_1_dy);
   x21 = x11 + (int)(0.1*vec_1_dx);
   y21 = y11 + (int)(0.1*vec_1_dy);

/*
   coord[0] = x0;
   coord[1] = y0;
   coord[2] = x1;
   coord[3] = y1;
   coord[4] = x2;
   coord[5] = y2;
   coord[6] = x3;
   coord[7] = y3;
   coord[8] = x4;
   coord[9] = y4;
   coord[10] = x5;
   coord[11] = y5;
   coord[12] = x6;
   coord[13] = y6;
   coord[14] = x7;
   coord[15] = y7;
   coord[16] = x8;
   coord[17] = y8;
   coord[18] = x9;
   coord[19] = y9;
   coord[20] = x10;
   coord[21] = y10;
   coord[22] = x11;
   coord[23] = y11;
   coord[24] = x12;
   coord[25] = y12;
   coord[26] = x13;
   coord[27] = y13;
   coord[28] = x14;
   coord[29] = y14;
   coord[30] = x15;
   coord[31] = y15;
   coord[32] = x16;
   coord[33] = y16;
   coord[34] = x17;
   coord[35] = y17;
   coord[36] = x18;
   coord[37] = y18;
   coord[38] = x19;
   coord[39] = y19;
   coord[40] = x20;
   coord[41] = y20;
   coord[42] = x21;
   coord[43] = y21;
*/

   // safe check:
   if (x0 < 0 || x0 > 160 ||
       x1 < 0 || x1 > 160 ||
       x2 < 0 || x2 > 160 ||
       x3 < 0 || x3 > 160 ||
       x4 < 0 || x4 > 160 ||
       x5 < 0 || x5 > 160 ||
       x6 < 0 || x6 > 160 || 
       x7 < 0 || x7 > 160 ||
       x8 < 0 || x8 > 160 ||
       x9 < 0 || x9 > 160 ||
       x10 < 0 || x10 > 160 ||
       x11 < 0 || x11 > 160 ||
       x12 < 0 || x12 > 160 ||
       x13 < 0 || x13 > 160 ||
       x14 < 0 || x14 > 160 ||
       x15 < 0 || x15 > 160 ||
       x16 < 0 || x16 > 160 ||
       x17 < 0 || x17 > 160 ||
       x18 < 0 || x18 > 160 ||
       x19 < 0 || x19 > 160 ||
       x20 < 0 || x20 > 160 ||
       x21 < 0 || x21 > 160 ||
       y0 < 0 || y0 > 200 ||
       y1 < 0 || y1 > 200 ||
       y2 < 0 || y2 > 200 ||
       y3 < 0 || y3 > 200 ||
       y4 < 0 || y4 > 200 ||
       y5 < 0 || y5 > 200 ||
       y6 < 0 || y6 > 200 || 
       y7 < 0 || y7 > 200 ||
       y8 < 0 || y8 > 200 ||
       y9 < 0 || y9 > 200 ||
       y10 < 0 || y10 > 200 ||
       y11 < 0 || y11 > 200 ||
       y12 < 0 || y12 > 200 ||
       y13 < 0 || y13 > 200 ||
       y14 < 0 || y14 > 200 ||
       y15 < 0 || y15 > 200 ||
       y16 < 0 || y16 > 200 ||
       y17 < 0 || y17 > 200 ||
       y18 < 0 || y18 > 200 ||
       y19 < 0 || y19 > 200 ||
       y20 < 0 || y20 > 200 ||
       y21 < 0 || y21 > 200
   ) {
/*      fprintf(stdout, "car_plot:\n");
      fprintf(stdout, "length = %f\n", length_vec_2);
      fprintf(stdout, "0  %d, %d\n", x0, y0);
      fprintf(stdout, "1  %d, %d\n", x1, y1);
      fprintf(stdout, "2  %d, %d\n", x2, y2);
      fprintf(stdout, "3  %d, %d\n", x3, y3);   

      fprintf(stdout, "4  %d, %d\n", x4, y4);
      fprintf(stdout, "5  %d, %d\n", x5, y5);
      fprintf(stdout, "6  %d, %d\n", x6, y6);
      fprintf(stdout, "7  %d, %d\n", x7, y7);   

      fprintf(stdout, "8  %d, %d\n", x8, y8);
      fprintf(stdout, "9  %d, %d\n", x9, y9);
      fprintf(stdout, "10 %d, %d\n", x10, y10);
      fprintf(stdout, "11 %d, %d\n", x11, y11);   

      fprintf(stdout, "12 %d, %d\n", x12, y12);
      fprintf(stdout, "13 %d, %d\n", x13, y13);
      fprintf(stdout, "14 %d, %d\n", x14, y14);
      fprintf(stdout, "15 %d, %d\n", x15, y15);   

      fprintf(stdout, "16 %d, %d\n", x16, y16);
      fprintf(stdout, "17 %d, %d\n", x17, y17);
      fprintf(stdout, "18 %d, %d\n", x18, y18);
      fprintf(stdout, "19 %d, %d\n", x19, y19);   

      fprintf(stdout, "20 %d, %d\n", x20, y20);
      fprintf(stdout, "21 %d, %d\n", x21, y21);
*/      return 1;
   } else {
      error = 0;
   }

   if (plot == 1) {

      // now plot them
      video_line(x2,y2,x3,y3,c);
      video_line(x0,y0,x4,y4,c);
      video_line(x1,y1,x5,y5,c);
      video_line(x16,y16,x17,y17,c);
      video_line(x12,y12,x13,y13,c);
      video_line(x12,y12,x14,y14,c);
      video_line(x14,y14,x15,y15,c);
      video_line(x13,y13,x15,y15,c);
      video_line(x2,y2,x8,y8,c);
      video_line(x3,y3,x9,y9,c);
      video_line(x6,y6,x7,y7,c);
      video_line(x6,y6,x12,y12,c);
      video_line(x7,y7,x13,y13,c);
      video_line(x14,y14,x4,y4,c);
      video_line(x15,y15,x5,y5,c);
      video_line(x16,y16,x18,y18,c);
      video_line(x17,y17,x19,y19,c);
      video_line(x6,y6,x20,y20,c);
      video_line(x7,y7,x21,y21,c);
   }

   return error;
}

//==================================
//drive the current car forward by 1 unit
//the current position of the car is 
//at x0,y0 to x1,y1 with color 1=white 0=black 2=invert
//speed: 0: stop, 1: slow moving: 2: faster moving, 3: fastest
//NOTE: this function requires signed chars   
//Code is from Lu Liu
int start_car(unsigned int *x0, unsigned int *y0, unsigned int *x1, unsigned int *y1, int speed) {
   int error;
   unsigned int length;
   unsigned int coord[8];
   int x0_int, x1_int, y0_int, y1_int;
   int x0_int2, x1_int2, y0_int2, y1_int2;

   x0_int = fix2int(*x0)+128;
   y0_int = fix2int(*y0)+128;
   x1_int = fix2int(*x1)+128;
   y1_int = fix2int(*y1)+128;

   switch (speed)
   begin
      case 0 : length = 0; break;
      case 1 : length = vcar_unit[0]; break;
      case 2 : length = vcar_unit[1]; break;
      case 3 : length = vcar_unit[2]; break;
      default : length = 0;
   end

   // this calculates the new coordinates of the car
   video_rectangle_fix(*x0, *y0, *x1, *y1, length, &coord[0]);
   x0_int2 = fix2int(coord[4])+128;
   y0_int2 = fix2int(coord[5])+128;
   x1_int2 = fix2int(coord[6])+128;
   y1_int2 = fix2int(coord[7])+128;

   // check if the new position is valid:
   error = video_car(x0_int2,y0_int2,x1_int2,y1_int2,0,0);

   // if valid
   if (error == 0) {

      // erase the car in current position
      error = video_car(x0_int,y0_int,x1_int,y1_int,1,0);

      // redraw the car in new position
      error = video_car(x0_int2,y0_int2,x1_int2,y1_int2,1,2);

      // update the current position
      *x0 = coord[4];
      *y0 = coord[5];
      *x1 = coord[6];
      *y1 = coord[7];
   }

   return error;
}

//==================================
//plot parking lot type 0
//Code is from Lu Liu
void plot_parking_lot_0(void) {
   int error;   

   // plot parking lot lines:
   video_line(100, 0, 160, 0, 1);
   video_line(100, 40, 160, 40, 1);
   video_line(100, 80, 160, 80, 1);
   video_line(100, 120, 160, 120, 1);
   video_line(100, 160, 160, 160, 1);
   video_line(100, 199, 160, 199, 1);
   video_line(159, 0, 159, 199, 1);

   // plot cars:
   error = video_car(105,30,105,10,1,1);
   error = video_car(95,148,100,126,1,1);
   error = video_car(158,168,158,193,1,1);
}


//==================================
//plot parking lot type 0
//Code is from Lu Liu
void plot_parking_lot_1(void) {
   int error;   

   // plot parking lot lines:
   video_line(79, 0, 79, 20, 1);
   video_line(79, 40, 79, 60, 1);
   video_line(79, 80, 79, 100, 1);
   video_line(79, 120, 79, 140, 1);
   video_line(79, 160, 79, 180, 1);
   video_line(5, 0, 5, 199, 1);
   video_line(5, 0, 30, 0, 1);
   video_line(5, 60, 30, 60, 1);
   video_line(5, 140, 10, 140, 1);
   video_line(5, 199, 30, 199, 1);
   video_line(154, 0, 130, 0, 1);
   video_line(154, 70, 130, 70, 1);
   video_line(154, 140, 130, 140, 1);
   video_line(154, 199, 130, 199, 1);
   video_line(154, 0, 154, 199, 1);
   video_line(159, 0, 159, 199, 1);
   video_line(130, 140, 154, 199, 1);
   video_line(154, 140, 130, 199, 1);


   // plot cars:
   error = video_car(30,53,10,53,1,1);
   error = video_car(28,189,8,189,1,1);
   error = video_car(130,5,150,5,1,1);
   error = video_car(128,73,150,76,1,1);
}

//=====================================
// adjust idx and idx_2 (angle_state)
// according to current car coordinate
void adjust_angle_state(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, int *idx, int *idx_2) {
   int x0_int = fix2int(x0) + 128;
   int y0_int = fix2int(y0) + 128;
   int x1_int = fix2int(x1) + 128;
   int y1_int = fix2int(y1) + 128;
   float temp;

   if (x0_int == x1_int) {
      if (y0_int < y1_int) {
         *idx = 54;
         *idx_2 = 18;
      } else if (y0_int > y1_int) {
         *idx = 18;
         *idx_2 = 54;
      }
   } else if (y0_int == y1_int) {
      if (x0_int < x1_int) {
         *idx = 36;
         *idx_2 = 0;
      } else if (x0_int > x1_int) {
         *idx = 0;
         *idx_2 = 36;
      }   
   } else {
      temp = (1.0*(y1_int - y0_int)) / (x1_int - x0_int);

      // first quadrant
      if (x1_int > x0_int && y1_int > y0_int) {

         if ( temp < 0.043661) {
            *idx = 36;
            *idx_2 = 0;
         } else if ( temp > 0.043661 && temp < 0.131652) {
            *idx = 37;
            *idx_2 = 1;
         } else if ( temp > 0.131652 && temp < 0.221695) {
            *idx = 38;
            *idx_2 = 2;
         } else if ( temp > 0.221695 && temp < 0.315299) {
            *idx = 39;
            *idx_2 = 3;
         } else if ( temp > 0.315299 && temp < 0.414214) {
            *idx = 40;
            *idx_2 = 4;
         } else if ( temp > 0.414214 && temp < 0.520567) {
            *idx = 41;
            *idx_2 = 5;
         } else if ( temp > 0.520567 && temp < 0.637070) {
            *idx = 42;
            *idx_2 = 6;
         } else if ( temp > 0.637070 && temp < 0.767327) {
            *idx = 43;
            *idx_2 = 7;
         } else if ( temp > 0.767327 && temp < 0.916331) {
            *idx = 44;
            *idx_2 = 8;
         } else if ( temp > 0.916331 && temp < 1.091309) {
            *idx = 45;
            *idx_2 = 9;
         } else if ( temp > 1.091309 && temp < 1.303225) {
            *idx = 46;
            *idx_2 = 10;
         } else if ( temp > 1.303225 && temp < 1.569686) {
            *idx = 47;
            *idx_2 = 11;
         } else if ( temp > 1.569686 && temp < 1.920982) {
            *idx = 48;
            *idx_2 = 12;
         } else if ( temp > 1.920982 && temp < 2.414214) {
            *idx = 49;
            *idx_2 = 13;
         } else if ( temp > 2.414214 && temp < 3.171595) {
            *idx = 50;
            *idx_2 = 14;
         } else if ( temp > 3.171595 && temp < 4.510709) {
            *idx = 51;
            *idx_2 = 15;
         } else if ( temp > 4.510709 && temp < 7.595754) {
            *idx = 52;
            *idx_2 = 16;
         } else if ( temp > 7.595754 && temp < 22.903766) {
            *idx = 53;
            *idx_2 = 17;
         } else if (temp > 22.903766) {
            *idx = 54;
            *idx_2 = 18;
         }

      // second quadrant
      } else if (x1_int < x0_int && y1_int > y0_int) {

         if ( temp < -22.903766) {
            *idx = 54;
            *idx_2 = 18;
         } else if ( temp > -22.903766 && temp < -7.595754) {
            *idx = 55;
            *idx_2 = 19;
         } else if ( temp > -7.595754 && temp < -4.510709) {
            *idx = 56;
            *idx_2 = 20;
         } else if ( temp > -4.510709 && temp < -3.171595) {
            *idx = 57;
            *idx_2 = 21;
         } else if ( temp > -3.171595 && temp < -2.414214) {
            *idx = 58;
            *idx_2 = 22;
         } else if ( temp > -2.414214 && temp < -1.920982) {
            *idx = 59;
            *idx_2 = 23;
         } else if ( temp > -1.920982 && temp < -1.569686) {
            *idx = 60;
            *idx_2 = 24;
         } else if ( temp > -1.569686 && temp < -1.303225) {
            *idx = 61;
            *idx_2 = 25;
         } else if ( temp > -1.303225 && temp < -1.091309) {
            *idx = 62;
            *idx_2 = 26;
         } else if ( temp > -1.091309 && temp < -0.916331) {
            *idx = 63;
            *idx_2 = 27;
         } else if ( temp > -0.916331 && temp < -0.767327) {
            *idx = 64;
            *idx_2 = 28;
         } else if ( temp > -0.767327 && temp < -0.637070) {
            *idx = 65;
            *idx_2 = 29;
         } else if ( temp > -0.637070 && temp < -0.520567) {
            *idx = 66;
            *idx_2 = 30;
         } else if ( temp > -0.520567 && temp < -0.414214) {
            *idx = 67;
            *idx_2 = 31;
         } else if ( temp > -0.414214 && temp < -0.315299) {
            *idx = 68;
            *idx_2 = 32;
         } else if ( temp > -0.315299 && temp < -0.221695) {
            *idx = 69;
            *idx_2 = 33;
         } else if ( temp > -0.221695 && temp < -0.131652) {
            *idx = 70;
            *idx_2 = 34;
         } else if ( temp > -0.131652 && temp < -0.043661) {
            *idx = 71;
            *idx_2 = 35;
         } else if ( temp > -0.043661) {
            *idx = 0;
            *idx_2 = 36;
         }

      // third quadrant
      } else if (x1_int < x0_int && y1_int < y0_int) {

         if ( temp < 0.043661) {
            *idx = 0;
            *idx_2 = 36;
         } else if ( temp > 0.043661 && temp < 0.131652) {
            *idx = 1;
            *idx_2 = 37;
         } else if ( temp > 0.131652 && temp < 0.221695) {
            *idx = 2;
            *idx_2 = 38;
         } else if ( temp > 0.221695 && temp < 0.315299) {
            *idx = 3;
            *idx_2 = 39;
         } else if ( temp > 0.315299 && temp < 0.414214) {
            *idx = 4;
            *idx_2 = 40;
         } else if ( temp > 0.414214 && temp < 0.520567) {
            *idx = 5;
            *idx_2 = 41;
         } else if ( temp > 0.520567 && temp < 0.637070) {
            *idx = 6;
            *idx_2 = 42;
         } else if ( temp > 0.637070 && temp < 0.767327) {
            *idx = 7;
            *idx_2 = 43;
         } else if ( temp > 0.767327 && temp < 0.916331) {
            *idx = 8;
            *idx_2 = 44;
         } else if ( temp > 0.916331 && temp < 1.091309) {
            *idx = 9;
            *idx_2 = 45;
         } else if ( temp > 1.091309 && temp < 1.303225) {
            *idx = 10;
            *idx_2 = 46;
         } else if ( temp > 1.303225 && temp < 1.569686) {
            *idx = 11;
            *idx_2 = 47;
         } else if ( temp > 1.569686 && temp < 1.920982) {
            *idx = 12;
            *idx_2 = 48;
         } else if ( temp > 1.920982 && temp < 2.414214) {
            *idx = 13;
            *idx_2 = 49;
         } else if ( temp > 2.414214 && temp < 3.171595) {
            *idx = 14;
            *idx_2 = 50;
         } else if ( temp > 3.171595 && temp < 4.510709) {
            *idx = 15;
            *idx_2 = 51;
         } else if ( temp > 4.510709 && temp < 7.595754) {
            *idx = 16;
            *idx_2 = 52;
         } else if ( temp > 7.595754 && temp < 22.903766) {
            *idx = 17;
            *idx_2 = 53;
         } else if ( temp > 22.903766) {
            *idx = 18;
            *idx_2 = 54;
         }

      // fourth quadrant
      } else if (x1_int > x0_int && y1_int < y0_int) {

         if ( temp < -22.903766) {
            *idx = 18;
            *idx_2 = 54;
         } else if ( temp > -22.903766 && temp < -7.595754) {
            *idx = 19;
            *idx_2 = 55;
         } else if ( temp > -7.595754 && temp < -4.510709) {
            *idx = 20;
            *idx_2 = 56;
         } else if ( temp > -4.510709 && temp < -3.171595) {
            *idx = 21;
            *idx_2 = 57;
         } else if ( temp > -3.171595 && temp < -2.414214) {
            *idx = 22;
            *idx_2 = 58;
         } else if ( temp > -2.414214 && temp < -1.920982) {
            *idx = 23;
            *idx_2 = 59;
         } else if ( temp > -1.920982 && temp < -1.569686) {
            *idx = 24;
            *idx_2 = 60;
         } else if ( temp > -1.569686 && temp < -1.303225) {
            *idx = 25;
            *idx_2 = 61;
         } else if ( temp > -1.303225 && temp < -1.091309) {
            *idx = 26;
            *idx_2 = 62;
         } else if ( temp > -1.091309 && temp < -0.916331) {
            *idx = 27;
            *idx_2 = 63;
         } else if ( temp > -0.916331 && temp < -0.767327) {
            *idx = 28;
            *idx_2 = 64;
         } else if ( temp > -0.767327 && temp < -0.637070) {
            *idx = 29;
            *idx_2 = 65;
         } else if ( temp > -0.637070 && temp < -0.520567) {
            *idx = 30;
            *idx_2 = 66;
         } else if ( temp > -0.520567 && temp < -0.414214) {
            *idx = 31;
            *idx_2 = 67;
         } else if ( temp > -0.414214 && temp < -0.315299) {
            *idx = 32;
            *idx_2 = 68;
         } else if ( temp > -0.315299 && temp < -0.221695) {
            *idx = 33;
            *idx_2 = 69;
         } else if ( temp > -0.221695 && temp < -0.131652) {
            *idx = 34;
            *idx_2 = 70;
         } else if ( temp > -0.131652 && temp < -0.043661) {
            *idx = 35;
            *idx_2 = 71;
         } else if ( temp > -0.043661) {
            *idx = 36;
            *idx_2 = 0;
         }
      }
   }
}

//==================================
//check if a car is fully plotted
//return 1 if any point on the car is not plotted
//Code is from Lu Liu
int check_car(int x0, int y0, int x1, int y1) {
   int x2,y2;
   int x3,y3;
   int x4,y4;
   int x5,y5;
   int x6,y6;
   int x7,y7;
   int x8,y8;
   int x9,y9;
   int x10,y10;
   int x11,y11;
   int x12,y12;
   int x13,y13;
   int x14,y14;
   int x15,y15;
   int x16,y16;
   int x17,y17;
   int x18,y18;
   int x19,y19;
   int x20,y20;
   int x21,y21;
   int vec_1_dx = x1-x0;
   int vec_1_dy = y1-y0;
   int vec_2_dx;
   int vec_2_dy;
   //float length_vec_1 = sqrt(vec_1_dx*vec_1_dx + vec_1_dy*vec_1_dy);
   //float length_vec_2 = 2.5*length_vec_1;
   int length_vec_1 = car_width;
   int length_vec_2 = car_length;
   int coord_int[8];
   int error;

   // calculate all the points
   x2 = x0 + (int)(0.3*vec_1_dx);
   y2 = y0 + (int)(0.3*vec_1_dy);
   x3 = x0 + (int)(0.7*vec_1_dx);
   y3 = y0 + (int)(0.7*vec_1_dy);
   error = video_rectangle(x0,y0,x1,y1,length_vec_2,&coord_int[0],0,0);
   if (error == 1) {
      return 1;
   }
   x4 = coord_int[4];
   y4 = coord_int[5];
   x5 = coord_int[6];
   y5 = coord_int[7];
   vec_2_dx = x4 - x0;
   vec_2_dy = y4 - y0;
   x6 = x0 + (int)(0.25*vec_2_dx);
   y6 = y0 + (int)(0.25*vec_2_dy);
   x7 = x1 + (int)(0.25*vec_2_dx);
   y7 = y1 + (int)(0.25*vec_2_dy);
   x8 = x0 + (int)(0.03125*vec_2_dx);
   y8 = y0 + (int)(0.03125*vec_2_dy);
   x9 = x1 + (int)(0.03125*vec_2_dx);
   y9 = y1 + (int)(0.03125*vec_2_dy);
   x10 = x0 + (int)(0.45*vec_2_dx);
   y10 = y0 + (int)(0.45*vec_2_dy);
   x11 = x1 + (int)(0.45*vec_2_dx);
   y11 = y1 + (int)(0.45*vec_2_dy);
   x12 = x10 + (int)(0.1*vec_1_dx);
   y12 = y10 + (int)(0.1*vec_1_dy);
   x13 = x11 - (int)(0.1*vec_1_dx);
   y13 = y11 - (int)(0.1*vec_1_dy);
   error = video_rectangle(x12,y12,x13,y13,0.425*length_vec_2,&coord_int[0],0,0);
   if (error == 1) {
      return 1;
   }
   x14 = coord_int[4];
   y14 = coord_int[5];
   x15 = coord_int[6];
   y15 = coord_int[7];
   x16 = x4 + (int)(0.4*vec_1_dx);
   y16 = y4 + (int)(0.4*vec_1_dy);
   x17 = x5 - (int)(0.4*vec_1_dx);
   y17 = y5 - (int)(0.4*vec_1_dy);
   x18 = x4 - (int)(0.03125*vec_2_dx);
   y18 = y4 - (int)(0.03125*vec_2_dy);
   x19 = x5 - (int)(0.03125*vec_2_dx);
   y19 = y5 - (int)(0.03125*vec_2_dy);
   x20 = x10 - (int)(0.1*vec_1_dx);
   y20 = y10 - (int)(0.1*vec_1_dy);
   x21 = x11 + (int)(0.1*vec_1_dx);
   y21 = y11 + (int)(0.1*vec_1_dy);

   // safe check:
   if (x0 > 0 && x0 < 160 &&
       x1 > 0 && x1 < 160 &&
       x2 > 0 && x2 < 160 &&
       x3 > 0 && x3 < 160 &&
       x4 > 0 && x4 < 160 &&
       x5 > 0 && x5 < 160 &&
       x6 > 0 && x6 < 160 && 
       x7 > 0 && x7 < 160 &&
       x8 > 0 && x8 < 160 &&
       x9 > 0 && x9 < 160 &&
       x10 > 0 && x10 < 160 &&
       x11 > 0 && x11 < 160 &&
       x12 > 0 && x12 < 160 &&
       x13 > 0 && x13 < 160 &&
       x14 > 0 && x14 < 160 &&
       x15 > 0 && x15 < 160 &&
       x16 > 0 && x16 < 160 &&
       x17 > 0 && x17 < 160 &&
       x18 > 0 && x18 < 160 &&
       x19 > 0 && x19 < 160 &&
       x20 > 0 && x20 < 160 &&
       x21 > 0 && x21 < 160 &&
       y0 > 0 && y0 < 200 &&
       y1 > 0 && y1 < 200 &&
       y2 > 0 && y2 < 200 &&
       y3 > 0 && y3 < 200 &&
       y4 > 0 && y4 < 200 &&
       y5 > 0 && y5 < 200 &&
       y6 > 0 && y6 < 200 && 
       y7 > 0 && y7 < 200 &&
       y8 > 0 && y8 < 200 &&
       y9 > 0 && y9 < 200 &&
       y10 > 0 && y10 < 200 &&
       y11 > 0 && y11 < 200 &&
       y12 > 0 && y12 < 200 &&
       y13 > 0 && y13 < 200 &&
       y14 > 0 && y14 < 200 &&
       y15 > 0 && y15 < 200 &&
       y16 > 0 && y16 < 200 &&
       y17 > 0 && y17 < 200 &&
       y18 > 0 && y18 < 200 &&
       y19 > 0 && y19 < 200 &&
       y20 > 0 && y20 < 200 &&
       y21 > 0 && y21 < 200
   ) {

      // now xor and check all the lines
      video_line(x2,y2,x3,y3,2);
      error = error | video_line_set(x2,y2,x3,y3);
      video_line(x0,y0,x4,y4,2);
      error = error | video_line_set(x0,y0,x4,y4);
      video_line(x1,y1,x5,y5,2);
      error = error | video_line_set(x1,y1,x5,y5);
      video_line(x16,y16,x17,y17,2);
      error = error | video_line_set(x16,y16,x17,y17);
      video_line(x12,y12,x13,y13,2);
      error = error | video_line_set(x12,y12,x13,y13);
      video_line(x12,y12,x14,y14,2);
      error = error | video_line_set(x12,y12,x14,y14);
      video_line(x14,y14,x15,y15,2);
      error = error | video_line_set(x14,y14,x15,y15);
      video_line(x13,y13,x15,y15,2);
      error = error | video_line_set(x13,y13,x15,y15);
      video_line(x2,y2,x8,y8,2);
      error = error | video_line_set(x2,y2,x8,y8);
      video_line(x3,y3,x9,y9,2);
      error = error | video_line_set(x3,y3,x9,y9);
      video_line(x6,y6,x7,y7,2);
      error = error | video_line_set(x6,y6,x7,y7);
      video_line(x6,y6,x12,y12,2);
      error = error | video_line_set(x6,y6,x12,y12);
      video_line(x7,y7,x13,y13,2);
      error = error | video_line_set(x7,y7,x13,y13);
      video_line(x14,y14,x4,y4,2);
      error = error | video_line_set(x14,y14,x4,y4);
      video_line(x15,y15,x5,y5,2);
      error = error | video_line_set(x15,y15,x5,y5);
      video_line(x16,y16,x18,y18,2);
      error = error | video_line_set(x16,y16,x18,y18);
      video_line(x17,y17,x19,y19,2);
      error = error | video_line_set(x17,y17,x19,y19);
      video_line(x6,y6,x20,y20,2);
      error = error | video_line_set(x6,y6,x20,y20);
      video_line(x7,y7,x21,y21,2);
      error = error | video_line_set(x7,y7,x21,y21);

      if (error == 0) {

		 // erase those points
		 video_line(x2,y2,x3,y3,0);
		 video_line(x0,y0,x4,y4,0);
		 video_line(x1,y1,x5,y5,0);
		 video_line(x16,y16,x17,y17,0);
		 video_line(x12,y12,x13,y13,0);
		 video_line(x12,y12,x14,y14,0);
		 video_line(x14,y14,x15,y15,0);
		 video_line(x13,y13,x15,y15,0);
		 video_line(x2,y2,x8,y8,0);
		 video_line(x3,y3,x9,y9,0);
		 video_line(x6,y6,x7,y7,0);
		 video_line(x6,y6,x12,y12,0);
		 video_line(x7,y7,x13,y13,0);
		 video_line(x14,y14,x4,y4,0);
		 video_line(x15,y15,x5,y5,0);
		 video_line(x16,y16,x18,y18,0);
		 video_line(x17,y17,x19,y19,0);
		 video_line(x6,y6,x20,y20,0);
		 video_line(x7,y7,x21,y21,0);
      }
   }

   return error;
}

// this function checks if the car is parked correctly between two parking lines
// returns 0 if passed
// note: the lines must be parallel to x/y axis
int check_parking (unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, int x0_line, int y0_line, int x1_line, int y1_line) {
   int x0_int = fix2int(x0)+128;
   int y0_int = fix2int(y0)+128;
   int x1_int = fix2int(x1)+128;
   int y1_int = fix2int(y1)+128;
   int error = 0;
   int coord[8];

   // find all car four points
   video_rectangle(x0_int, y0_int, x1_int, y1_int, car_length, &coord[0], 0, 0);

   // check if all the four points on the car is within the two parking line
   if (x0_line < x1_line) {
      error = error | (x0_line > coord[0]);
      error = error | (x0_line > coord[2]);
      error = error | (x0_line > coord[4]);
      error = error | (x0_line > coord[6]);
      error = error | (x1_line < coord[0]);
      error = error | (x1_line < coord[2]);
      error = error | (x1_line < coord[4]);
      error = error | (x1_line < coord[6]);
   } else {
      error = error | (x1_line > coord[0]);
      error = error | (x1_line > coord[2]);
      error = error | (x1_line > coord[4]);
      error = error | (x1_line > coord[6]);
      error = error | (x0_line < coord[0]);
      error = error | (x0_line < coord[2]);
      error = error | (x0_line < coord[4]);
      error = error | (x0_line < coord[6]);
   }
   if (y0_line < y1_line) {
      error = error | (y0_line > coord[1]);
      error = error | (y0_line > coord[3]);
      error = error | (y0_line > coord[5]);
      error = error | (y0_line > coord[7]);
      error = error | (y1_line < coord[1]);
      error = error | (y1_line < coord[3]);
      error = error | (y1_line < coord[5]);
      error = error | (y1_line < coord[7]);
   } else {
      error = error | (y1_line > coord[1]);
      error = error | (y1_line > coord[3]);
      error = error | (y1_line > coord[5]);
      error = error | (y1_line > coord[7]);
      error = error | (y0_line < coord[1]);
      error = error | (y0_line < coord[3]);
      error = error | (y0_line < coord[5]);
      error = error | (y0_line < coord[7]);
   }

   return error;
}

// this function checks car parking result in parking lot 0
// returns 0 if passed
int check_parking_lot_0 (void) {
    int error = 0;
    int temp = 0;

    // check if all the cars in the lot are intact
    error = error | check_car(105,30,105,10);
    error = error | check_car(95,148,100,126);
    error = error | check_car(158,168,158,193);

    // check if the car is parked at the correct place
    temp = check_parking (x0_fix, y0_fix, x1_fix, y1_fix, 100, 40, 160, 80);
    temp = temp & check_parking (x0_fix, y0_fix, x1_fix, y1_fix, 100, 80, 160, 120);

	temp = temp << 1;
    return error | temp;
}

// this function checks car parking result in parking lot 1
// returns 0 if passed
int check_parking_lot_1 (void) {
    int error = 0;
    int temp = 0;

    // check if all the cars in the lot are intact
    error = error | check_car(30,53,10,53);
    error = error | check_car(28,189,8,189);
    error = error | check_car(130,5,150,5);
    error = error | check_car(128,73,150,76);

    // check if the car is parked at the correct place
    temp = check_parking (x0_fix, y0_fix, x1_fix, y1_fix, 5, 60, 35, 140);

	temp = temp << 1;
    return error | temp;
}

// this function checks if a line is crossed by another rectangle
// returns 1 if it is
// note: the line must be parallel to x/y axis
int check_line (int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3, int line_x0, int line_y0, int line_x1, int line_y1) {
   int cross = 0;
   int less = 0;
   int greater = 0;

   // vertical line
   if (line_x0 == line_x1) {
      less = less | (x0 < line_x0);
      less = less | (x1 < line_x0);
      less = less | (x2 < line_x0);
      less = less | (x3 < line_x0);
      greater = greater | (x0 > line_x0);
      greater = greater | (x1 > line_x0);
      greater = greater | (x2 > line_x0);
      greater = greater | (x3 > line_x0);

      if (less & greater) {
         if (line_y0 < line_y1) {
            cross = cross | ((line_y0 < y0) & (line_y1 > y0));
            cross = cross | ((line_y0 < y1) & (line_y1 > y1));
            cross = cross | ((line_y0 < y2) & (line_y1 > y2));
            cross = cross | ((line_y0 < y3) & (line_y1 > y3));
         } else {
            cross = cross | ((line_y1 < y0) & (line_y0 > y0));
            cross = cross | ((line_y1 < y1) & (line_y0 > y1));
            cross = cross | ((line_y1 < y2) & (line_y0 > y2));
            cross = cross | ((line_y1 < y3) & (line_y0 > y3));
         }
      }

   // horizontal line
   } else {
      less = less | (y0 < line_y0);
      less = less | (y1 < line_y0);
      less = less | (y2 < line_y0);
      less = less | (y3 < line_y0);
      greater = greater | (y0 > line_y0);
      greater = greater | (y1 > line_y0);
      greater = greater | (y2 > line_y0);
      greater = greater | (y3 > line_y0);

      if (less & greater) {
         if (line_x0 < line_x1) {
            cross = cross | ((line_x0 < x0) & (line_x1 > x0));
            cross = cross | ((line_x0 < x1) & (line_x1 > x1));
            cross = cross | ((line_x0 < x2) & (line_x1 > x2));
            cross = cross | ((line_x0 < x3) & (line_x1 > x3));
         } else {
            cross = cross | ((line_x1 < x0) & (line_x0 > x0));
            cross = cross | ((line_x1 < x1) & (line_x0 > x1));
            cross = cross | ((line_x1 < x2) & (line_x0 > x2));
            cross = cross | ((line_x1 < x3) & (line_x0 > x3));
         }
      }
   }
   return cross;
}

// this function checks if a line in parking lot 0 is crossed by the car and save the status
// if it is crossed, set the idx
// if it is not crossed but previously crossed, redraw the line
// if it is not crossed and not previously crossed, do nothing
void redraw_a_line_parking_lot_0 (int *cross, int *prev_cross) {
   int x0_int = fix2int(x0_fix)+128;
   int y0_int = fix2int(y0_fix)+128;
   int x1_int = fix2int(x1_fix)+128;
   int y1_int = fix2int(y1_fix)+128;
   int coord[8];

   // store the previous status
   prev_cross[0] = cross[0];
   prev_cross[1] = cross[1];
   prev_cross[2] = cross[2];

   // find all car four points
   video_rectangle(x0_int, y0_int, x1_int, y1_int, car_length, &coord[0], 0, 0);

   // check if each line in this parking lot is crossed by the car
   cross[0] = check_line(coord[0], coord[1], coord[2], coord[3], coord[4], coord[5], coord[6], coord[7], 100, 40, 160, 40);
   cross[1] = check_line(coord[0], coord[1], coord[2], coord[3], coord[4], coord[5], coord[6], coord[7], 100, 80, 160, 80);
   cross[2] = check_line(coord[0], coord[1], coord[2], coord[3], coord[4], coord[5], coord[6], coord[7], 100, 120, 160, 120);

   // redraw the line if the line is previously crossed but not currently crossed
   if (cross[0] == 0 && prev_cross[0] == 1)
	  video_line(100, 40, 160, 40, 1);
   if (cross[1] == 0 && prev_cross[1] == 1)
	  video_line(100, 80, 160, 80, 1);
   if (cross[2] == 0 && prev_cross[2] == 1)
	  video_line(100, 120, 160, 120, 1);
}

// this function checks if a line in parking lot 1 is crossed by the car and save the status
// if it is crossed, set the idx
// if it is not crossed but previously crossed, redraw the line
// if it is not crossed and not previously crossed, do nothing
void redraw_a_line_parking_lot_1 (int *cross, int *prev_cross) {
   int x0_int = fix2int(x0_fix)+128;
   int y0_int = fix2int(y0_fix)+128;
   int x1_int = fix2int(x1_fix)+128;
   int y1_int = fix2int(y1_fix)+128;
   int coord[8];

   // store the previous status
   prev_cross[0] = cross[0];
   prev_cross[1] = cross[1];
   prev_cross[2] = cross[2];
   prev_cross[3] = cross[3];
   prev_cross[4] = cross[4];
   prev_cross[5] = cross[5];
   prev_cross[6] = cross[6];

   // find all car four points
   video_rectangle(x0_int, y0_int, x1_int, y1_int, car_length, &coord[0], 0, 0);

   // check if each line in this parking lot is crossed by the car
   cross[0] = check_line(coord[0], coord[1], coord[2], coord[3], coord[4], coord[5], coord[6], coord[7], 79, 0, 79, 20);
   cross[1] = check_line(coord[0], coord[1], coord[2], coord[3], coord[4], coord[5], coord[6], coord[7], 79, 40, 79, 60);
   cross[2] = check_line(coord[0], coord[1], coord[2], coord[3], coord[4], coord[5], coord[6], coord[7], 79, 80, 79, 100);
   cross[3] = check_line(coord[0], coord[1], coord[2], coord[3], coord[4], coord[5], coord[6], coord[7], 79, 120, 79, 140);
   cross[4] = check_line(coord[0], coord[1], coord[2], coord[3], coord[4], coord[5], coord[6], coord[7], 79, 160, 79, 180);
   cross[5] = check_line(coord[0], coord[1], coord[2], coord[3], coord[4], coord[5], coord[6], coord[7], 5, 60, 30, 60);
   cross[6] = check_line(coord[0], coord[1], coord[2], coord[3], coord[4], coord[5], coord[6], coord[7], 5, 60, 5, 140);

   // redraw the line if the line is previously crossed but not currently crossed
   if (cross[0] == 0 && prev_cross[0] == 1)
	  video_line(79, 0, 79, 20, 1);
   if (cross[1] == 0 && prev_cross[1] == 1)
	  video_line(79, 40, 79, 60, 1);
   if (cross[2] == 0 && prev_cross[2] == 1)
	  video_line(79, 80, 79, 100, 1);
   if (cross[3] == 0 && prev_cross[3] == 1)
	  video_line(79, 120, 79, 140, 1);
   if (cross[4] == 0 && prev_cross[4] == 1)
	  video_line(79, 160, 79, 180, 1);
   if (cross[5] == 0 && prev_cross[5] == 1)
	  video_line(5, 60, 30, 60, 1);
   if (cross[6] == 0 && prev_cross[6] == 1)
	  video_line(5, 60, 5, 140, 1);
}

// this function erase the whole screen
void erase_screen (void) {
   int line = 0;
   for (line = 0; line <= 160; line ++)
      video_line(line,0,line,199,0);
}

// this function adjust the car size to its origin
// NOTE: for this project, this function shall only be called when the car is parallel to y-axis
void adjust_car_size(unsigned int *x0, unsigned int *y0, unsigned int *x1, unsigned int *y1) {
   int x0_int = (fix2int(*x0)+128);
   int x1_int = (fix2int(*x1)+128);
   int y0_int = (fix2int(*y0)+128);
   int y1_int = (fix2int(*y1)+128);
   int dx = x1_int - x0_int;
   unsigned int new_x;

   // erase the current car
   video_car(x0_int, y0_int, x1_int, y1_int, 1, 0);

   if (dx > 0) {
	  new_x = x0_int + 20;
	  if (new_x >= 160) {
		 x0_int = x1_int - 20;
		 *x0 = int2fix(x0_int-128);
	  } else {
	     x1_int = new_x;
		 *x1 = int2fix(x1_int-128);
	  }
   } else {
	  new_x = x1_int + 20;
	  if (new_x >= 160) {
		 x0_int = new_x;
		 *x0 = int2fix(x0_int-128);
	  } else {
	     x1_int = x0_int - 20;
		 *x1 = int2fix(x1_int-128);
	  }
   }

   // redraw the new car
   video_car(x0_int, y0_int, x1_int, y1_int, 1, 2);
}

//=== animation stuff ==================================================
char str0[] = "0";
char str1[] = "1";
char str_print[6];
int temp0;
int temp1;
char color;
int prev_lines[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int lines[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int stage;
char check_str0[] = "You Hit A Car!";
char check_str1[] = "You Parked Out of Bound!";
int coord[8];
int adjust_size = 1;
///////////////

//==================================         
// set up the ports and timers
int main() {
   int error = 0;

   //*********************************************************
   // INITIALIZATION - begin
   //*********************************************************
   // interrupts enabled
   TCCR1B = _BV(WGM12) | _BV(CS10);
   OCR1A = LINE_TIME;    // time for one NTSC line
   OCR1B = SLEEP_TIME;    // time to go to sleep
   TIMSK1 = _BV(OCIE1B) | _BV(OCIE1A);

   //init ports
   DDRD = 0x03;        //video out

   // USART in MSPIM mode, transmitter enabled, frequency fosc/4
   UCSR0B = _BV(TXEN0);
   UCSR0C = _BV(UMSEL01) | _BV(UMSEL00);
   UBRR0 = 1 ;

   // ADC
   //init the A to D converter 
   //channel zero/ left adj /INTERNAL Aref=Vcc
   ADMUX = (1<<ADLAR) | (1<<REFS0) ;  
    
   //enable ADC and set prescaler to 1/128*16MHz=125,000
   //and clear interupt enable
   //and start a conversion
   ADCSRA = (1<<ADEN) | (1<<ADSC) + 7 ; 
   //To get the initial setting
   while (ADCSRA & (1<<ADSC) );
   //get the sample  
   Ain1 = ADCH;

   //start another conversion
   ADMUX = (1<<ADLAR) | (1<<REFS0) + 2;  
   ADCSRA |= (1<<ADSC) ; 
   while (ADCSRA & (1<<ADSC) );
   //get the sample  
   Ain2 = ADCH;
   
   last_abs_wheel_angle = abs_wheel_angle(Ain1,Ain2, last_abs_wheel_angle); 
   last_wheel_angle =last_abs_wheel_angle; 

   // set the reverse
   PORTB = 0x94;
   PORTD = 0x20;

   //init the UART -- uart_init() is in uart.c
   uart_init();

   stdout = stdin = stderr = &uart_str;
   fprintf(stdout, "hello\n");

   //initialize synch constants 
   LineCount = 1;

   syncON = 0b00000000;
   syncOFF = 0b00000001;

   //side lines
   #define width screen_width-1
   #define height screen_height-1

   // Set up single video line timing
   sei();
   set_sleep_mode(SLEEP_MODE_IDLE);
   sleep_enable();

   //*********************************************************
   // INITIALIZATION - end
   //*********************************************************

   //*********************************************************
   // VIDEO GAME INITIALIZATION- begin
   //*********************************************************
RESTART:

   // print 'speed' at the end of the screen
   str_print[0] = 'S';
   str_print[1] = 'P';
   str_print[2] = 'E';
   str_print[3] = 'E';
   str_print[4] = 'D';
   str_print[5] = ':';
   video_putsmalls(4, 190, str_print);
    
   // initialize car parameter
   car_gas = 0;
   car_angle = 0;
   reverse = 0;

   // select stage
   stage = ~PIND & 0x20;

   // draw parking lot and car init position
   if (stage) {
     plot_parking_lot_1();
     x0_fix = int2fix(60-128);
     y0_fix = int2fix(60-128);
     x1_fix = int2fix(40-128);
     y1_fix = int2fix(60-128);

     angle_state = 0;
     angle_state_2 = 36;
   } else {
     plot_parking_lot_0();
     x0_fix = int2fix(10-128);
     y0_fix = int2fix(5-128);
     x1_fix = int2fix(30-128);
     y1_fix = int2fix(5-128);

     angle_state = 36;
     angle_state_2 = 0;
   }

   //*********************************************************
   // VIDEO GAME INITIALIZATION- end
   //*********************************************************

   // The following loop executes the if-block
   // when the screen refresh is done
   // then does all of the frame-end processing
   while(1) {

     if (LineCount == ScreenBot) { 

        //*********************************************************
        // SENSOR READINGS- begin
        //*********************************************************

        // acc0
        ADMUX = (1<<ADLAR) | (1<<REFS0) ;  
        //start another conversion
        ADCSRA |= (1<<ADSC) ; 
        //get the sample  
        while(ADCSRA & (1<<ADSC) )
        Ain1 = ADCH;
        ADCSRA |= (1<<ADSC) ;
        while(ADCSRA & (1<<ADSC) )
        Ain1 = ADCH;
        ADCSRA |= (1<<ADSC) ;
        while(ADCSRA & (1<<ADSC) )
        Ain1 = ADCH;

        // brake pedal
        ADMUX = (1<<ADLAR) | (1<<REFS0)+7 ;  
        //start another conversion
        ADCSRA |= (1<<ADSC) ; 
        while (ADCSRA & (1<<ADSC) );
        //get the sample  
        Ain3 = ADCH;  
        ADCSRA |= (1<<ADSC) ;      
        while (ADCSRA & (1<<ADSC) );
        //get the sample  
        Ain3 = ADCH;

        // gear pedal
        ADMUX = (1<<ADLAR) | (1<<REFS0)+5 ;  
        //start another conversion
        ADCSRA |= (1<<ADSC) ; 
        while (ADCSRA & (1<<ADSC) );
        //get the sample  
        Ain4 = ADCH;  
        ADCSRA |= (1<<ADSC) ;      
        while (ADCSRA & (1<<ADSC) );
        //get the sample  
        Ain4 = ADCH;

        // speed
        car_gas = potentiometer(Ain4);
        if (Ain3 > 150) {
           car_gas = 0;
        }

        // forward/backward
        if (~PINB & 0x04) {
           reverse = 0;
        } else {
           reverse = 1;
        }

        // acc1
        //start another conversion
        ADMUX = (1<<ADLAR) | (1<<REFS0) + 2;  
        ADCSRA |= (1<<ADSC) ; 
        while (ADCSRA & (1<<ADSC) );
        //get the sample  
        Ain2 = ADCH;
        ADCSRA |= (1<<ADSC) ;
        while (ADCSRA & (1<<ADSC) );
        //get the sample  
        Ain2 = ADCH;         
    
        // steering wheel angle
        wheel_angle = relative_wheel_angle(last_abs_wheel_angle,Ain1,Ain2);
        last_abs_wheel_angle=abs_wheel_angle(Ain1,Ain2,last_abs_wheel_angle); 
        last_wheel_angle = last_wheel_angle + wheel_angle;
        if (last_wheel_angle<-450) last_wheel_angle = -450;
        if (last_wheel_angle>450)  last_wheel_angle = 450;
        car_angle = car_angle_compute(last_wheel_angle);

        //*********************************************************
        // SENSOR READINGS- end
        //*********************************************************

        //*********************************************************
        // CAR POSITION UPDATE- begin
        //*********************************************************
        error = start_car(&x0_fix, &y0_fix, &x1_fix, &y1_fix, car_gas);
        //*********************************************************
        // CAR POSITION UPDATE- end
        //*********************************************************

        //*********************************************************
        // CAR VARIABLE UPDATE- begin
        //*********************************************************
        limit = 30;
        if (car_gas != 0) {
			switch (car_gas)
			begin
			   case 1 : limit = 45; break;
			   case 2 : limit = 23; break;
			   case 3 : limit = 15; break;
			end
        }

        //*********************************************************
        // CAR VARIABLE UPDATE- end
        //*********************************************************

        //*********************************************************
        // CAR STATUS DISPLAY- begin
        //*********************************************************
        // DISPLAY:
        // speed
        itoa(car_gas, str_print, 10);
        video_putsmalls(28, 190, str_print);
 
        // forward/backward
        str_print[0] = '\0';
        if (reverse == 0) {
           str_print[0] = 'D';
           video_putsmalls(36, 190, str_print);
        } else {
           str_print[0] = 'R';
           video_putsmalls(36, 190, str_print);
        }
        str_print[0] = 'blank';
        video_putsmalls(40, 190, str_print);
           
        // steering wheel angle
        if (car_angle > 0) {
           str_print[0] = '\0';
           str_print[0] = 'P';
           video_putsmalls(44, 190, str_print);
           temp0 = car_angle;
        } else {
           str_print[0] = '\0';
           str_print[0] = 'N';
           video_putsmalls(44, 190, str_print);
           temp0 = (-1)*car_angle;
        }

        str_print[2] = '\0';
        itoa(temp0, str_print, 10);
		if (temp0 < 10) {
		   str_print[1] = str_print[0];
           str_print[0] = 'blank';
		}
        video_putsmalls(48, 190, str_print);

        // angle index
        str_print[0] = '\0';
        str_print[0] = 'A';
        video_putsmalls(60, 190, str_print);
        itoa(angle_state, str_print, 10);
		if (angle_state < 10) {
		   str_print[1] = str_print[0];
           str_print[0] = 'blank';
        }
        video_putsmalls(64, 190, str_print);
        str_print[0] = 'blank';
        video_putsmalls(72, 190, str_print);
        itoa(angle_state_2, str_print, 10);
		if (angle_state_2 < 10) {
		   str_print[1] = str_print[0];
           str_print[0] = 'blank';
        }
        video_putsmalls(76, 190, str_print);

        // error
        str_print[0] = 'blank';
        video_putsmalls(84, 190, str_print);
        str_print[0] = 'E';
        video_putsmalls(88, 190, str_print);
        itoa(error, str_print, 10);
        video_putsmalls(92, 190, str_print);
        //*********************************************************
        // CAR STATUS DISPLAY- end
        //*********************************************************

        //*********************************************************
        // ADJUSTMENT- begin
        //*********************************************************
		if (error == 0 && car_gas != 0)
           adjust_angle_state(x0_fix, y0_fix, x1_fix, y1_fix, &angle_state, &angle_state_2);

        if (stage)
		   redraw_a_line_parking_lot_1(&lines[0], &prev_lines[0]);
		else
		   redraw_a_line_parking_lot_0(&lines[0], &prev_lines[0]);

		if ((angle_state == 0 || angle_state == 36) && adjust_size == 1) {
		   adjust_car_size(&x0_fix, &y0_fix, &x1_fix, &y1_fix);
		   adjust_size = 0;
		} else if (angle_state != 0 && angle_state != 36) {
		   adjust_size = 1;
	    }

        //*********************************************************
        // ADJUSTMENT- end
        //*********************************************************

        // check when done
        if ((~PINB & 0x10) == 0x10) {
           break;
        }
 
        /////////////////////////////////////////
        // add this line to execute code exactly once per frame
        // comment it out for max execution speed
        while (LineCount != ScreenTop) ;
        
     } // if
     
  }  //while(1)

  car_gas = 0;

  //*********************************************************
  // CHECK PARKING RESULT- begin
  //*********************************************************
  str_print[0] = '\0';
  if (stage) {
	 error = check_parking_lot_1();
     if (error) {
        // FAIL
        str_print[0] = 'F';
        str_print[1] = 'A';
        str_print[2] = 'I';
        str_print[3] = 'L';
        str_print[4] = '!';
        str_print[5] = '\0';
     } else {
        // PASS
        str_print[0] = 'P';
        str_print[1] = 'A';
        str_print[2] = 'S';
        str_print[3] = 'S';
        str_print[4] = '!';
        str_print[5] = '\0';
     }
  } else {
	 error = check_parking_lot_0();
     if (error) {
        // FAIL
        str_print[0] = 'F';
        str_print[1] = 'A';
        str_print[2] = 'I';
        str_print[3] = 'L';
        str_print[4] = '!';
        str_print[5] = '\0';
     } else {
        // PASS
        str_print[0] = 'P';
        str_print[1] = 'A';
        str_print[2] = 'S';
        str_print[3] = 'S';
        str_print[4] = '!';
        str_print[5] = '\0';
     }
  }

  // display result
  video_puts(60, 100, str_print);

  if (error == 1) {
	 video_puts(10, 130, check_str0);
  } else if (error == 2) {
	 video_puts(10, 130, check_str1);
  } else if (error == 3) {
	 video_puts(10, 130, check_str0);
	 video_puts(10, 160, check_str1);
  }

  //*********************************************************
  // CHECK PARKING RESULT- begin
  //*********************************************************

  while ((~PINB & 0x80) != 0x80); // wait until restart
  erase_screen();

  goto RESTART;

  // check the result
}  //main