231a-af talkToArduino
The file can be accessed from here.
Return to Final Project Presentation.
;;; ; talkToArduino.asm
;;; ; Jessica Lin
;;; ; This program requires arduino-serial.c for handling the
;;; ; communication with an Arduino diecimila.
;;; ;
;;; ; To assemble and run
;;; ; nasm -f elf talkToArduino.asm
;;; ; gcc -o arduino-serial arduino-serial.c talkToArduino.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"
%assign SYS_EXIT 1
%assign SYS_WRITE 4
%assign SYS_READ 3
%assign SYS_LSEEK 19
%assign SEEKSET 0
%assign STDOUT 1
%assign SYS_OPEN 5
%assign SYS_CLOSE 6
%assign SYS_CREATE 8
%assign O_RDONLY 000000q
%assign O_WRONLY 000001q
%assign O_RDWR 000002q
%assign O_CREAT 000100q
%assign S_IRUSR 00400q
%assign S_IWUSR 00200q
%assign S_IXUSR 00100q
;;; ; ; --- MACRO -----------------------------------------------
;;; ; ; print msg,length
%macro print 2 ; %1 = address %2 = # of chars
pushad ; save all registers
mov edx,%2
lea ecx,[%1]
mov eax,4
mov ebx,1
int 0x80
popad ; restore all registers
%endmacro
;;; ; ; --- MACRO -----------------------------------------------
;;; ; ; print2 "quoted string"
%macro print2 1 ; %1 = immediate string,
section .data
%%str db %1
%%strL equ $-%%str
section .text
print %%str, %%strL
%endmacro
;;; ; --- MACRO -----------------------------------------------
;;; ; createFile filename, handle
%macro createFile 2
mov eax,SYS_CREATE
mov ebx,%1
mov ecx, S_IRUSR|S_IWUSR|S_IXUSR
int 0x80
test eax,eax
jns %%createfile
print2 "Could not open file"
mov eax,SYS_EXIT
mov ebx,0
int 0x80 ; final system call
%%createfile:
mov %2,eax ; save handle
%endmacro
;;; ; --- MACRO -----------------------------------------------
;;; ; openFile filename, mode, handle
%macro openFile 3
mov eax,SYS_OPEN
mov ebx,%1
mov ecx,%2
mov edx, S_IRUSR|S_IWUSR|S_IXUSR
int 0x80
test eax,eax
jns %%readFile
print2 "Could not open file"
mov eax,SYS_EXIT
mov ebx,0
int 0x80 ; final system call
%%readFile:
mov %3,eax ; save handle
%endmacro
;;; ; --- MACRO -----------------------------------------------
;;; ; readFile handle, buffer, buffer-length, number-bytes-read
%macro readFile 4
mov eax,SYS_READ
mov ebx,%1 ; file descriptor in bx
mov ecx,%2 ; buffer address
mov edx,%3 ; max number of bytes to read
int 0x80
mov %4,eax ; save number bytes read
%endmacro
;;; ; --- MACRO -----------------------------------------------
;;; ; writeBuf handle, buffer, noBytesToWrite
%macro writeFile 3
mov eax,SYS_WRITE
mov ebx,%1
mov ecx,%2
mov edx,%3
int 0x80
%endmacro
;;; ; --- MACRO -----------------------------------------------
;;; ; close handle
%macro close 1
mov eax,SYS_CLOSE
mov ebx,%1
int 0x80
%endmacro
;;; -------------------------
;;; data segment
;;; -------------------------
section .data
msg1 db "w d 13 1", 0
msg1len equ $-msg1
msg2 db "w d 13 0", 0
msg2len equ $-msg2
msg3 db "r a", 0
msg3len equ $-msg3
msg4 db "w d 13 "
msg4val db " ", 0
msg4len equ $-msg4
home db 27,"[2J" ; clear the screen
db 27,"[1;1H" ; ansi sequence to bring
; cursor at position 1,1
homeLen equ $-home
fileName db "data.txt",0
handle dd 0
noRead dd 0
timemsg db " seconds remaining!", 0x00
tmsglen equ $-timemsg
leavemsg db "Time to go!", 0x00
tvsec dd 0
tvusec dd 0
start dd 0 ; time the program begins running
latest dd 0 ; time at the last at/away computer switch
current dd 0 ; current time
here dd 0 ; how long user has been at computer
MAXHERE dd 60 ; max length of time user can be at computer
gone dd 0 ; how long user has been gone
MINGONE dd 15 ; min length of time user must be away
oldal dd '0'
TEMPTOTAL dd 480 ; will run for 8 minutes
section .bss
MAXBUF equ 100000
fbuffer resb MAXBUF
;;; -------------------------
;;; code area
;;; -------------------------
section .text
global asm_main
asm_main:
;; create file to store information
createFile fileName, [handle]
call timeofDay ; eax = # secs since epoch
mov dword[start], eax
mov dword[latest], eax
mov dword[current], eax
mov byte[fbuffer], 's'
mov byte[fbuffer+1], 't'
mov byte[fbuffer+2], 'a'
mov byte[fbuffer+3], 'r'
mov byte[fbuffer+4], 't'
mov byte[fbuffer+5], " "
mov dword[fbuffer+6], eax
mov byte[fbuffer+10], 0x0a
writeFile [handle], fbuffer, 11
close [handle]
.for:
sub eax, TEMPTOTAL
cmp eax, dword[start]
je .exit
call readPin1 ; get status of Pin 1 in al
push eax ; make space
push eax ; push status of Pin 1
mov eax, latest
push eax ; push address of latest time
mov eax, dword[current]
push eax ; push current time
mov eax, oldal
push eax ; push address of old al
mov eax, here
push eax ; push address of here counter
mov eax, gone
push eax ; push address of gone counter
call changeState
pop eax ; return status of Pin 1
push eax ; make space to store variable
push eax ; push status of Pin 1
mov eax, dword[current]
push eax ; push current time
mov eax, dword[latest]
push eax ; push latest time
mov eax, here
push eax ; push address of here counter
mov eax, gone
push eax ; push address of gone counter
call update ; updates time counters
pop eax
call setPin13 ; set Pin 13 to value in al
mov eax, dword[here]
push eax ; push here time counter
mov eax, dword[gone]
push eax ; push gone time counter
call monitor
.time: call timeofDay
cmp eax, dword[current]
je .time
mov dword[current], eax
call print_nl
jmp .for
;;; return to C program
.exit:
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
;;; ; ----------------------------------------------------------------
;;; ; delay 100 ms.
;;; ; ----------------------------------------------------------------
delay100ms:
pushad
mov ecx, 100000000 ; 200,000,000 cycles (assuming 2GHz)
.for add eax, 1 ; 1 cycle
loop .for ; 1 cycle
popad
ret
;;; ; ----------------------------------------------------------------
;;; ; readPin1: sends the arduino a request for value of pins
;;; ; if Pin1 < 100,
;;; ; al = '0'
;;; ; else al = '1'
;;; ; ----------------------------------------------------------------
readPin1:
mov eax, msg3
mov ecx, msg3len ; "r a" read analog pins
call copyMsg ; now buf contains "r a"
call serialport_write
call serialport_read_until
;; call displayBuffer
mov al, [buf+8]
cmp al, 0x20
je .far
mov al,'1'
jmp .done
.far: mov al, '0'
.done:
ret
;;; ; ----------------------------------------------------------------
;;; ; SetPin13: sets pin 13 to the value '0' or '1' passed in al
;;; ; ----------------------------------------------------------------
setPin13:
pushad
mov byte[msg4val], al ; and embed '0' or '1' at right place
mov eax, msg4
mov ecx, msg4len ; copy msg4 in buf
call copyMsg
;; call displayBuffer
call serialport_write ; send message "w d 13 x" to arduino
popad ; restore registers
ret
;;; ; ----------------------------------------------------------------
;;; ; timeofDay: sets eax = current # seconds since Jan 1st, 1970
;;; ; ----------------------------------------------------------------
timeofDay:
mov eax, 78
mov ebx, tvsec
mov ecx, 0
int 0x80
mov eax, [tvsec]
ret
;;; ; ----------------------------------------------------------------
;;; ; update: updates the time counters
;;; ; ----------------------------------------------------------------
update:
push ebp
mov ebp, esp
sub esp, 4
%define return dword[ebp+28] ; will push status of pin after
%define pin dword[ebp+24] ; status of pin1
%define time dword[ebp+20] ; current time
%define latest dword[ebp+16] ; latest time of at/away from computer
%define near dword[ebp+12] ; address of time counter
%define far dword[ebp+8] ; address of time counter
%define diff dword[ebp-4] ; difference = current - latest
;; find difference between latest and current times
push eax
mov eax, time
sub eax, latest
mov diff, eax
pop eax
;; determines if user is at computer or not
cmp pin, '0'
je .notHere ; if user not at computer
cmp pin, '1'
je .here ; if user at computer
print2 "error!"
call print_nl
jmp .exit
.notHere: ; update "far" counter
push eax
push ebx
mov ebx, far
mov eax, diff
mov dword[ebx], eax ; far counter = difference in time
pop ebx
pop eax
jmp .exit
.here: ; update "near" counter
call print_nl
push eax
push ebx
mov eax, near
mov ebx, diff
mov dword[eax], ebx ; near counter = difference in time
pop ebx
pop eax
.exit:
push eax
mov eax, pin
mov return, eax
pop eax
mov esp, ebp
pop ebp
ret 20
;;; ; ----------------------------------------------------------------
;;; ; changeState: if user leaves/returns to computer
;;; ; ----------------------------------------------------------------
changeState:
push ebp
mov ebp, esp
%define return dword[ebp+32] ; will push status afterwards
%define pin1 dword[ebp+28] ; status of pin 1
%define lataddr dword[ebp+24] ; adrress of latest time
%define current dword[ebp+20] ; current time
%define oldaddr dword[ebp+16] ; address of old status of pin 1
%define near dword[ebp+12] ; address of time counter
%define far dword[ebp+8] ; address of time counter
push eax
push ebx
mov eax, oldaddr
mov ebx, [eax]
cmp ebx, pin1 ; compare old al and new al
je .done
;; set latest time to be current time
mov eax, lataddr ; eax = &latest
mov ebx, current ; ebx = current time
mov dword[eax], ebx ; latest time = current time
;; resets value of old al (status of pin1)
mov eax, oldaddr ; eax = &oldal
mov ebx, pin1
mov dword[eax], ebx ; oldal = new al
;; set both time counters to 0
mov eax, near
mov dword[eax], 0
mov eax, far
mov dword[eax], 0
;; record information in data.txt
mov eax, pin1
push eax
mov eax, current
push eax
call writeToFile
.done:
;; put status of pin1 status back in top spot
mov eax, pin1
mov return, eax
pop ebx
pop eax
pop ebp
ret 24
;;; ; ----------------------------------------------------------------
;;; ; monitor: monitors how long the user has been at the computer
;;; ; ----------------------------------------------------------------
monitor:
push ebp
mov ebp, esp
%define here dword[ebp+12]
%define gone dword[ebp+8]
;; call clrScreen
cmp here, 0
je .gone
.here:
push eax
mov eax, dword[MAXHERE]
cmp eax, here
ja .hereLow
mov eax, leavemsg
call print_string
call print_nl
;; print2 0x07 ; this SHOULD make console beep
pop eax
jmp .done
.hereLow:
sub eax, here
call print_int
mov eax, timemsg
call print_string
call print_nl
pop eax
jmp .done
.gone:
push eax
mov eax, dword[MINGONE]
cmp eax, gone
ja .goneLow
print2 "You can come back now!"
call print_nl
pop eax
jmp .done
.goneLow:
sub eax, gone
call print_int
mov eax, timemsg
call print_string
call print_nl
pop eax
jmp .done
.done: pop ebp
ret 8
;;; ; ----------------------------------------------------------------
;;; ; clrScreen: clears the screen and brings the cursor
;;; ; to "home" position. This is done by using ANSI sequences
;;; ; that, when sent to the screen, do not actually print
;;; ; anything, but instead modify different things, such as
;;; ; the position of the cursor, the contents of the screen,
;;; ; or other screen-related properties. All ansi sequences
;;; ; start with Ascii 27, which is the ESCape character.
;;; ; ----------------------------------------------------------------
clrScreen:
pushad ; save all registers
mov eax,4
mov ebx,1
lea ecx,[home]
mov edx,homeLen
int 0x80
popad ; restore all registers
ret
;;; ; ----------------------------------------------------------------
;;; ; writeToFile: writes the current state change to data.txt
;;; ; having difficulties writing to the file
;;; ; ----------------------------------------------------------------
writeToFile:
push ebp
mov ebp, esp
%define pin1 dword[ebp+12]
%define time dword[ebp+8]
;; store current contents of file in fbuffer
openFile fileName, O_RDWR, [handle]
readFile [handle], fbuffer, MAXBUF, [noRead]
close [handle]
push eax
push ebx
mov eax, [noRead]
call print_int
call print_nl
cmp pin1, '0'
jne .present
.disappeared:
mov byte[fbuffer+eax], 'l'
mov byte[fbuffer+eax+1], 'e'
mov byte[fbuffer+eax+2], 'f'
mov byte[fbuffer+eax+3], 't'
mov byte[fbuffer+eax+4], " "
mov ebx, time
mov dword[fbuffer+eax+5], ebx
mov byte[fbuffer+eax+9], 0x0a
add eax, 10
mov ebx, eax
jmp .done
.present:
mov byte[fbuffer+eax], 'r'
mov byte[fbuffer+eax+1], 'e'
mov byte[fbuffer+eax+2], 't'
mov byte[fbuffer+eax+3], 'u'
mov byte[fbuffer+eax+4], 'r'
mov byte[fbuffer+eax+5], 'n'
mov byte[fbuffer+eax+6], 'e'
mov byte[fbuffer+eax+7], 'd'
mov byte[fbuffer+eax+8], " "
mov ebx, time
mov dword[fbuffer+eax+9], ebx
mov byte[fbuffer+eax+13], 0x0a
add eax, 14
mov ebx, eax
.done:
createFile fileName, [handle]
writeFile [handle], fbuffer, ebx
close [handle]
pop ebp
ret 8