;;; 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