// Laura Hotca and Meg Walraed-Sullivan

// ECE 476 Final Projeft

//*************************************************************************

//Compiler Directives

//*************************************************************************

#pragma regalloc-                                                                                                               //allocate registers

#pragma optsize-                                                                                                                 //optimize for speed

#include <Mega32.h>  

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include <delay.h>  

//*************************************************************************

//Constants

//*************************************************************************

#define lineTime 1018                                                                                                       //63.65 us                             

#define ScreenTop 30                                                                                                        //top of visible screen                                        

#define ScreenBot 230                                                                      //bottom of visible screen

#define STAFF_START 7                                                                                                 //top staff line    

#define width 126                                                                                                                //width of staff line   

#define CLEF_UPSHIFT 20                                                              //y-coord of clef start                                     

#define CLEF_X_START 7                                                                                                              //x-coord of leftmost starting point to draw clef

#define BTW_STAFF 13                                                                                                   //offset to get to the next staff

#define STAFF_HEIGHT 20                                                                                                             //height of staff

#define BTW_LINES 5                                                                                                                      //distance between lines

#define NOTE_WIDTH 15                                                                                                                //distance between notes

#define STAFF_NUM_NOTES 6                                                                                     //number of notes that fit on a staff

#define NOTE_START 23                                                                                                                //x-coord of start of first note

#define NUM_STAFFS      9                                                                                                              //number of staffs allowed        

#define maxkeys 16                                                                                                            //number of keys on keypad

//*************************************************************************

//Register Allocated Variables

//*************************************************************************

register char v1 @4;                                                                                                          //hold tv screen variables in 

register char v2 @5;                                                                                                          //  registers before blasting to

register char v3 @6;                                                                                                          //  screen

register char v4 @7;

register char v5 @8;

register char v6 @9;

register char v7 @10;

register char v8 @11;

register int i @12;

 

//*************************************************************************

//Compiler Directives

//*************************************************************************

#pragma regalloc+                                                                                                              //don't allocate registers manually

 

//*************************************************************************

//Variables

//*************************************************************************

 

//=========================================================================

//keypad variables

char butnum;                                                                                                                        //index into key array                                                                                                       

char key;                                                                                                                               //which key is pressed   

 

// look up table for the keys

flash unsigned char keytbl[16]={0xee, 0xed, 0xeb,0xe7,  

                                                                                                                                                                0xde, 0xdd, 0xdb, 0xd7,

                                                                                0xbe, 0xbd, 0xbb, 0xb7,   

                                                                                0x7e, 0x7d, 0x7b, 0x77};  

                                                                                                                                                       

 

//=========================================================================

//UART variables

bit new_data;                                                                                                                                        //if UART has just received new data

bit sending_data;                                                                                                                 //sending data to PC           

bit send_bit;                                          //used to send data to PC

//=========================================================================

//MIDI Variables

char midi_str[6];                                                                                                                 //holds 6 bytes indicating a note was pressed and released

char byte_index;                                                                                                                                  //index into midi_str

char current_state;                                                                                                                            //state for midi input timing

char note_index;                                                                                                                  //index into midi string of note number

char current_note_number;                                                                             //value of note being played

char current_velocity;                                                                                                       //value of current velocity

char note_name[1];                                                                                                             //name of current note       

char note_array[NUM_STAFFS*STAFF_NUM_NOTES];                        //holds notes on screen

char note_lengths[NUM_STAFFS*STAFF_NUM_NOTES];                    //holds lengths of notes on screen

char note_array_index;                                                                                                     //index into screen array       

int note_counter;                                                                                                                 //counts durations of note   

 

enum{whole,half,quarter,eight,sixteenth};                                    //durations of notes

 

//lengths of notes in increments of note counter                                                          

flash char note_length_lookup []={0,90,45,22,11};

 

//states for midi input

enum {waiting_for_status, waiting_for_note, waiting_for_velocity};

//=========================================================================

//Video Display Variables

char syncON, syncOFF;                                                                                                                    //for video display timing

int LineCount;                                                                                                                                                     //current line index

char screen[1600];                                                                                                                                             //holds screen array

int y;                                                                                                                                                                       //erase later

char  starting_x;                                                                                                                                 //position of note to be drawn

char current_staff;                                                                                             //keep track of which staff we are on            

bit interupt_counter;                                                                                                                          //used to poll keypad at 30 ms

char out_of_space[] = "OUT OF SPACE";                                                    //string to print after max notes entered

char out_of_space_1[] = "D=PRINT";                                                           //string to print after max notes entered  

int line_width;                                                                                                                                      //compare value to determine if we move to the next staff

 

//Point plot lookup table

flash char pos[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};  

 

//offset for heights of notes                                                             

flash char note_offset [12]={0,0,2,2,5,8,8,10,10,13,13,15};

   

//character bitmaps

//5x7 characters

flash char bitmap[39][7]={

 //0

 0b01110000,

 0b10001000,

 0b10011000,

 0b10101000,

 0b11001000,

 0b10001000,

 0b01110000,

 //1

 0b00100000,                                      

 0b01100000,

 0b00100000,

 0b00100000,

 0b00100000,

 0b00100000,

 0b01110000, 

 //2

 0b01110000,

 0b10001000,

 0b00001000,

 0b00010000,

 0b00100000,

 0b01000000,

 0b11111000,

 //3

 0b11111000,

 0b00010000,

 0b00100000,

 0b00010000,

 0b00001000,

 0b10001000,

 0b01110000,

 //4

 0b00010000,

 0b00110000,

 0b01010000,

 0b10010000,

 0b11111000,

 0b00010000,

 0b00010000,

 //5

 0b11111000,

 0b10000000,

 0b11110000,

 0b00001000,

 0b00001000,

 0b10001000,

 0b01110000,

 //6

 0b01000000,

 0b10000000,

 0b10000000,

 0b11110000,

 0b10001000,

 0b10001000,

 0b01110000,

 //7

 0b11111000,

 0b00001000,

 0b00010000,

 0b00100000,

 0b01000000,

 0b10000000,

 0b10000000,

 //8

 0b01110000,

 0b10001000,

 0b10001000,

 0b01110000,

 0b10001000,

 0b10001000,

 0b01110000,

 //9

 0b01110000,

 0b10001000,

 0b10001000,

 0b01111000,

 0b00001000,

 0b00001000,

 0b00010000, 

 //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,

 //figure1

 0b01110000,

 0b00100000,

 0b01110000,

 0b10101000,

 0b00100000,

 0b01010000,

 0b10001000,

 //figure2

 0b01110000,

 0b10101000,

 0b01110000,

 0b00100000,

 0b00100000,

 0b01010000,

 0b10001000,

 //blank

 0b00000000,

 0b00000000,

 0b00000000,

 0b00000000,

 0b00000000,

 0b00000000,

 0b00000000

 };

 

 

