CS-220, Lab # 7 Due Date: 4-20-06 In this lab you are to write a .COM-file-format assembly language program and a C language program for an IBM PC-compatible computer, each of which will receive keyboard characters entered by the user, and, if the key pressed corresponds to one of the key-of-c piano keys (namely A, B, C, D, E, F, G, a, b, c, d, e, f, g), output a tone with the frequency of that musical note. Here upper case letters represent lower pitch tones and lower case letters the higher pitch tones (an octive above). The following table gives the frequencies of some keys on a piano keyboard: Note Frequency (Hz) Note Frequency (Hz) -------------------------------------------------------------------- Middle-C 262 C-sharp (D-flat) 277 D 294 D-sharp (E-flat) 311 E 330 F 349 F-sharp (G-flat) 370 G 392 G-sharp (A-flat) 415 A 440 A-sharp (B-flat) 466 B 494 high-c 523 c-sharp (d-flat) 554 d 587 d-sharp (e-flat) 622 e 659 f 698 f-sharp (g-flat) 740 g 784 g-sharp (a-flat) 831 a 880 a-sharp (b-flat) 932 b 988 You are not required to implement sharps and flats, but may do so if you wish. In that case you will need to use different keys to represent these notes. Perhaps you could use the numeric keys for that. Your program should continue "playing" notes until some special non-note key (perhaps the 'Q' key, for Quit) is pressed. Sound on a PC: As discussed in class, on an IBM PC, port 61h controls, among other things, the speaker. Although there is more than one way to produce a tone using this port, in this lab you will use the fact that channel 2 of the PC's Intel 8254 timer chip can be made to send a square wave of a specified frequency to the speaker. The steps outlined in the notes at: http://www.cs.binghamton.edu/~reckert/220/8254_timer.html should be followed. Specifically: 1. Program timer channel 2 of the 8254 for square wave output and binary count operation by sending the appropriate bit pattern to output port 43h. This only needs to be done once. Command register format: value: 1 0 1 1 0 1 1 0 --------------------------------- | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | --------------------------------- | | | | | | | |__ Count format (0=binary) | | | | |___|___|_______ Mode of operation | | | | (3=square wave) | | |__ |_______ How to access latch (3=LSB then MSB) |___|_______________ Timer/oscillator channel 2. Determine the timer count that corresponds to the desired tone frequency: count = 1193180/frequency. (The frequency, of course, depends upon which key was pressed.) 3. Send the count computed in the previous step to output port 42h. This is done in two steps: First output the least significant byte of the count to port 42h; then output the most significant byte of the count to port 42h. 4. Turn on timer 2 (thus starting the tone) by sending xxxxxx11b to port 61h. Here the bits marked with x should not be changed, as they control other things on the PC. 5. Delay for a short period of time. (Perhaps 1/4 second; the exact value is not important as long as it's not so short that the user can't hear the sound or so long that keyboard operation becomes sluggish. Hint: because of the high speed of the PC system clock, you will probably need a nested delay loop.) 6. Turn off timer 2 (thus terminating the sound) by sending xxxxxx10b to port 61h. Again the bits marked with x should not be changed. In order to get the notes, your assembly language program should use the DOS single-character input service of int 21h to get the ASCII code of the key. If the key is one of the notes of the piano keyboard, the program should generate a tone of the corresponding frequency as described above. If not, it should not produce a tone. As mentioned above, the assembly language program should be written as a .COM file executable. The reason is that in the next lab you will modify the program to make it into an interrupt service routine that intercepts the keyboard interrupt. This is much easier to do if the program has a single segment. We will be talking about interrupts in class very soon. In order to do port-mapped I/O in assembly language you will need to use the IN and OUT instructions. To do it in C, use the inportb() and outportb() functions described in class. Also in the C version be sure to put the following two #include statements at the beginning of your program: #include <conio.h> #include <dpmi.h> You should demonstrate your programs to the lab instructor. If you cannot do that, you must submit a diskette or CD-ROM containing the source and executable files for each. You should submit the standard documentation--i.e., a readable, well- documented .LST file. Flow charts and a hierarchy chart are not required.