Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;still in the process of writing up comments, sorry if some parts don't make sense
- ;also some parts might not be needed, i didn't have enough time to thoroughly check
- ;what functions/lines of codes were doing nothing
- .include "m2560def.inc"
- .def temp = r16
- .def temp2 = r17
- .def ten = r18
- .def counter = r19
- .def lcd = r20 ;to handle the LCD
- .def digit = r21 ;register to display digits
- .def holes = r22 ;register for hole in the motor that we use to calculate speed
- ;(note for function EXT_INT2: there are 4 holes)
- .macro do_lcd_command
- ldi lcd, @0
- rcall lcd_command
- rcall lcd_wait
- .endmacro
- .macro do_lcd_data
- ldi lcd, @0
- rcall lcd_data
- rcall lcd_wait
- .endmacro
- ;need own register command because do_lcd_data does not work on registers
- .macro register_lcd_data
- mov lcd, @0
- subi lcd, -'0'
- rcall lcd_data
- rcall lcd_wait
- .endmacro
- ;clear a word from memory
- ;the parameter A0 is the memory address for that word #
- .macro clear
- ldi YL, low(@0) ; load the memory address to Y
- ldi YH, high(@0)
- clr temp
- st Y+, temp ; clear the two bytes at @0 in SRAM
- st Y, temp
- .endmacro
- .dseg
- TimerCounter: .byte 2 ;Temporary counter to see if 1 second has passed
- ;just dealing with vector table stuff here, used to be really long but i cleaned up some stuff
- .cseg
- .org 0x0000
- jmp RESET
- jmp DEFAULT ;interrupt request 0 not dealt with
- jmp DEFAULT ;interrupt request 1 not dealt with
- .org INT2addr ;INT2addr is the address of the ext interrupt request 2
- jmp EXT_INT2 ;jump to the interrupt handler for the external interrupt
- .org OVF0addr ;OVF0addr is the address of the timer0 overflow interrupt vector
- jmp Timer0OVF ;jump to the interrupt handler for timer0 overflow
- jmp DEFAULT
- DEFAULT:
- reti
- ;standard stuff
- RESET:
- clr holes ;clear holes on reset//make sure that we're not using previous value of holes prior
- ldi r16, low(RAMEND)
- out SPL, r16
- ldi r16, high(RAMEND)
- out SPH, r16
- ser temp ;Set temp to all 1's
- out DDRC,temp ;Set PortC to Output
- clr temp
- out PORTC, temp ;Set all LED's to 0
- sei
- ser r16 ;Set r16 all to 1's
- out DDRF, r16 ;Set PortF to Output
- out DDRA, r16 ;Set portA to Output
- clr r16 ;Setting r16 to 0
- out PORTF, r16
- out PORTA, r16
- do_lcd_command 0b00111000 ; 2x5x7
- rcall sleep_5ms
- do_lcd_command 0b00111000 ; 2x5x7
- rcall sleep_1ms
- do_lcd_command 0b00111000 ; 2x5x7
- do_lcd_command 0b00111000 ; 2x5x7
- do_lcd_command 0b00001000 ; display off?
- do_lcd_command 0b00000001 ; clear display
- do_lcd_command 0b00000110 ; increment, no display shift
- do_lcd_command 0b00001110 ; Cursor on, bar, no blink
- do_lcd_data 'S' ;make LCD display "Speed: "
- do_lcd_data 'p' ;was thinking of making it display units/second as well but too much effort
- do_lcd_data 'e'
- do_lcd_data 'e'
- do_lcd_data 'd'
- do_lcd_data ':'
- do_lcd_data ' '
- rjmp main
- incCounter:
- inc counter
- clr holes
- jmp back
- EXT_INT2:
- in temp, SREG
- push temp
- push ten
- inc holes
- cpi holes,4 ;check if 1 whole spin has occurred (because there are 4 holes)
- breq incCounter
- rjmp EXT_INT2
- END_INT2:
- pop ten
- pop temp
- out SREG, temp
- reti
- Timer0OVF: ;interrupt subroutine to Timer0
- in temp, SREG
- push temp
- push YH ;save conflicting registers
- push YL
- push r25
- push r24
- newSecond: ;load value of the temporary counter
- lds r24, TimerCounter
- lds r25, TimerCounter+1
- adiw r25:r24, 1 ;inc the temp counter by 1
- cpi r24, low(781) ;check if (r25:r24) = 781 (100ms) since 7812 = 10^6/128 (1s)
- ldi temp, high(781) ;7812 = 10^6/128
- cpc r25, temp
- brne notSecond
- isSecond: ;100ms is 781, since the counter is at 100ms
- do_lcd_command 0b00000001 ;Clear Display
- do_lcd_command 0b00000110 ;Increment, no display shift
- do_lcd_command 0b00001110 ;Cursor on, bar, no blink
- do_lcd_data 'S'
- do_lcd_data 'p'
- do_lcd_data 'e'
- do_lcd_data 'e'
- do_lcd_data 'd'
- do_lcd_data ':'
- do_lcd_data ' '
- rjmp display
- end:
- clr counter
- clear TimerCounter
- rjmp endIf
- notSecond: ;store new value
- sts TimerCounter, r24
- sts TimerCounter+1, r25
- endIf:
- pop r24 ;restore conflicting
- pop r25
- pop YL
- pop YH
- pop temp
- out SREG, temp
- reti
- main:
- clear TimerCounter
- clr counter
- clr digit
- ;external interrupt, mostly taken from prev. labs/lectures
- ldi temp, (2 << ISC20) ;Set INT0 as falling edge triggered interrupt
- sts EICRA, temp
- in temp, EIMSK ;Enable INT2
- ori temp, (1<<INT2)
- out EIMSK, temp
- ;timer 0
- ldi temp, 0b00000000 ;Loading 0 into a temp register
- out TCCR0A, temp ;Setting TCR0A to a input
- ldi temp, 0b00000010 ;Loading 8 into a temp register
- out TCCR0B, temp ;Setting prescalar value to 8
- ldi temp, 1<<TOIE0 ;TOIE0 is the bit number of TOIE0 which is 0 (128 microseconds)
- sts TIMSK0, temp ;Enale Timer0 overflow Interrupt (T/C0 interrupt enable)
- sei ;Enable Global Interrupt Bit
- loop:
- rjmp loop
- ;LED display
- display:
- ldi ten,10
- mul counter,ten ;multi counter*10 (Since we did 100ms, this is for 1 second)
- mov temp, r0
- out PORTC,temp ;display respective speed of LCD
- clr digit
- ifHundred:
- cpi temp, 100 ;check if number is >100
- brsh countHundred
- cpi digit, 0 ;check if digit is 0
- breq ifTen
- register_lcd_data digit
- clr digit
- ldi temp2,1
- ifTen:
- cpi temp, 10 ;if temp is >10
- brsh countTen
- cpi temp2, 1 ;else if temp2 is 1
- breq else
- cpi digit, 0
- breq checkOne
- else:
- register_lcd_data digit
- clr digit
- rjmp checkOne
- checkOne:
- register_lcd_data temp
- rjmp end
- countTen:
- subi temp, 10 ;subtract 10 from the speed
- inc digit ;inc digits to be displayed
- rjmp ifTen
- countHundred:
- subi temp, 100 ;subtract 100 from the speed
- inc digit ;incr the first digit to be displayed
- rjmp ifHundred
- ;standard lcd stuff
- .equ LCD_RS = 7
- .equ LCD_E = 6
- .equ LCD_RW = 5
- .equ LCD_BE = 4
- .macro lcd_set
- sbi PORTA, @0
- .endmacro
- .macro lcd_clr
- cbi PORTA, @0
- .endmacro
- ;slightly modified some bits to suit ports
- lcd_command:
- out PORTF, lcd ;Displaying contents stored in r20
- rcall sleep_1ms
- lcd_set LCD_E
- rcall sleep_1ms
- lcd_clr LCD_E
- rcall sleep_1ms
- ret
- lcd_data:
- out PORTF, lcd
- lcd_set LCD_RS
- rcall sleep_1ms
- lcd_set LCD_E
- rcall sleep_1ms
- lcd_clr LCD_E
- rcall sleep_1ms
- lcd_clr LCD_RS
- ret
- lcd_wait:
- push lcd ;so it doesn't conflict
- clr lcd
- out DDRF, lcd
- out PORTF, lcd
- lcd_set LCD_RW
- lcd_wait_loop:
- rcall sleep_1ms
- lcd_set LCD_E
- rcall sleep_1ms
- in lcd, PINF
- lcd_clr LCD_E
- sbrc lcd, 7
- rjmp lcd_wait_loop
- lcd_clr LCD_RW
- ser lcd
- out DDRF, lcd
- pop lcd ;restore
- ret
- ;delay stuff as normal
- .equ F_CPU = 16000000
- .equ DELAY_1MS = F_CPU / 4 / 1000 - 4 ;4 cycles per iteration - setup/call-return overhead
- sleep_1ms:
- push r24
- push r25
- ldi r25, high(DELAY_1MS)
- ldi r24, low(DELAY_1MS)
- delayloop_1ms:
- sbiw r25:r24, 1
- brne delayloop_1ms
- pop r25
- pop r24
- ret
- sleep_5ms:
- rcall sleep_1ms
- rcall sleep_1ms
- rcall sleep_1ms
- rcall sleep_1ms
- rcall sleep_1ms
- ret
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement