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