//================================

//3x5 font numbers, then letters

//packed two per definition for fast

//copy to the screen at x-position divisible by 4

flash 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};        

//*************************************************************************

//Prototypes

//*************************************************************************

void video_pt(char x, char y, char c); 

void video_smallchar(char x, char y, char c);

void video_putsmalls(char x, char y, char *str);

void video_line(char x1, char y1, char x2, char y2, char c);

char video_set(char x, char y);

void draw_clef(char x_start, char y_start);

char draw_staff(char x_start, char y_start, char staff_length);

void initialize(void);

void test_the_command(void);  

void get_the_command(void);

void draw_note(char note_num, char intensity, char note_type);  

void clear_screen(void);

char compress_note(char note_num);

void decode_keypad(void); 

void draw_and_store_note(char note_num, int note_length);

void auto_scroll(void);

 

//==================================

//turn warnings back off

#pragma warn-

//==================================

 

//*************************************************************************

//Timer1 Interupt                                                          

//   sync generator for video display, must be entered from sleep mode to

//   ensure correct timing

//*************************************************************************

interrupt [TIM1_COMPA] void t1_cmpA(void)  {

   

  PORTD = syncON;                                                                           //start horizontal sync pulse

  LineCount ++ ;                                                   //update index into screen

  if (LineCount==248)         {                                              //vertical synch after line 247

    syncON = 0b00100000;

    syncOFF = 0;

  }//if (LineCount==248)

  if (LineCount==251) {                                                                                      //regular sync after line 250

    syncON = 0;

    syncOFF = 0b00100000;

  }//if (LineCount==251) 

  if (LineCount==263) {                                                                      //new frame after line 262

     LineCount = 1;

  }//if (LineCount==263)  

 

  delay_us(2);                                                                                                        //adjust to make 5 us pulses

  PORTD = syncOFF;                                                                                                         //end sync pulse  

 

  if (LineCount<ScreenBot && LineCount>=ScreenTop) {

     //compute byte index for beginning of the next line

     //left-shift 4 would be individual lines

     // <<3 means line-double the pixels

     //The 0xfff8 truncates the odd line bit

     //i=(LineCount-ScreenTop)<<3 & 0xfff8; //

      

       #asm

       push r16

       lds   r12, _LineCount

       lds   r13, _Linecount+1

       ldi   r16, 30

       sub  r12, r16

       ldi  r16,0

       sbc  r13, r16

       lsl  r12

       rol  r13

       lsl  r12

       rol  r13

       lsl  r12   

       rol  r13

       mov  r16,r12

       andi r16,0xf0

       mov  r12,r16

       pop r16

       #endasm

       

       //load 16 registers with screen info

       #asm

       push r14

       push r15

       push r16

       push r17

       push r18

       push r19

       push r26

       push r27

      

       ldi  r26,low(_screen)   ;base address of screen

       ldi  r27,high(_screen)  

       add  r26,r12            ;offset into screen (add i)

       adc  r27,r13

       ld   r4,x+                ;load 16 registers and inc pointer

       ld   r5,x+

       ld   r6,x+ 

       ld   r7,x+

       ld   r8,x+

       ld   r9,x+

       ld   r10,x+ 

       ld   r11,x+

       ld   r12,x+

       ld   r13,x+

       ld   r14,x+ 

       ld   r15,x+

       ld   r16,x+  

       ld   r17,x+ 

       ld   r18,x+

       ld   r19,x

      

       pop  r27

       pop  r26

       #endasm 

 

       delay_us(4);                                                                   //adjust to center image on screen

      

       //blast 16 bytes to the screen  

       #asm

       ;but first a macro to make the code shorter 

       ;the macro takes a register number as a parameter

       ;and dumps its bits serially to portD.6  

       ;the nop can be eliminated to make the display narrower

       .macro videobits ;regnum

        BST  @0,7

        IN   R30,0x12

                   BLD  R30,6

                   nop

                   OUT  0x12,R30 

               

                   BST  @0,6

                   IN   R30,0x12

        BLD  R30,6

                   nop

                   OUT  0x12,R30

               

                   BST  @0,5

                   IN   R30,0x12

                   BLD  R30,6

                   nop

                   OUT  0x12,R30

               

                   BST  @0,4

                   IN   R30,0x12

                   BLD  R30,6

                   nop

                   OUT  0x12,R30

               

                   BST  @0,3

                   IN   R30,0x12

       BLD  R30,6

                   nop

                   OUT  0x12,R30

               

                   BST  @0,2

                   IN   R30,0x12

                   BLD  R30,6

                   nop

                   OUT  0x12,R30

               

       BST  @0,1

                   IN   R30,0x12

                   BLD  R30,6

                   nop

                   OUT  0x12,R30

               

                   BST  @0,0

                   IN   R30,0x12

                   BLD  R30,6

                   nop

                   OUT  0x12,R30

       .endm    

       

                    videobits r4 ;video line -- byte 1

        videobits r5 ;byte 2 

        videobits r6 ;byte 3

        videobits r7 ;byte 4

        videobits r8 ;byte 5

        videobits r9 ;byte 6

        videobits r10 ;byte 7

        videobits r11 ;byte 8

        videobits r12 ;byte 9

        videobits r13 ;byte 10 

        videobits r14 ;byte 11

        videobits r15 ;byte 12

        videobits r16 ;byte 13

        videobits r17 ;byte 14

        videobits r18 ;byte 15

        videobits r19 ;byte 16

                   clt   ;clear video after the last pixel on the line

                   IN   R30,0x12

                   BLD  R30,6

                   OUT  0x12,R30

                                                                                                                               

        pop r19

        pop r18

        pop r17

        pop r16 

        pop r15

        pop r14

        #endasm

                         

    }//if (LineCount<ScreenBot && LineCount>=ScreenTop)        

}//timer1 interupt           

 

interrupt [EXT_INT0] void clear_button(void)  {

 

}//clear_button interrupt

//*************************************************************************

//video_pt                                                          

