231a-ac final.asm

From CSclasswiki
Jump to: navigation, search
;;; final.asm
;;; Yang Li
;;; 12/16/2008
;;; 
;;; This program constantly reads 4 bytes of ASCII characters
;;; representing the status of 4 arduino pins from c buffer to memory.
;;; If the switch status has not changed for a while,
;;; it send stored status back to the arduino.
;;;
;;; Sample output:
;;;
;;; ****************************************
;;; *       Interactive LED Matrix         *
;;; *    CSC231 Fall 2008 Final Project    *
;;; *             231a-ac Yang Li          *
;;; ****************************************
;;; Current Switch Status:1101
;;; Time before next playback: 51
;;; Playback? OFF
;;; 
;;; 
;;; To assemble and run:
;;;   nasm -f elf final.asm
;;; gcc -o arduino-serial arduino-serial.c asm_io.o final.o
;;; ./arduino-serial -b 9600 -p /dev/ttyUSB0

;;; ----------------------- EXTERN LABELS -----------------------
extern serialport_writebyte	; int function
extern serialport_write		; int function
extern serialport_read_until	; int function
extern displayBuffer		; int function
	
extern buf	
extern byte		

%include "asm_io.inc"
;;;------------------- Macros------------------------------------
%macro printMSG 1		;print C string
	push 	eax
	mov	eax,%1
	call	print_string
	pop	eax
%endmacro
	

%macro printStatus 1		;move cursor and print status as a C string
	pushad
	mov	eax,[%1]	
	mov	[currentStatus+7],eax ;modify string base on buf
	printMSG  currentStatus	      ;print status message
	popad
%endmacro
	
%macro printTimer 0		;move cursor and print time to next playback 
	push	eax		;as a C string
	printMSG indentTimer
	mov	eax,[alarm]
	call	print_int
	pop	eax
%endmacro

;;;---------------- Global Constants-----------------------------
%assign replayStepN	50	;# of steps during each playback
%assign alarmMax	100	;# of steps between last action and playback	
%assign MAXBUF     1024		;size of buffer in bytes
        ;; -------------------------
        ;; data segment
        ;; -------------------------
        section .data
;;; arduino commands
msgR	db	"r d", 0	;read pin status 
msgRlen	equ	$-msgR
msgP	db	"p", 0		;toogle playback mode 
msgPlen	equ	$-msgP
msgW	db	"w d 1 0",0	;write pin status 
msgWlen equ	$-msgW
pinNum  db	"1234"		;ascii characters 

;;; counters 
alarm	dd	100		;alarm for next playback
lastmove dd	0		;address of last status change
actived  dd	0		;if status has changed since program start

;;; screen display
welcomeMSG db 	"****************************************",10
	db	"*       Interactive LED Matrix         *",10
	db	"*    CSC231 Fall 2008 Final Project    *",10
	db	"*             231a-ac Yang Li          *",10
	db 	"****************************************",10
	db 	"Current Switch Status: ",10
	db 	"Time before next playback: ",10
	db	"Playback? OFF",10,0
	
startP  db	27,"[8;11H",27,"[31m","ON ",10,0 ;"ON" in red text
endP	db	27,"[8;11H",27,"[30m","OFF",10,0 ;"OFF" in black text
sClear  db      27,"[2J"        ; clear the screen
        db      27,"[1;1H",0    ; bring cursor at position 1,1
currentStatus db 27,"[6;23H","XXXX",10,10,10,0 ;template for displaying status
indentTimer db 27,"[7;27H",27,"[K",20,0	;move cursor and clear previous time

	section .bss
memory  resb    MAXBUF          ; storage for past status


        ;; -------------------------
        ;; code area
        ;; -------------------------
        section .text
        global  asm_main
asm_main:
;;; -------------------------
;;; main loop
;;; -------------------------
;;; Pseudocode:
;;; 
;;; welcome()
;;; buf=read_buffer()
;;; memory[0]=buf
;;; i=4
;;; While true:
;;; 	buf = read_buffer()
;;; 	memory[i]=buf
;;; 	if i==0:
;;; 		last_status=MaxBuf-4
;;; 	if (last_status==memory[i]):
;;; 		alarm--
;;; 	else :
;;; 		actived=true
;;; 		alarm=alarmMax
;;; 		last_status=i
;;; 	if (alarm==0):
;;; 		replay()
;;; 		alarm=alarmMax
;;; 	if (esi+4>Maxbuf):
;;; 		i=0
;;; 	else:
;;; 		i+=4
;;; 	delay()
;;; ------------------------
	call 	welcome 	
	call 	read_buffer	;get first set of status
	printStatus	buf	
	mov	eax,dword[buf]	;copy status to memory
	mov	[memory],eax
	
	mov	ecx,-1		;loop inifinite times
	mov	esi,4 		;initialize index pointer
for:
	push	ecx
	call 	read_buffer	;read buffer
	printStatus buf		
	
	mov	eax,dword[buf]  ;copy status to memory
	mov	[memory+esi],eax

	cmp	esi,0		;test if at index 0 (wrapped around)
	jne	cmpPrevious
	cmp	eax,[memory+MAXBUF-4]	;if yes, cmp with largest index
	jne	notSame
	jmp	same

cmpPrevious:			;if no, cmp with previous index
	cmp	eax,[memory+esi-4]
	jne	notSame
