#include <18F452.h> // Standard Include for 18F452 Chip
#fuses HS,NOWDT,NOPROTECT,NOLVP,PUT // High Speed Clock, No Watch Dog Timer, No Code Protection, No Low Voltage P?, Power Up Timer
#use delay (clock=40000000) // 40 mhz powered oscillator

/*
   Keeps track of the state we are in
   0 for drawing line with variable horizontal position and width
   1 for moving square around the screen
   2 for writing I T P   P I C T V
*/
unsigned byte state = 0;
unsigned byte max_state = 2;

/* Counters to see what line and frame we are on */
unsigned long line_counter = 0;
unsigned long frame_counter = 0;

/* ADC Values */
unsigned byte a0_value = 100;
unsigned byte a1_value = 100;

/* Horizontal and Vertical Positions */
unsigned byte horizontal_pos;
unsigned byte vertical_pos;

/* Width and Height of the Square, Width for the Box */
unsigned byte width = 10;
unsigned byte height = 40;

/* Constants with which to reset the box */
unsigned byte sq_width = 10; // THIS IS A CONSTANT
unsigned byte sq_height = 40; // THIS IS A CONSTANT

/* Constant for which lines to draw letters in */
unsigned byte min_line = 50;
unsigned byte max_line = 150;

/* Frame Count Max Value for letter drawing (per letter) */
unsigned long max_frames = 50;

/* Which letter we are on */
unsigned byte letter_number = 0;

/* Which line of the bitmap letter we are on */
unsigned byte mod_count;

/* Bitmap Letter I */
unsigned byte letter_i[] = {
   0b01110000,
   0b00100000,
   0b00100000,
   0b00100000,
   0b00100000,
   0b00100000,
   0b00100000,
   0b00100000,
   0b01110000,
   0b00000000
};

/* Bitmap Letter T */
unsigned byte letter_t[] = {
   0b11111000,
   0b10101000,
   0b00100000,
   0b00100000,
   0b00100000,
   0b00100000,
   0b00100000,
   0b00100000,
   0b00100000,
   0b00000000
};

/* Bitmap Letter P */
unsigned byte letter_p[] = {
   0b11111100,
   0b10000100,
   0b10000100,
   0b10000100,
   0b10000100,
   0b11111100,
   0b10000000,
   0b10000000,
   0b10000000,
   0b00000000,
};

/* Bitmap Letter C */
unsigned byte letter_c[] = {
   0b11111100,
   0b10000100,
   0b10000000,
   0b10000000,
   0b10000000,
   0b10000000,
   0b10000000,
   0b10000100,
   0b11111100,
   0b00000000
};

/* Bitmap Letter V */
unsigned byte letter_v[] = {
   0b10000100,
   0b10000100,
   0b10000100,
   0b10000100,
   0b10000100,
   0b10000100,
   0b01001000,
   0b01001000,
   0b00110000,
   0b00000000
};

void pixelNop()
{
   #ASM
      nop
      nop
   #ENDASM
}

/* Draw a line with variable width and horizontal position */
void drawLine()
{
   output_low(PIN_D1);  // Low/Black to Start
   delay_us(horizontal_pos); // Delay to the position on screen we want
   output_high(PIN_D1); // High/White on
   delay_us(width); // Delay the width of the line we want
   output_low(PIN_D1); // Low/Black to End
}

/* Draw a square that you can move around on the screen, ala etch-a-sketch */
void drawSquare()
{
   output_low(PIN_D1);  // Start with Low/Black
   delay_us(horizontal_pos); // Delay to the horizontal position on screen
   
   //If we are on the correct line count for vertical position
   if (line_counter >= vertical_pos - height/2 && line_counter <= vertical_pos + height/2)
   {
      output_high(PIN_D1);  // Give us White
      delay_us(width); // Delay for the width of the square
   }

   output_low(PIN_D1); // Always Low/Black to End
}

/* Interrupt for a new field */
#INT_EXT1
void fieldInterrupt()
{
   line_counter = 0;
   frame_counter++;
   if (frame_counter > max_frames)
   {
      frame_counter = 0;
      letter_number++;
      letter_number = letter_number%10;
   }
}