//   plots one point at x,y with color 1=white 0=black 2=invert

//*************************************************************************

void video_pt(char x, char y, char c) {  

 

  #asm

  ;  i=(x>>3) + ((int)y<<4) ;   the byte with the pixel in it

 

  push r16

  ldd r30,y+2   ;get x

  lsr r30

  lsr r30

  lsr r30       ;divide x by 8

  ldd r12,y+1   ;get y

  lsl r12       ;mult y by 16

  clr r13

  lsl r12

  rol r13

  lsl r12

  rol r13

  lsl r12

  rol r13

  add r12, r30      ;add in x/8

 

  ;v2 = screen[i];   r5

  ;v3 = pos[x & 7];  r6

  ;v4 = c            r7

  ldi r30,low(_screen)

  ldi r31,high(_screen)

  add r30, r12

  adc r31, r13

  ld r5,Z    ;get screen byte

  ldd r26,y+2   ;get x

  ldi r27,0

  andi r26,0x07           ;form x & 7

  ldi r30,low(_pos*2) 

  ldi r31,high(_pos*2)

  add r30,r26

  adc r31,r27

  lpm r6,Z

  ld r16,y   ;get c

      

  ;if (v4==1) screen[i] = v2 | v3 ;

  ;if (v4==0) screen[i] = v2 & ~v3;

  ;if (v4==2) screen[i] = v2 ^ v3 ;

      

  cpi r16,1

  brne tst0

  or  r5,r6

  tst0:

  cpi r16,0

  brne tst2

  com r6

  and r5,r6

  tst2:

  cpi r16,2

  brne writescrn

  eor r5,r6

  writescrn:

  ldi r30,low(_screen)

  ldi r31,high(_screen)

  add r30, r12

  adc r31, r13

  st Z, r5         ;write the byte back to the screen

 

  pop r16

  #endasm

      

}//video_pt

 

//==================================

//turn warnings off

#pragma warn-

//==================================

 

 

 

//*************************************************************************

//video_putchar                                                           

//   put a big character on the screen; c is index into bitmap

//*************************************************************************

void video_putchar(char x, char y, char c)  {

    v7 = x;

    for (v6=0;v6<7;v6++) {

        v1 = bitmap[c][v6];

        v8 = y+v6;

        video_pt(v7,   v8, (v1 & 0x80)==0x80); 

        video_pt(v7+1, v8, (v1 & 0x40)==0x40);

        video_pt(v7+2, v8, (v1 & 0x20)==0x20);

        video_pt(v7+3, v8, (v1 & 0x10)==0x10);

        video_pt(v7+4, v8, (v1 & 0x08)==0x08);

    }//for

}//video_putchar

     

//*************************************************************************

//video_smallchar                                                          

//   put a small character on the screen; c is index into bitmap

//   ***x-coord must be on divisible by 4***

//*************************************************************************

void video_smallchar(char x, char y, char c)  {

  char mask;

  i=((int)x>>3) + ((int)y<<4) ;

  if (x == (x & 0xf8)) mask = 0x0f;     //f8

  else mask = 0xf0;

 

  screen[i] =    (screen[i] & mask) | (smallbitmap[c][0] & ~mask);

  screen[i+16] = (screen[i+16] & mask) | (smallbitmap[c][1] & ~mask);

  screen[i+32] = (screen[i+32] & mask) | (smallbitmap[c][2] & ~mask);

  screen[i+48] = (screen[i+48] & mask) | (smallbitmap[c][3] & ~mask);

  screen[i+64] = (screen[i+64] & mask) | (smallbitmap[c][4] & ~mask);

}//video_smallchar  

 

//*************************************************************************

//video_putsmalls                                                          

//   put a string of small characters on the screen

//   ***x-coord must be on divisible by 4***

//*************************************************************************

void video_putsmalls(char x, char y, char *str) {

  char i ;

  for (i=0; str[i]!=0; i++) {  

    if (str[i]>=0x30 && str[i]<=0x3a)

      video_smallchar(x,y,str[i]-0x30);

    else if (str[i]==0x20)

      video_smallchar(x,y,12); 

    else if (str[i]==0x3D)

      video_smallchar(x,y,11);

    else

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

    x = x+4;

  }//for

}//video_putsmalls

      

//*************************************************************************

//video_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 char dx,dy,j, temp;

  signed char s1,s2, xchange;

  signed char x,y;

       

  x = x1;

  y = y1;

  dx = cabs(x2-x1);

  dy = cabs(y2-y1);

  s1 = csign(x2-x1);

  s2 = csign(y2-y1);

  xchange = 0;  

  if (dy>dx) {

    temp = dx;

    dx = dy;

    dy = temp;

    xchange = 1;

  }//if (dy>dx)

  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 (e>=0)

    if (xchange==1)

      y = y + s2;

    else

      x = x + s1;

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

  }//for

}//video_line

 

//*************************************************************************

//video_set                                                          

//   grab the value of point at x,y with color 1=white 0=black 2=invert

//*************************************************************************

char video_set(char x, char y){

  i=((int)x>>3) + ((int)y<<4) ; 

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

}//video_set

 

//*************************************************************************

//draw_clef                                                          

//   draws the G-clef at given coordinates

//*************************************************************************

void draw_clef(char x_start, char y_start)  {  

   char j;

   char y;

   char x;

  

   y = y_start-21;                                                                  //contains the current y-coord

   x = x_start;                                        //contains the current x-coord

  

  video_line(x_start,y_start,x_start,y,1);        //draw vertical line

                

  for(j=0;j<3;j++)  {                                                              //draw top half of top loop      

   video_pt(++x,++y,1);

  }//for     

 

  video_pt(x,++y,1);                              //draw vertically down

             

  for(j=0;j<7;j++) {                               //draw bottom half of top loop

                video_pt(--x,++y,1);                                                              //and top half of left part of

  }//for                                                                                                                    // bottom loop             

 

  for(j=0;j<4;j++){                                                                     //draw vertically down    

   video_pt(x,++y,1);

  }//for

                 

  for(j=0;j<3;j++){                                //draw bottom half of left

    video_pt(++x,++y,1);                                                        //part of bottom loop

  }//for 

          

  x = x + 2;                                                                                              //for aesthetics

  //draw vertically down

  video_pt(x,++y,1);         

 

  y=y+1;                                                                                  //for aesthetics

 

  for(j=0;j<3;j++) {                              //draw bottom half of right part      

   video_pt(++x,--y,1);                           //of bottom loop

  }//for 

 

  x = x+1;                                                                                //for aesthetics

  for(j=0;j<3;j++) {                                                                              //draw vertically up     

   video_pt(x,--y,1);

  }//for      

   

  for(j=0;j<3;j++) {                                                                              //draw horizontally left

   video_pt(--x,y,1);

  }//for

  

 }//draw_clef

 

