231a-ad playNotes

From CSclasswiki
Jump to: navigation, search
;;; ; ; playNotes.asm
;;; ; ; Amy Gray 
;;; ; ; December 2008
;;; ; ; 
;;; ; ;
;;; ; ;
;;; ; ; to assemble and run: 
;;; ; ;
;;; ; ;     nasm -f elf -F  stabs playNotes.asm
;;; ; ;     gcc -o playNotes driver.c playNotes.o
;;; ; ;     ./playNotes
;;; ; ; =========================================================

;; %include "asm_io.inc"

;;; External Labels =============================================
extern getchar
extern getc
	

                EXIT    equ             1
                WRITE   equ             4
                STDOUT  equ             1

        
;;; ;  ===========================================================
;;; ;  data areas
;;; ;  ===========================================================
;;; ;  note: 78 is dec for N and is essentially arbitrary.  When
;;; ;  playing the array, the program will check to see if the
;;; ;  "note" equals 78, and if so, knows there are no more notes
;;; ;  contained in the array and will end the loop.  I chose N
;;; ;  for "null" or "no note."
;;; ;  ===========================================================
                section .data
array		dd	78,78,78,78,78,78,78,78,78,78,78,78,78,78
		dd	78,78,78,78,78,78,78,78,78,78,78,78,78,78
		dd	78,78,78,78,78
arrayLen	equ	$-array 
nextIndex	dd	0 	;next index to be written to
message1	db	"Would you like to quit after this round?"
		db	" Type 'n' for no, 'y' for yes.", 10
message1Len	equ	$-message1
message2	db	"Sorry, input not valid. "
message2Len	equ	$-message2
message3	db	"Enter a new note: c, d, e, f, g, a, b, C,"
		db	" or p for pause."
message3Len	equ	$-message3
message4	db	"There's no more room to add notes!"
		db	"Your loop will continue to play and "
		db	"you can continue to make adjustments "
		db 	"until you choose to exit.  Type 'e' to exit."
message4Len	equ	$-message4
        
                section .bss
MAXBUF          equ     100000
buffer          resb    MAXBUF  ; 100,000 bytes of storage
        
;;; ;  =============================================================
;;; ;  code area
;;; ;  =============================================================

                section .text
                global asm_main

asm_main:
	mov	eax, WRITE
	mov	ebx, STDOUT
	mov	ecx, message1	;quit after play?
	mov	edx, message1Len
	int	0x80

	mov	eax, 0		;clear eax
	mov	ebx, 0
	mov	ecx, 0
	mov	edx, 0
;;  	call	getchar

ReadLoop1:
  	mov	ah, 0		;read key opcode
  	;; art of assembly says use 16h.  16h is BIOS
  	;; 80h for Linux?
  	int	0x80
  	cmp	al, 1		;special function?
  	je	ReadLoop1	;if so, don't echo this keystroke
  	putc
   	cmp	al, 0x16		;carriage return (ENTER)
   	jne	ReadLoop1

checkKey:
	cmp	al, 0x79	;check for y
	je	lastRound1
	cmp	al, 0x6E	;check for n
	jne	badAnswer1

lastRound1:	jmp	lastRound2
badAnswer1:	jmp	badAnswer2
main:
	mov	eax, WRITE
	mov	ebx, STDOUT
	mov	ecx, message3
	mov	edx, message3Len
	int	0x80
;; 	mov	eax, message3  	;ask for new note
;; 	call	print_string
	mov	eax, 0		;clear eax
	
ReadLoop2:
	mov	ah, 0		;read key opcode
	;; art of assembly says use 16h.  16h is BIOS
	;; 80h for Linux?
	int	80h
	cmp	al, 0		;special function?
	jz	ReadLoop2	;if so, don't echo this keystroke
	cmp	al, 0dh		;carriage return (ENTER)
	jne	ReadLoop2

getNextIndex:
	mov	ebx, 0
	mov	ecx, [arrayLen]
gniLoop:
	cmp	dword[array + ebx], 78
	je	checkNote
	inc	ebx
	loop	gniLoop
	