same:
	dec	dword[alarm]	;if same, decrement alarm counter
	jmp	testAlarm
notSame:
	mov	dword[actived],1;if not same, status has changed 
	mov	[lastmove],esi	;update last active status
	mov	dword[alarm],alarmMax
				;reset alarm
testAlarm:
	printTimer	
	cmp	dword[alarm],0	;test if alarm rings	
	jne	notRing	
	call	replay		;if yes, replay past actions
	mov	dword[alarm],alarmMax ;reset alarm
notRing:	
	cmp	esi,MAXBUF-4	;test memory overflow
	jge	overflow
	add	esi,4		;if not,increment 4 bytes
	jmp	finish
overflow:			;if yes,start from 0
	mov	esi,0
finish:	
	call	delay
	pop	ecx


        loop   skip		;replacement for "loop for"
        jmp    next
skip:   jmp    for
next:   
        ret
;;; --------------------------------------------
;;; replay: replay past status 
;;; modified registers:none
;;; --------------------------------------------
;;; Pseudocode:
;;;
;;; def replay():
;;; 	if (!actived):
;;; 		return
;;; 	togglePlayMode()
;;; 	if (last_move<replayStepN*4):
;;; 		i=MaxBuf-replayStepN*4+last_move
;;; 	else:
;;; 		i=last_move-4*replayStepN
;;; 	for k in range(replayStepN):
;;; 		loopSwitches(esiPointer)
;;; 		delay()
;;; 		if (esi+4>MaxBuf):
;;; 			esi=0
;;; 		else:
;;; 			esi+=4
;;; 	togglePlayMode()
;;; --------------------------------------------
replay:
	pushad
  	cmp	dword[actived],0;if never actived,do not replay
 	je	done1
	
	printMSG startP	
	call	togglePlayMode	;tooglePlayMode on

	mov	ecx,replayStepN	;loop N times

				;test enough space to go back N steps 
	cmp	dword[lastmove],replayStepN*4
	jl 	.wrap
	mov	esi,[lastmove]	;if yes,go back N steps since last move	
	sub	esi,4*replayStepN 
	jmp	loopStatus
.wrap:				;if no, wrap around 0
	mov	esi,MAXBUF-replayStepN*4 
	add	esi,[lastmove]


	jmp	loopStatus	;prevent short jmps
done1:	jmp	done2		;prevent short jmps

loopStatus:	
	push	ecx
	call    writeStatus	;write status to arduino
	pop	ecx
	
	call	delay		;slow down playback 
	call	delay
	call	delay
	
	cmp	esi,MAXBUF-4	;test array overflow
	jge	.overflow
	add	esi,4		;if not, increment 4 bytes
	jmp	nextStatus
.overflow:	
	mov	esi,0		;if yes, start from 0
nextStatus:
	loop	loopStatus	;end outer loop

	call 	togglePlayMode	;play mode off
	printMSG endP	
done2:	
 	popad
	ret

;;;---------------------------------------------------------------
;;; writeStatus:write arduino command base on status at index esi
;;; modified register edi,eax
;;; --------------------------------------------------------------
writeStatus:	
	mov	ecx,4		;loop through 4 status
	mov	edi,0		
.for:	
	mov	al,[memory+esi+edi]
	mov	[msgW+6],al	;copy status: '0' or '1'
	mov	al,[pinNum+edi]
	mov	[msgW+4],al	;copy switch #
	call	writeMsgW	;send command
	inc	edi
	loop	.for	;end inner loop
	ret


;;;---------------------------------------------------------------
;;; writeMsgW: send write digital command to arduino
;;; --------------------------------------------------------------
writeMsgW:	
	pushad
	mov	eax,msgW
	mov	ecx,msgWlen
	call	copyMsg
	call	serialport_write
	popad
	
	ret
	
;;;---------------------------------------------------------------
;;; togglePlayMode: change to play mode
;;; --------------------------------------------------------------
togglePlayMode:
	pushad
	mov	eax,msgP
	mov	ecx,msgPlen
	call	copyMsg
	call	serialport_write
	popad
	
	ret
	
;;; ---------------------------------------------------------------
;;; read_buffer: read and display buffer
;;; modified registers: eax,ecx
;;; ---------------------------------------------------------------
read_buffer:
	mov	eax, msgR
	mov	ecx, msgRlen	; "r d" read digital pins
	call	copyMsg		; now buf contains "r d"
	call	serialport_write
	call	serialport_read_until
	ret

;;; ----------------------------------------------------------------
;;; delay 10 ms, or 0.01 sec
;;; ----------------------------------------------------------------
delay:
	pushad
	mov	ecx,10000000	
.for	add	eax, 1		
	loop	.for		
	popad
	ret
	
;;; ----------------------------------------------------------------
;;; copyMsg1: puts array whose address in eax  in external buffer
;;; 	      number of bytes shoudl be in ecx.
;;; ----------------------------------------------------------------
copyMsg:
	pushad
	mov	esi, eax	; source buffer
	mov	edi, buf	; destination buffer in C program
.for	mov	al, [esi]
	mov	[edi], al
	inc	esi
	inc	edi
	loop	.for
	popad
	ret
;;; ----------------------------------------------------------
;;;Welcome
;;;-----------------------------------------------------------
welcome:
	printMSG sClear
	printMSG welcomeMSG
	ret