//*************************************************************************

//draw_staff                                                          

//   draws the staff at given coordinates

//*************************************************************************

char draw_staff(char x_start, char y_start, char staff_length) { 

  char j;

 

  for (j=0;j<5;j++) {

   video_line(x_start,y_start,x_start+staff_length,y_start,1);  

   y_start = y_start + BTW_LINES;   

  }//for 

 

  return y_start+BTW_STAFF-BTW_LINES-1;

}//draw_staff

 

 

//*************************************************************************

//draw_note                                                          

//   draws note at apropriate point, given note name

//*************************************************************************

void draw_note(char this_note_num, char intensity, char note_type){

   

    char starting_y;                                                                                                              //y_coordinate of the note position

    char i;                                            //used to index into loops

    char sharp_x;                                                                                                                   //used for drawing sharp sign

    char sharp_y;                                      //used for drawing sharp sign

    char c_line =  STAFF_START+STAFF_HEIGHT+BTW_LINES; //y coordinate used for bottom c

    char note_num;                                                                                                               //what note is being drawn

    char sharp;                                                                                                                       //black or white key   

    char draw_c_line;                                                                                                           //whether the note is a c                                                            

    int j;                                                                                                                                   //used to index into loops

    int starting_point;                                                                                                           //index into screen array (for memory copy)

    int ending_point;                                  //index into screen array (for memory copy)

    int copy_to;                                       //used for memory copy

   

    

    note_num=this_note_num%12;                                                                                 //determine which note to be drawn

    if ((note_num==1)|| (note_num==3) || (note_num==6) || (note_num==8) || (note_num==10))

                                sharp=1;

    else

                                sharp = 0; 

    if ((note_num==1)|| (note_num==0))

                                draw_c_line=1;    //the note is a c  

    else

                                draw_c_line=0;

    starting_y=STAFF_START+STAFF_HEIGHT+BTW_LINES+1-(note_offset[note_num]);

   

   

    

    //Determine which staff you can draw in

    //staff 1 

    if ( (starting_x > line_width) && (current_staff==3) )           { 

                   //SCROLL

                   starting_point=16*(STAFF_START-BTW_LINES+1);    

      ending_point=starting_point + (16*(BTW_LINES+STAFF_HEIGHT+BTW_STAFF+STAFF_HEIGHT+BTW_LINES+1));   

      //copy lines upward

      for (j=starting_point;j<ending_point;j++) { 

        screen[j]=screen[j+16*(STAFF_HEIGHT+BTW_STAFF-1)];

      }//for            

      //clear 3rd staff

      starting_point=16*(STAFF_START+(2*(STAFF_HEIGHT+BTW_STAFF))-BTW_LINES-1);  

      ending_point=starting_point+16*(STAFF_HEIGHT+(2*BTW_LINES)+2);

      for (j=starting_point;j<ending_point;j++) { 

        screen[j]=0;

      }//for     

      //redraw 3rd staff lines  

      starting_point=16*(STAFF_START+STAFF_HEIGHT+BTW_STAFF-1);

      copy_to=16*(STAFF_START+2*(STAFF_HEIGHT+BTW_STAFF)-2);

      for (j=0;j<16;j++)          {

        screen[copy_to++]=screen[starting_point++];

      }//for                

      starting_point+=(16*(BTW_LINES-1));

      copy_to+=(16*(BTW_LINES-1));

      for (j=0;j<16;j++)          {

        screen[copy_to++]=screen[starting_point++];

      }//for

      starting_point+=(16*(BTW_LINES-1));

      copy_to+=(16*(BTW_LINES-1));

      for (j=0;j<16;j++)          {

        screen[copy_to++]=screen[starting_point++];

      }//for

      starting_point+=(16*(BTW_LINES-1));

      copy_to+=(16*(BTW_LINES-1));

      for (j=0;j<16;j++)          {

        screen[copy_to++]=screen[starting_point++];

      }//for

      starting_point+=(16*(BTW_LINES-1));

      copy_to+=(16*(BTW_LINES-1));

      for (j=0;j<16;j++)          {

        screen[copy_to++]=screen[starting_point++];

      }//for

      starting_point=16*(STAFF_START+STAFF_HEIGHT+BTW_STAFF-BTW_LINES);    

      ending_point=starting_point + 16*(STAFF_HEIGHT+(2*BTW_LINES)+2);   

      //copy clef and beg/end lines

      for (j=starting_point;j<ending_point;j++) { 

       screen[j+16*(STAFF_HEIGHT+BTW_STAFF-1)]=screen[j];

       j++;

       screen[j+16*(STAFF_HEIGHT+BTW_STAFF-1)]=screen[j];

       j+=14;

       screen[j+16*(STAFF_HEIGHT+BTW_STAFF-1)]=screen[j];

      }//for               

      current_staff=3;

      starting_x=NOTE_START;                         

     

    }//if 

   

    //staff 2

    if ( (starting_x > line_width) && (starting_x<(2*line_width)) && (current_staff==1) )                {

      current_staff=2;

      starting_x=NOTE_START;

    }//if 

   

    //staff 3   

    if ( (starting_x > line_width) && (current_staff==2) )           {

      current_staff=3;

      starting_x=NOTE_START;

    }//if

   

   

    //Initialize the starting y coordinate for the current staff

    if (current_staff==2)      {

      starting_y+=BTW_STAFF+STAFF_HEIGHT-1;  

    }//if (current_staff==2)

   

    if (current_staff==3)      {

      starting_y+=2*(BTW_STAFF+STAFF_HEIGHT-1);        

    }//if (current_staff==2)      

                             

    //Draw the note outline

    video_pt(starting_x, starting_y,intensity);

    video_pt(starting_x, --starting_y,intensity);

    for (i=0;i<2;i++)              { 

      video_pt(++starting_x, --starting_y,intensity);   

    }//for

    video_pt(++starting_x, starting_y,intensity);  

    video_pt(++starting_x, starting_y,intensity);

    video_pt(++starting_x, ++starting_y,intensity); 

    video_pt(starting_x, ++starting_y,intensity);

    for (i=0;i<2;i++)              { 

    video_pt(--starting_x, ++starting_y,intensity);

    }      

    for (i=0;i<2;i++)              {

    video_pt(--starting_x, starting_y,intensity);

    } 

   

    switch (note_type)           {    

      case half :

        //Draw stems   

        starting_x+=4;

        starting_y-=3;        

        for (j=0;j<(3*BTW_LINES-2);j++)         {

          video_pt(starting_x, --starting_y,intensity);                        //up

        }//for      

        starting_x-=4;

        starting_y+=(4+3*BTW_LINES-3);

       

      break;

      case quarter:

        //Fill note in

        video_pt(starting_x, --starting_y,intensity);                          //up  

        video_pt(starting_x, --starting_y,intensity);                          //up

        video_pt(++starting_x, --starting_y,intensity);     //diag

        video_pt(++starting_x, starting_y,intensity);                        //right     

        video_pt(++starting_x, starting_y,intensity);                        //right

        video_pt(starting_x, ++starting_y,intensity);                        //down

        video_pt(--starting_x, starting_y,intensity);                         //left

        video_pt(--starting_x, starting_y,intensity);          //left

        video_pt(starting_x, ++starting_y,intensity);                        //down

        video_pt(++starting_x, starting_y,intensity);                        //right

       

        starting_x-=2;

        starting_y++;

       

       //Draw stems   

        starting_x+=4;

        starting_y-=3;        

        for (j=0;j<(3*BTW_LINES-2);j++)         {

          video_pt(starting_x, --starting_y,intensity);                        //up

        }//for      

        starting_x-=4;

        starting_y+=(4+3*BTW_LINES-3);

      break;

      case eight:

         //Fill note in

        video_pt(starting_x, --starting_y,intensity);                          //up  

        video_pt(starting_x, --starting_y,intensity);                          //up

        video_pt(++starting_x, --starting_y,intensity);     //diag

        video_pt(++starting_x, starting_y,intensity);                        //right     

        video_pt(++starting_x, starting_y,intensity);                        //right

        video_pt(starting_x, ++starting_y,intensity);                        //down

        video_pt(--starting_x, starting_y,intensity);                         //left

        video_pt(--starting_x, starting_y,intensity);          //left

        video_pt(starting_x, ++starting_y,intensity);                        //down

        video_pt(++starting_x, starting_y,intensity);                        //right    

       

        starting_x-=2;

        starting_y++;

        

       //Draw stems 

        starting_x+=4;

        starting_y-=3;        

        for (j=0;j<(3*BTW_LINES-2);j++)         {

          video_pt(starting_x, --starting_y,intensity);                        //up

        }//for      

        starting_x-=4;

        starting_y+=(4+3*BTW_LINES-3);

       

        starting_x+=4;

        starting_y-=2;

        starting_y-=(3*BTW_LINES);

     

        //Draw first flag

        video_pt(++starting_x, ++starting_y,intensity);                   //diag SE

        video_pt(++starting_x, ++starting_y,intensity);                   //diag SE

        video_pt(++starting_x, ++starting_y,intensity);                   //diag SE        

        video_pt(++starting_x, ++starting_y,intensity);                   //diag SE

        video_pt(starting_x, ++starting_y,intensity);                                        //down   

        video_pt(starting_x, ++starting_y,intensity);                                        //down   

       

        starting_y+=((3*BTW_LINES)-4);

        starting_x-=8;

       

      break;       

      case sixteenth:

           //Fill note in

        video_pt(starting_x, --starting_y,intensity);                          //up  

        video_pt(starting_x, --starting_y,intensity);                          //up

        video_pt(++starting_x, --starting_y,intensity);     //diag

        video_pt(++starting_x, starting_y,intensity);                        //right     

        video_pt(++starting_x, starting_y,intensity);                        //right

        video_pt(starting_x, ++starting_y,intensity);                        //down

        video_pt(--starting_x, starting_y,intensity);                         //left

        video_pt(--starting_x, starting_y,intensity);          //left

        video_pt(starting_x, ++starting_y,intensity);                        //down

        video_pt(++starting_x, starting_y,intensity);                        //right    

       

        starting_x-=2;

        starting_y++;

       

        //Draw stems   

        starting_x+=4;

        starting_y-=3;        

        for (j=0;j<(3*BTW_LINES-2);j++)         {

          video_pt(starting_x, --starting_y,intensity);                        //up

        }//for      

        starting_x-=4;

        starting_y+=(4+3*BTW_LINES-3);

       

        starting_x+=4;

        starting_y-=2;

        starting_y-=(3*BTW_LINES);

     

        //Draw first flag

        video_pt(++starting_x, ++starting_y,intensity);                   //diag SE

        video_pt(++starting_x, ++starting_y,intensity);                   //diag SE

        video_pt(++starting_x, ++starting_y,intensity);                   //diag SE        

        video_pt(++starting_x, ++starting_y,intensity);                   //diag SE

        video_pt(starting_x, ++starting_y,intensity);                                        //down   

        video_pt(starting_x, ++starting_y,intensity);                                        //down   

           

        //Draw second flag 

        starting_x -= 4;

        starting_y -= 3;

        video_pt(++starting_x, ++starting_y,intensity);                   //diag SE

        video_pt(++starting_x, ++starting_y,intensity);                   //diag SE

        video_pt(++starting_x, ++starting_y,intensity);                   //diag SE        

        video_pt(++starting_x, ++starting_y,intensity);                   //diag SE

        video_pt(starting_x, ++starting_y,intensity);                                        //down   

        video_pt(starting_x, ++starting_y,intensity);                                        //down

       

        starting_x-=8;

        starting_y+=8;                  

      break;

    }//switch

        

    if (draw_c_line)               {

       //jump to right coords

       starting_y-=2;

       starting_x-=3;

       video_pt(starting_x++,starting_y,intensity);      

       video_pt(starting_x,starting_y,intensity);

       starting_x+=7;

       video_pt(starting_x++,starting_y,intensity);      

       video_pt(starting_x,starting_y,intensity);

       //return

       starting_x-=6;

       starting_y+=2;

    }//if (draw_c_line) 

   

    if (sharp) {

                sharp_x=starting_x-5;

                sharp_y=starting_y+1;

                if ((note_num==7)||(note_num==8))                {

                  sharp_y=sharp_y-3;

                }//if ((note_num==7)||(note_num==8))

                for (i=0;i<5;i++)  {

                                video_pt(sharp_x, --sharp_y,intensity);                          //up  

                                }//for  

                sharp_x=sharp_x-2;

                sharp_y=sharp_y+5;

                for (i=0;i<5;i++)  {

                                video_pt(sharp_x, --sharp_y,intensity);                          //up  

                                }//for  

                sharp_y+=1;

                sharp_x-=2;

                for (i=0;i<5;i++)  {

                                video_pt(++sharp_x, sharp_y,intensity);                        //right  

                                }//for      

                sharp_y+=2;

                sharp_x-=5;

                for (i=0;i<5;i++)  {

                                video_pt(++sharp_x, sharp_y,intensity);                        //right  

                }//for 

                starting_x++;

   }//if sharp                                

                

    starting_x+=NOTE_WIDTH;

   

}//draw_note                   

 