checkNote:
	cmp	ebx, [arrayLen-1];end of array?
	je	noMoreRoom1 	;array has exceeded 32 notes
	mov	[nextIndex], ebx
	
	cmp	ah, 0x63	;low c?
	je	noteClow1
	cmp	ah, 0x64	;d?
	je	noteD1
	cmp	ah, 0x65	;e?
	je	noteE1
	cmp	ah, 0x66	;f?
	je	noteF1
	cmp	ah, 0x67	;g?
	je	noteG1	
	cmp	ah, 0x61	;a?
	je	noteA1
	cmp	ah, 0x62	;b?
	je	noteB1
	cmp	ah, 0x43	;high C?
	je	noteChigh1
	cmp	ah, 0x70	;pause?
	je	notePause1
	jmp	badNote

;; Steps for Short Jumps =========================== 
lastRound2:	jmp 	lastRound
badAnswer2:	jmp	badAnswer
noMoreRoom1:	jmp	noMoreRoom
noteClow1:	jmp	noteClow
noteD1:		jmp	noteD
noteE1:		jmp	noteE
noteF1:		jmp	noteF
noteG1:		jmp	noteG
noteA1:		jmp	noteA
noteB1:		jmp	noteB
noteChigh1:	jmp	noteChigh
notePause1:	jmp	notePause
;;==================================================

;; TONES  ========================================== 
;; Start by defining the relationship between 
;;      note, period, &  frequency. 
;; #define  c     3830    // 261 Hz 
;; #define  d     3400    // 294 Hz 
;; #define  e     3038    // 329 Hz 
;; #define  f     2864    // 349 Hz 
;; #define  g     2550    // 392 Hz 
;; #define  a     2272    // 440 Hz 
;; #define  b     2028    // 493 Hz 
;; #define  C     1912    // 523 Hz 
;; #define  p     0
;; ==================================================

noteClow:
	mov	ebx, [nextIndex]
	mov	dword[array + ebx], 3830
	jmp	checkPots
noteD:
	mov	ebx, [nextIndex]
	mov	dword[array + ebx], 3400
	jmp	checkPots
noteE:
	mov	ebx, [nextIndex]
	mov	dword[array + ebx], 3038
	jmp	checkPots
noteF:
	mov	ebx, [nextIndex]
	mov	dword[array + ebx], 2864
	jmp	checkPots
noteG:
	mov	ebx, [nextIndex]
	mov	dword[array + ebx], 2550
	jmp	checkPots
noteA:
	mov	ebx, [nextIndex]
	mov	dword[array + ebx], 2272
	jmp	checkPots
noteB:	
	mov	ebx, [nextIndex]
	mov	dword[array + ebx], 2028
	jmp	checkPots
noteChigh:	
	mov	ebx, [nextIndex]
	mov	dword[array + ebx], 1912
	jmp	checkPots
notePause:
	mov	ebx, [nextIndex]
	mov	dword[array + ebx], 0
	jmp	checkPots

;;====================================================
noMoreRoom:
	mov	eax, message4	;no more room, but
				;loop will play
;; 	call	print_string
	

	;; play loop that checks for arduino input
;;====================================================

checkPots:
	jmp	mainPlay

mainPlay:
	mov	ecx, 0 		;clear ecx
	mov	ecx, [nextIndex] ;#of notes
	mov	ebx, 0		    ;which note to play
;; for testing, just print the array 
.loop:
	mov	eax, [array + ebx]
;; 	call	print_int
	inc	ebx
	loop	.loop
	jmp	asm_main

lastRound:
;plays once, then quits
	jmp	exit
badAnswer:
	mov	eax, WRITE
	mov	ebx, STDOUT
	mov	ecx, message2
	mov	edx, message2Len
	int	0x80
	jmp	asm_main

badNote:
	mov	eax, WRITE
	mov	ebx, STDOUT
	mov	ecx, message2
	mov	edx, message2Len
	int	0x80
	jmp	main
	
exit:
	ret