/* Interrupt for a line to be drawn */
#INT_EXT2
void drawMe ()
{
   byte p;

   if (state == 0)
   {
      drawLine();
   }
   else if (state == 1)
   {
      drawSquare();
   }
   else // Draw The Letters -- Not a seperate function because of time
   {
      //drawLetters();
      if (line_counter > 50 && line_counter < 150)  // If we are in the right range of lines
      {
        
        if (letter_number == 0)
        {
         for (p = 8; p > 0; p--) // Draw from left to right on the bitmap instead of right to left (start with index 7)
      	{
         	if (bit_test(letter_i[mod_count],p-1)) // Test the bit of the byte for this line of this letter
         	{
        	      output_high(PIN_D1); // white if high
               pixelNop();
            }
   	      else
   		   {
   			   output_low(PIN_D1); // black if low
               pixelNop();
            }
          }
         }
         else if (letter_number == 1)
         {
            for (p = 8; p > 0; p--) // Draw from left to right on the bitmap instead of right to left (start with index 7)
      	   {
         	  if (bit_test(letter_t[mod_count],p-1)) // Test the bit of the byte for this line of this letter
         	  {
        	         output_high(PIN_D1); // white if high
                  pixelNop();
      	     }
      	     else
   	     	  {
   		    	   output_low(PIN_D1); // black if low
                 pixelNop();
              }
            }
         }
         else if (letter_number == 2)
         {
            for (p = 8; p > 0; p--) // Draw from left to right on the bitmap instead of right to left (start with index 7)
         	{
            	if (bit_test(letter_p[mod_count],p-1)) // Test the bit of the byte for this line of this letter
            	{
        	         output_high(PIN_D1); // white if high
                  pixelNop();
        	     }
      	     else
       		  {
   		    	   output_low(PIN_D1); // black if low
                  pixelNop();
              }
            }
         }
         else if (letter_number == 3)
         {
            pixelNop();
            pixelNop();
            pixelNop();
         }  
         else if (letter_number == 4)
         {
            for (p = 8; p > 0; p--) // Draw from left to right on the bitmap instead of right to left (start with index 7)
      	  {
            	if (bit_test(letter_p[mod_count],p-1)) // Test the bit of the byte for this line of this letter
         	  {
         	       output_high(PIN_D1); // white if high
                  pixelNop();
      	       }
   	        else
   		    {
   			      output_low(PIN_D1); // black if low
               pixelNop();
                  }
            }
         }
         else if (letter_number == 5)
         {
            for (p = 8; p > 0; p--) // Draw from left to right on the bitmap instead of right to left (start with index 7)
      	  {
            	if (bit_test(letter_i[mod_count],p-1)) // Test the bit of the byte for this line of this letter
         	  {
        	       output_high(PIN_D1); // white if high
                  pixelNop();

      	     }
      	     else
   	     	  {
   		    	   output_low(PIN_D1); // black if low
                 pixelNop();
               }
            }
         }
         else if (letter_number == 6)
         {
            for (p = 8; p > 0; p--) // Draw from left to right on the bitmap instead of right to left (start with index 7)
      	  {
         	  if (bit_test(letter_c[mod_count],p-1)) // Test the bit of the byte for this line of this letter
         	  {
        	          output_high(PIN_D1); // white if high
                  pixelNop();
              }
   	        else
   		       {
   			      output_low(PIN_D1); // black if low
                  pixelNop();
               }
            }
         }
         else if (letter_number == 7)
         {
            for (p = 8; p > 0; p--) // Draw from left to right on the bitmap instead of right to left (start with index 7)
      	  {
            	if (bit_test(letter_t[mod_count],p-1)) // Test the bit of the byte for this line of this letter
            	{
           	      output_high(PIN_D1); // white if high
                  pixelNop();
   	        }
   	        else
   		    {
   		    	   output_low(PIN_D1); // black if low
                pixelNop();
             }
            }
         }
         else if (letter_number == 8)
         {
            for (p = 8; p > 0; p--) // Draw from left to right on the bitmap instead of right to left (start with index 7)
      	  {
         	  if (bit_test(letter_v[mod_count],p-1)) // Test the bit of the byte for this line of this letter
         	  {
        	      output_high(PIN_D1); // white if high
               pixelNop();
      	     }
      	     else
   	     	  {
   		    	   output_low(PIN_D1); // black if low
                 pixelNop();
               }
            }
         }
         else if (letter_number == 9)
         {
            pixelNop();
            pixelNop();
            pixelNop();
         }

         // Do the math
         mod_count = (line_counter-50)/10;
         
         output_low(PIN_D1);
      } // End Right Line Zone
   } // End Draw Letters
   line_counter++;
} // End Function

main()
{
   boolean switch_on = 0;
   
   /* Setup ADC */
   setup_adc(ADC_CLOCK_INTERNAL );
   setup_adc_ports( ALL_ANALOG );
   
   /* Delay To Start */
   delay_ms(500);
   
   /* Enable the Interrupts */
   enable_interrupts(GLOBAL);
   
   ENABLE_INTERRUPTS(INT_EXT2); // Set up PIC18 EXT2
   ext_int_edge( 2, L_TO_H);
   ENABLE_INTERRUPTS(INT_EXT1); // Set up PIC18 EXT1
   ext_int_edge( 1, L_TO_H);
   ENABLE_INTERRUPTS(INT_EXT); // Set up PIC18 EXT0
   ext_int_edge( L_TO_H);
   

   
   /* Main Loop */
   while(TRUE)
   {
      /* Read ADC Channel 0 */
      set_adc_channel(0);
      delay_us(10); // Delay before read
      a0_value = read_adc(); // Read ADC from POT on A0, 0 to 255
         
      /* Read ADC Channel 1 */
      set_adc_channel(1);
      delay_us(10); // Delay before read
      a1_value = read_adc(); // Read ADC from POT on A1, 0 to 255

      if (state == 0) // Line Drawing
      {
         horizontal_pos = a0_value/5; // Set Horizontal Postion using ADC value (div by 5)
         width = a1_value/5;  // Set width of line on screen using ADC value (div by 5 = 0 to 51 
      }
      else if (state == 1) // Box Drawing
      {
         // Reset Width and Height for the square (this doesn't need to be done every time but...)
         width = sq_width;
         height = sq_height;
      
         horizontal_pos = a0_value/5; // Set Horizontal Postion using ADC value (div by 5 = 0 to 51)
         vertical_pos = a1_value;  // Set Vertical Position using ADC value (0 to 255)
      }
      else if (state == 2) // Letter Writing
      {
         max_frames = a0_value;
      }
      /* Check state of button and change state */
      
      if (input(PIN_D7))
      {
         if (!switch_on)
         {
            switch_on = 1;
            if (state < max_state)
            {
               state++;
            }
            else
            {
               state = 0;
            }
         }
      }
      else
      {
         switch_on = 0;
      }
      
   }
}