//*************************************************************************

//initialize                                                          

//   set up the ports and timers

//*************************************************************************

void initialize(void) {

              

  char y_coord;                                                                                     //y coordinate used for drawing staffs and G-clefs 

  char x_coord;                                                                     //x coordinate used for drawing staffs and G-clefs

  char y_offset;                                                                                     //y offset used for drawing    

        

  //init timer 1 to generate sync

  OCR1A = lineTime;                                                                         //One NTSC line

  TCCR1B = 9;                                                                                                     //full speed; clear-on-match

  TCCR1A = 0x00;                                                                                              //turn off pwm and oc lines

  TIMSK = 0x10;                                                                                                  //enable interrupt T1 cmp                                                                     

  interupt_counter=0;

 

  //init ports                                  

  //D.5 is sync:1000 ohm + diode to 75 ohm resistor

  //D.6 is video:330 ohm + diode to 75 ohm resistor

  DDRD = 0xf0;                                                                                    //video out and MIDI

  DDRB = 0xff;                                                                                                     //LEDs

    

  LineCount = 1;                                                                                   //initialize synch constants

  syncON = 0b00000000;

  syncOFF = 0b00100000; 

 

  clear_screen();

 

  MCUCR = 0b10000000;                                                                  //enable sleep mode

    

  //initialize the UART

  //UBRRH = (unsigned char)(31>>8);                            //16 Mhz/(16*31.25*10^3)-1

  UBRRL = 31;

  UCSRB = 0b00010000;                                                                   //Enable receiver and transmitter

  UCSRC = 0b01000000;                                                                                   //Set frame format: 8data, 1stop bit

  sending_data=0;                                                                                                //whether we are sending to PC

 

 

  #asm ("sei");                                                                                     //enable interupts        

      

  //MIDI variables

  byte_index=0;                              //index into midi_str

  current_state=waiting_for_status;          //which byte we are waiting for

  note_array_index=0;                                                                        //index into note storage array

  note_counter=0;                                                                                                //used to calculate duration of notes

 

  //Drawing variables         

  starting_x=NOTE_START;                                            //x-coord for drawing

  current_staff=1;                                                                                                //holds current staff to be drawn to

  line_width=(NOTE_START+(STAFF_NUM_NOTES*NOTE_WIDTH));//width of a music line

 

  PORTB=0xff;                                                                                                     //turn led's off

}//initialize

 

//*************************************************************************

//main                                                          

//*************************************************************************

void main(void) {

  char current_note_index;      

  char current_note;    

  char type;

  int j;   

  char y_coord;                                                                                     //y coordinate used for drawing staffs and G-clefs 

  char x_coord;                                                                     //x coordinate used for drawing staffs and G-clefs

  char y_offset;                                                                                     //y offset used for drawing 

  char saved_index;                                                                                              //to save before we re-initialize

  int starting_point;

  int ending_point;  

  char x_start;

  char y_start;

  int copy_to;     

  char c;

  char msk;

                 

  initialize();

 

  while(1) {

 

    //stall here until next line starts

    //sleep enable; mode=idle 

    //use sleep to make entry into sync ISR uniform time 

    

    #asm ("sleep");

   

    //The following code executes during the vertical blanking

    //Code here can be as long as 

    //a total of 60 lines x 63.5 uSec/line x 8 cycles/uSec

   

    if (LineCount==231) {                                                                                                    //assume nothing new from UART   

   

               

      if (note_counter <= note_length_lookup[half]+3)  {             //no need to count past whole notes

        note_counter++;

      }//if                                                  

       

     

      interupt_counter=!interupt_counter;                                                       //switch interupt counter

      if (interupt_counter==0)              {                              //every other frame (30Hz)

        decode_keypad();                                //poll keypad

        if (butnum==16)           { 

          //setup the UART stuff for a 16 MHz crystal

          UCSRB = 0x10 + 0x08 ;

          UBRRL = 103 ;

          UCSRC=0x86;

          sending_data=1;       

        }//if (butnum==26)

     

        if (butnum==12)           { 

          //MIDI variables

                                byte_index=0;  

          current_state=waiting_for_status;  

          note_array_index=0;

          note_counter=0;

 

          //Drawing variables

          starting_x=NOTE_START;

          current_staff=1;

          //initialize the UART

                                UBRRL = 31;

                                UCSRB = 0b00010000;                                                    //Enable receiver and transmitter

                                UCSRC = 0b01000000;                                                      //Set frame format: 8data, 1stop bit

          sending_data=0;   

           //clear 3rd staff

          starting_point=16*(STAFF_START+(2*(STAFF_HEIGHT+BTW_STAFF))-BTW_LINES-1);  

          ending_point=starting_point+16*(STAFF_HEIGHT+(2*BTW_LINES)+2);

          for (j=starting_point;j<ending_point;j++) { 

            screen[j]=0;

          }//for     

          //redraw 3rd staff lines  

          x_start=0;

          y_start=STAFF_START+2*(STAFF_HEIGHT+BTW_STAFF)-2; 

          starting_point=16*(STAFF_START+STAFF_HEIGHT+BTW_STAFF-1);

          copy_to=16*(STAFF_START+2*(STAFF_HEIGHT+BTW_STAFF)-2);

          for (j=0;j<16;j++)      {

            screen[copy_to++]=screen[starting_point++];

          }//for                

          starting_point+=(16*(BTW_LINES-1));

          copy_to+=(16*(BTW_LINES-1));

          for (j=0;j<16;j++)      {

            screen[copy_to++]=screen[starting_point++];

          }//for

          starting_point+=(16*(BTW_LINES-1));

          copy_to+=(16*(BTW_LINES-1));

          for (j=0;j<16;j++)      {

            screen[copy_to++]=screen[starting_point++];

          }//for

          starting_point+=(16*(BTW_LINES-1));

          copy_to+=(16*(BTW_LINES-1));

          for (j=0;j<16;j++)      {

            screen[copy_to++]=screen[starting_point++];

          }//for

          starting_point+=(16*(BTW_LINES-1));

          copy_to+=(16*(BTW_LINES-1));

          for (j=0;j<16;j++)      {

            screen[copy_to++]=screen[starting_point++];

          }//for

          starting_point=16*(STAFF_START+STAFF_HEIGHT+BTW_STAFF-BTW_LINES);    

          ending_point=starting_point + 16*(STAFF_HEIGHT+(2*BTW_LINES)+2);   

          //copy clef and beg/end lines

          for (j=starting_point;j<ending_point;j++) { 

            screen[j+16*(STAFF_HEIGHT+BTW_STAFF-1)]=screen[j];

            j++;

            screen[j+16*(STAFF_HEIGHT+BTW_STAFF-1)]=screen[j];

            j+=14;

            screen[j+16*(STAFF_HEIGHT+BTW_STAFF-1)]=screen[j];

          }//for       

                  

                    starting_point=16*(STAFF_START-BTW_LINES+1);    

          ending_point=starting_point + (16*(BTW_LINES+STAFF_HEIGHT+BTW_STAFF+STAFF_HEIGHT+BTW_LINES+1));   

          //copy lines upward

          for (j=starting_point;j<ending_point;j++) { 

            screen[j]=screen[j+16*(STAFF_HEIGHT+BTW_STAFF-1)];

          }//for    

          starting_x=NOTE_START;

        }//if (butnum==26)

      }//if (interupt_counter==0)

     

      if (sending_data==0)     {

        new_data=0;                                                                                                                                                 //assume UART got no data

        get_the_command();                                                                                                                   //check UART for new messages

        if (new_data) {                                                                                                              //if UART got data

          if (note_array_index<NUM_STAFFS*(STAFF_NUM_NOTES)){ 

          //if we haven't run out space

            switch (current_state)   {

              case waiting_for_status:                                                                     //if waiting for new note

                 if (midi_str[byte_index-1]==0x90){                                //if we get a status byte

                   note_index=byte_index;                  //hold byte index of noteON

                   current_state=waiting_for_note;                 //move to waiting for note

                 }//if (midi_str[byte_index-1]==0x90)

              break;

              case waiting_for_note:

                current_note_number=midi_str[note_index];              //grab note number

                current_state=waiting_for_velocity;                              //wait for velocity

              break;

              case waiting_for_velocity:

                current_velocity=midi_str[note_index+1];    //grab velocity

                if (current_velocity==0){                                                                                                                  //if note off

                  byte_index=0;                               //reset midi_str        

                                if (note_counter>note_length_lookup[half]) {

                                  type =whole;

                                }

                                else if ((note_counter>note_length_lookup[quarter])&&(note_counter<=note_length_lookup[half])){

                                                type=half;

                                }

                                else if ((note_counter>note_length_lookup[eight])&&(note_counter<=note_length_lookup[quarter])){

                                                type=quarter;     

                                } 

                                else if ((note_counter>note_length_lookup[sixteenth])&&(note_counter<=note_length_lookup[eight])){

                                                type=eight;     

                                }      

                                else if (note_counter<=note_length_lookup[sixteenth])             {

                                  type =sixteenth;

                                }

                  note_counter=0;           

                  draw_and_store_note(current_note_number, type); //draw note

                }//if (current_velocity==0              

                else {                                                                                                                                      //have received a note on

                                note_counter=0;

                }//else

                current_state=waiting_for_status;                                 //wait for next note

              break;

            }//switch

          }//if (note_array_index>=43) 

          else {  

            for (j=500;j<1100;j++)           {

              screen[j]=0;

            }//for                                                                                                                                                                          //note array over 43 notes

            video_putsmalls(40,42, out_of_space);

            video_putsmalls(44,54, out_of_space_1);

          }//else

        }//if (new_data)

      }//if (sending_data==0)

      else{                                                                                                                                                                                 //we are sending data to PC

       

       

        //SCROLLING CODE FOR SENDING ALL DATA TO PC

        /*

        //clear 3rd staff

        starting_point=16*(STAFF_START+(2*(STAFF_HEIGHT+BTW_STAFF))-BTW_LINES-1);  

        ending_point=starting_point+16*(STAFF_HEIGHT+(2*BTW_LINES)+2);

        for (j=starting_point;j<ending_point;j++) { 

          screen[j]=0;

        }//for     

        //redraw 3rd staff lines  

        x_start=0;

        y_start=STAFF_START+2*(STAFF_HEIGHT+BTW_STAFF)-2; 

        starting_point=16*(STAFF_START+STAFF_HEIGHT+BTW_STAFF-1);

        copy_to=16*(STAFF_START+2*(STAFF_HEIGHT+BTW_STAFF)-2);

        for (j=0;j<16;j++)        {

          screen[copy_to++]=screen[starting_point++];

        }//for                

        starting_point+=(16*(BTW_LINES-1));

        copy_to+=(16*(BTW_LINES-1));

        for (j=0;j<16;j++)        {

          screen[copy_to++]=screen[starting_point++];

        }//for

        starting_point+=(16*(BTW_LINES-1));

        copy_to+=(16*(BTW_LINES-1));

        for (j=0;j<16;j++)        {

          screen[copy_to++]=screen[starting_point++];

        }//for

        starting_point+=(16*(BTW_LINES-1));

        copy_to+=(16*(BTW_LINES-1));

        for (j=0;j<16;j++)        {

          screen[copy_to++]=screen[starting_point++];

        }//for

        starting_point+=(16*(BTW_LINES-1));

        copy_to+=(16*(BTW_LINES-1));

        for (j=0;j<16;j++)        {

          screen[copy_to++]=screen[starting_point++];

        }//for

        starting_point=16*(STAFF_START+STAFF_HEIGHT+BTW_STAFF-BTW_LINES);    

        ending_point=starting_point + 16*(STAFF_HEIGHT+(2*BTW_LINES)+2);    

        //copy clef and beg/end lines

        for (j=starting_point;j<ending_point;j++) { 

         screen[j+16*(STAFF_HEIGHT+BTW_STAFF-1)]=screen[j];

         j++;

         screen[j+16*(STAFF_HEIGHT+BTW_STAFF-1)]=screen[j];

         j+=14;

         screen[j+16*(STAFF_HEIGHT+BTW_STAFF-1)]=screen[j];

        }//for       

                  

                  starting_point=16*(STAFF_START-BTW_LINES+1);    

        ending_point=starting_point + (16*(BTW_LINES+STAFF_HEIGHT+BTW_STAFF+STAFF_HEIGHT+BTW_LINES+1));   

        //copy lines upward

        for (j=starting_point;j<ending_point;j++) { 

          screen[j]=screen[j+16*(STAFF_HEIGHT+BTW_STAFF-1)];

        }//for 

       

        PORTB=~note_array_index;

       

*/       

        //turn off all interupts for data sending

        #asm ("cli");

        for (j=0; j < 1600; j++)  {

         // if(j%16 == 0) printf("\n\r");

 

          msk = 0b10000000;

          for(c=0; c < 8; c++)   {

            send_bit = (screen[j] & msk) > 0;

            msk >>= 1;

            printf("%d",send_bit);

          }//for

        }//for

      

         PORTB=0x0;

         

      }//else

    }//if (LineCount==231)

  }//while(1)

}//main

 

//*************************************************************************

//test_the_command                                                          

//   checks to see if a char has been received and displays in binary. 

//*************************************************************************  

void test_the_command(void) {

 

  unsigned char midi_in; 

  char midi_string[1];

  char bit1;

  char bit2;

  char bit3;

  char bit4;

  char bit5;

  char bit6;

  char bit7; 

  char bit0;

 

  if (UCSRA.7) {                   //RX done bit    

    midi_in=UDR;   

    if ((midi_in&0b10000000)!=0){

    bit7=1;

    }

    else bit7=0;

    if ((midi_in&0b01000000)!=0){

    bit6=1;

    } 

    else bit6=0;

    if ((midi_in&0b00100000)!=0){

    bit5=1;

    }

    else bit5=0;

    if ((midi_in&0b00010000)!=0){

    bit4=1;

    }          

    else bit4=0;

    if ((midi_in&0b00001000)!=0){

    bit3=1;

    }          

    else bit3=0;

    if ((midi_in&0b00000100)!=0){

    bit2=1;

    }          

    else bit2=0;

    if ((midi_in&0b00000010)!=0){

    bit1=1;

    }          

    else bit1=0;

    if ((midi_in&0b00000001)!=0){

    bit0=1;

    }          

    else bit0=0;

    video_putchar(36,y,bit7);

    video_putchar(44,y,bit6);

    video_putchar(52,y,bit5);

    video_putchar(60,y,bit4);

    video_putchar(68,y,bit3);

    video_putchar(76,y,bit2);

    video_putchar(84,y,bit1);

    video_putchar(92,y,bit0);  

 

    y=y+10;                                            

 

  }//if UCSRA 

     

}//test_the_command

 

 

//*************************************************************************

//get_the_command                                                          

//   get the input from the UART

//*************************************************************************                       

void get_the_command(void) {

  unsigned char midi_in; 

 

 

  if (UCSRA.7) {                   //RX done bit    

    midi_in=UDR;   

    midi_str[byte_index++]=midi_in;               

    new_data=1;                    

  }//if UCSRA     

}//get_the_command   

 

//*************************************************************************

//clear_screen                                                         

//   draw an empty music sheet  

//*************************************************************************

void clear_screen(void){

  char y_coord;                                                                                     //y coordinate used for drawing staffs and G-clefs 

  char x_coord;                                                                     //x coordinate used for drawing staffs and G-clefs

  char y_offset;                                                                                     //y offset used for drawing 

  int j;  

 

  video_line(0,0,0,99,1);                                                      //draw vertical lines of outline box

  video_line(width,0,width,99,1);

 

  video_line(0,0,width,0,1);                                                                 //top line & bottom lines

  video_line(0,99,width,99,1);

 

  //staff lines                                                              

  y_coord=STAFF_START;                                                               //draw staff 1

  x_coord = 0;                           

  y_coord = draw_staff(x_coord,y_coord,width);

  //draw staff 2

  y_coord = draw_staff(x_coord,y_coord,width);

  //draw staff 3

  y_coord = draw_staff(x_coord,y_coord,width);

 

  //draw G clefs

  y_coord = STAFF_START+CLEF_UPSHIFT;            //y_offset = last line of staff coordinate

  x_coord = CLEF_X_START;                                                          //  + offset to get to first line of next staff  

  y_offset = BTW_STAFF + STAFF_HEIGHT;              //  + (4 pixel offsets between staff lines)x4 

  draw_clef(x_coord,y_coord);                                           //draw first G-clef

  y_coord = y_coord + y_offset;        

  draw_clef(x_coord,y_coord-1);                       //draw second G-clef   

  y_coord = y_coord + y_offset;

  draw_clef(x_coord,y_coord-2);                       //draw third G-clef 

 

}//clear_screen

//*************************************************************************

//decode_keypad

//   find out which button user is pressing

//*************************************************************************

void decode_keypad(void) {

 

  //get lower nibble

  DDRC = 0x0f;

  PORTC = 0xf0;

  delay_us(5);

  key = PINC;

    

  //get upper nibble

  DDRC = 0xf0;

  PORTC = 0x0f;

  delay_us(5);

  key = key | PINC;

    

  //find matching keycode in keytbl

  if (key != 0xff){  

    for (butnum=0; butnum<maxkeys; butnum++) {   

      if (keytbl[butnum]==key)  break;  

    }//for

    if (butnum==maxkeys) butnum=0;

    else butnum++;    //adjust by one to make range 1-16

  }//if 

  else butnum=0;

  //PORTB = ~ butnum;

   

}//decode_keypad      

//*************************************************************************

//draw_and_store_note                                                          

//   draws and stores note from keyboard

//*************************************************************************

void draw_and_store_note(char note_num, int length_of_note)                {

        

  draw_note(note_num,1,length_of_note);

  note_lengths[note_array_index]=length_of_note;

  note_array[note_array_index++]=note_num;    

 

}//draw_and_store_note

                         

//*************************************************************************

//send_to_pc

//  sends screen data to PC

//*************************************************************************