Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;
- ; FirstArduinoProject.asm
- ;
- ; Created: 4/25/2016 5:38:18 PM
- ; Author : Oscar Wennergren, Herman Nylén, Eric Johnsson
- ;
- ;[En lista med registerdefinitioner]
- .DEF rTemp = r16
- .DEF rTemp2 = r21
- .DEF rTemp3 = r23
- .DEF rUpdateFlag = r25
- .DEF rUpdateDelay = r24
- .DEF rColumn = r22
- .DEF rRow = r18
- .DEF rDirection = r20
- ;[En lista med konstanter]
- .EQU NUM_COLUMNS = 8
- .EQU MAX_LENGTH = 25
- .EQU START_X = 0b00000001
- .EQU START_Y = 0b00000001
- ;[Datasegmentet]
- .DSEG
- matrix: .BYTE NUM_COLUMNS
- snake: .BYTE MAX_LENGTH+1
- fruit: .BYTE 2
- snake_length: .BYTE 1
- .CSEG
- .org 0x0000
- jmp init
- nop
- .org 0x0020
- jmp tick
- nop
- ;
- ; Sätter stackpekaren på rätt position, startar timern samt sätter analog-digital konverteraren till att
- ; använda 8-bit register som resultat.
- ;
- init:
- sei
- ldi rTemp, HIGH(RAMEND)
- out SPH, rTemp
- ldi rTemp, LOW(RAMEND)
- out SPL, rTemp
- ldi rTemp, 0b01100000
- sts ADMUX,rTemp
- ldi rTemp,0b10000111
- sts ADCSRA,rTemp
- lds rTemp, TCCR0B
- ori rTemp, 0b00000110
- sts 0x45,r17
- ldi rTemp, (1<<TOIE0)
- lds rTemp2, TIMSK0
- or rTemp, rTemp2
- sts TIMSK0, rTemp
- ;
- ; Används för att sätta rätt I/O portar som aktiva, sätta längden på ormen till initiala värdet samt
- ; nollsätta nästintill alla register som kan tänkas användas under exekvering.
- ; Kallar sedan på funktionen populate och hoppar vidare till metoden för att ta hand om spelet.
- ;
- reset:
- ldi rTemp, 0b00001111
- out DDRC, rTemp
- ldi rTemp, 0b11111100
- out DDRD, rTemp
- ldi rTemp, 0b00111111
- out DDRB, rTemp
- ldi ZH, HIGH(snake_length)
- ldi ZL, LOW(snake_length)
- ldi rTemp, 3
- st Z, rTemp
- ldi rTemp, 0
- ldi rTemp2, 0
- ldi rTemp3, 0
- ldi rUpdateDelay, 0
- ldi rUpdateFlag, 0
- ldi rDirection, 0b0001
- rcall populate
- nop
- jmp print
- nop
- ;
- ; Laddar in värden i listan med delar för ormen samt skapar en frukt.
- ; Genom att använda sig av en lista med både frukter och kroppsdelar till ormen så
- ; är det enklare i ett senare skede att märka av kollisioner mellan ormen och frukter.
- ;
- populate:
- ldi ZH, HIGH(snake)
- ldi ZL, LOW(snake)
- ldi rTemp, 0b00001000
- std Z+0, rTemp
- ldi rTemp, 0b00010000
- std Z+1, rTemp
- ldi rTemp, 0b00001000
- std Z+2, rTemp
- ldi rTemp, 0b00100000
- std Z+3, rTemp
- ldi rTemp, 0b00001000
- std Z+4, rTemp
- ldi rTemp, 0b01000000
- std Z+5, rTemp
- ldi rTemp, 0
- std Z+6, rTemp
- std Z+7, rTemp
- ldi ZH, HIGH(fruit)
- ldi ZL, LOW(fruit)
- ldi rTemp, 0b00000010
- std Z+0, rTemp
- ldi rTemp, 0b00000100
- std Z+1, rTemp
- rcall resetMatrix
- nop
- ret
- ;
- ; Använder sig av olika temp-register som har skapats för att skriva data till de portarna där
- ; LED-matrisen befinner sig. Därefter "väntar" den några cykler genom att räkna upp till 90.
- ; Detta är ej en "snygg" lösning, skulle gå att använda sig av samma register som resten av koden använder sig av
- ; som förlitar sig på avbrott från timern. Problemet som uppstod var att både räkna antalet gånger som avbrott hade
- ; registrerats samt hantera att ett avbrott faktiskt hade skett. Detta hade kunnat lösas genom att enbart använda sig
- ; av en rUpdateDelay och inte använda sig av rUpdateFlag, för att sedan enbart öka rUpdateDelay med ett.
- ; Vi gjorde aldrig detta då denna lösning fungerade och den här lösningen disktuterades först i slutet av projektet.
- ;
- printAndReset:
- out PORTC, rTemp
- out PORTD, rTemp2
- out PORTB, rTemp3
- ldi rTemp, 0b0
- ldi rTemp2, 0b0
- ldi rTemp3, 0b0
- resetLoop:
- inc rTemp
- cpi rTemp, 90
- brlo resetLoop
- nop
- ldi rTemp, 0
- ret
- ;
- ; Följande subrutin används för att räkna om vår data som vi lagrar för koordinater
- ; till användbar data som kan skrivas till portarna som hanterar LED-matrisen.
- ; Vi sparar datan som binärtal, där en 1:a symboliserar en tänd LED och en 0:A symboliserar en släckt LED:
- ; Men eftersom portarna ligger förskjutna samt att alla rader/kolumner ej ligger på samma portar, så behövde
- ; vi skriva ut de på olika portar. Denna subrutin tar enbart hand om kolumnerna medan raderna är hårdkodade i
- ; subrutinen "print".
- ;
- calcColumn:
- push rTemp
- mov rTemp, rColumn
- andi rTemp, 0b00000011
- ldi rTemp2, 64
- mul rTemp, rTemp2
- movw rTemp, r0
- mov rTemp2, rTemp
- mov rTemp, rColumn
- andi rTemp, 0b11111100
- ror rTemp
- ror rTemp
- mov rTemp3, rTemp
- pop rTemp
- ret
- ;
- ; Gör som namnet antyder, återställer matrisen som lagrar vilka LEDs som skall tändas.
- ; Värt att notera, denna matris är ej densamma som LED-matrisen, utan denna är lagrad i minnet
- ; Medan LED-matrisen är den fysiska 8x8-matrisen med LEDs.
- ;
- resetMatrix:
- ldi YH, HIGH(matrix)
- ldi YL, LOW(matrix)
- ldi rTemp, 0b0
- std Y+0, rTemp
- std Y+1, rTemp
- std Y+2, rTemp
- std Y+3, rTemp
- std Y+4, rTemp
- std Y+5, rTemp
- std Y+6, rTemp
- std Y+7, rTemp
- ret
- ;
- ; Denna subrutin börjar med anropa subrutinen som återställer matrisen till
- ; en tom matris, sedan anropar den en subrutin som fyller denna matris med data
- ; som vi skall sedan använda för att tänka LEDs.
- ; Subrutinen börjar med att läsa om första raden i matrisen, anropar subrutinen som konverterar
- ; den raden till användbar data, anropar den subrutin som skriver ut data till portarna för LED-matrisen
- ; och släcker sedan den första raden. Subrutinen upprepar sedan detta för alla rader.
- ; Slutligen kollar subrutinen ifall det har skett ett avbrott från timern, om det har gjort det så hoppar den till
- ; en subrutin som skall ta hand om detta.
- ;
- print:
- rcall resetMatrix
- nop
- rcall dataToMatrix
- nop
- ldi YH, HIGH(matrix)
- ldi YL, LOW(matrix)
- ldi rTemp, 0
- ldi rTemp2, 0
- ldi rTemp3, 0
- ldd rColumn, Y+0
- rcall calcColumn
- nop
- ori rTemp, 0b00000001
- rcall printAndReset
- nop
- cbi PORTC, 0
- ldd rColumn, Y+1
- rcall calcColumn
- nop
- ori rTemp, 0b00000010
- rcall printAndReset
- nop
- cbi PORTC, 1
- ldd rColumn, Y+2
- rcall calcColumn
- nop
- ori rTemp, 0b00000100
- rcall printAndReset
- nop
- cbi PORTC, 2
- ldd rColumn, Y+3
- rcall calcColumn
- nop
- ori rTemp, 0b00001000
- rcall printAndReset
- nop
- cbi PORTC, 3
- ldd rColumn, Y+4
- rcall calcColumn
- nop
- ori rTemp2, 0b00000100
- rcall printAndReset
- nop
- cbi PORTD, 2
- ldd rColumn, Y+5
- rcall calcColumn
- nop
- ori rTemp2, 0b00001000
- rcall printAndReset
- nop
- cbi PORTD, 3
- ldd rColumn, Y+6
- rcall calcColumn
- nop
- ori rTemp2, 0b00010000
- rcall printAndReset
- nop
- cbi PORTD, 4
- ldd rColumn, Y+7
- rcall calcColumn
- nop
- ori rTemp2, 0b00100000
- rcall printAndReset
- nop
- cbi PORTD, 5
- cpi rUpdateFlag, 1
- breq gameloop
- nop
- jmp print
- nop
- ret
- ;
- ; Subrutin som ansvarar för att nollställa avbrottsflaggan
- ; och anropa andra subrutiner om tillräckligt många avbrott har skett.
- ;
- gameloop:
- ldi rUpdateFlag, 0
- inc rUpdateDelay
- cpi rUpdateDelay, 5
- breq updateSnake
- nop
- jmp print
- nop
- ;
- ; Subrutin för att uppdatera ormen.
- ; Den anropar en subrutin som läser av den analoga joysticken,
- ; en annan som kollar om ormen har kolliderat med något, sedan anropar den en subrutin som
- ; flyttar ormen. Sedan anropar den en subrutin som kollar om ormen har ätit sig själv, för att
- ; därefter hoppa tillbaka till den subrutinen som tar hand om belysningen av LED-matrisen.
- ;
- updateSnake:
- ldi rUpdateDelay, 0
- rcall readStick
- nop
- rcall detectCollision
- nop
- rcall moveSnake
- nop
- rcall snakeAteItself
- nop
- jmp print
- nop
- ;
- ; En subrutin för att kolla om ormens huvud har kolliderat med en frukt.
- ; I och med att vi enbart har en frukt aktiv så behöver vi enbart jämföra
- ; huvudets plats med fruktens plats. Detta gör denna subrutin väldigt simpel
- ; och snabb. Om den dock identiferar en kollision så kommer subrutinen att anropa
- ; en annan subrutin som ändrar positionen av frukten och en annan som får ormen att
- ; växa.
- ;
- detectCollision:
- rcall findSnakeHead
- ldi ZH, HIGH(fruit)
- ldi ZL, LOW(fruit)
- ldd rTemp, Y+0
- ldd rTemp2, Z+0
- cp rTemp, rTemp2
- breq collisionX
- nop
- jmp noCollision
- nop
- collisionX:
- ldd rTemp, Y+1
- ldd rTemp2, Z+1
- cp rTemp, rTemp2
- brne noCollision
- nop
- rcall generateRandomPoint
- nop
- rcall snakeWillGrow
- nop
- noCollision:
- ret
- ;
- ; Används för att få ormen att växa. Sker enbart när ormen har
- ; ätit en frukt. Kommer att jämföra ormens längd med 12, vilket är den
- ; storleken som vi har suttit som max (MAX_LENGTH+1 / 2), om den är lika stor som
- ; max längden så kommer ormen ej att växa.
- ; Den lägger till en kroppsdel framför huvudet och gör denna till det nya huvudet.
- ; Därefter så anropar den en subrutin som kommer att flytta huvudet baserat på den nuvarande
- ; riktingen som användaren har valt. Sedan kolla om detta resulterade i att ormen åt sig själv
- ; för att slutligen hoppa tillbaka till subrutinen som tar hand om belysningen.
- ;
- snakeWillGrow:
- rcall findSnakeHead
- nop
- ldi ZH, HIGH(snake_length)
- ldi ZL, LOW(snake_length)
- ld rTemp, Z
- ldi rTemp2, 12
- cp rTemp, rTemp2
- breq noGrow
- nop
- ldd rTemp, Y+0
- ldd rTemp2, Y+1
- std Y+2, rTemp
- std Y+3, rTemp2
- ldi rTemp, 0
- std Y+4, rTemp
- std Y+5, rTemp
- ld rTemp, Z
- inc rTemp
- st Z, rTemp
- adiw Y, 2
- rcall moveBasedOnDirection
- nop
- rcall snakeAteItself
- nop
- jmp print
- nop
- noGrow:
- ret
- ;
- ; Kollar om ormens huvud ligger på samma plats som en annan kroppsdel. Om den gör det
- ; så skall spelet resetas, annars returnar subrutinen.
- ;
- snakeAteItself:
- rcall findSnakeHead
- nop
- ldi ZH, HIGH(snake_length)
- ldi ZL, LOW(snake_length)
- ld rTemp, Z
- ldi ZH, HIGH(snake)
- ldi ZL, LOW(snake)
- ldi rTemp2, 0
- subi rTemp, 1
- detectSelfkill:
- cp rTemp, rTemp2
- breq endOfSelfkill
- nop
- push rTemp
- push rTemp2
- ldd rTemp, Z+0
- ldd rTemp2, Y+0
- cp rTemp, rTemp2
- breq XIsTheSame
- nop
- jmp nextBodyPart
- nop
- XIsTheSame:
- ldd rTemp, Z+1
- ldd rTemp2, Y+1
- cp rTemp, rTemp2
- brne nextBodyPart
- nop
- jmp reset
- nop
- nextBodyPart:
- adiw Z, 2
- pop rTemp2
- pop rTemp
- inc rTemp2
- jmp detectSelfkill
- nop
- endOfSelfkill:
- ret
- ;
- ; Simpel subrutin som hämtar positionen av ormens huvud.
- ; Resultaten kommer att sparas i Y.
- ; Istället för att leta efter en instans av '0', så kommer
- ; den att iterera och lägga till 2 på Y lika många gånger
- ; som snake_length.
- ;
- findSnakeHead:
- push rTemp
- push rTemp2
- ldi YH, HIGH(snake)
- ldi YL, LOW(snake)
- ldi ZH, HIGH(snake_length)
- ldi ZL, LOW(snake_length)
- ldi rTemp2, 0
- ld rTemp, Z
- subi rTemp, 1
- snakeHeadLoop:
- cp rTemp, rTemp2
- breq foundSnakeHead
- dec rTemp
- adiw Y, 2
- jmp snakeHeadLoop
- nop
- foundSnakeHead:
- pop rTemp2
- pop rTemp
- ret
- ;
- ; Flyttar alla kroppsdelar så att deras värde blir
- ; detsamma som kroppsdelen efter. Detta görs tills det hittas en 0:a.
- ; Detta gör så att den sista delen av ormen kommer att ha två instanser,
- ; så då anropas subrutinen som tar hand om förflyttningen baserat på riktningen
- ; som användaren har valt.
- ;
- moveSnake:
- rcall findSnakeHead
- nop
- moveSnakeList:
- ldi ZH, HIGH(snake)
- ldi ZL, LOW(snake)
- moveSnakeLoop:
- ldd rTemp, Z+2
- std Z+0, rTemp
- ldd rTemp, Z+3
- std Z+1, rTemp
- ldd rTemp, Z+4
- cpi rTemp, 0
- breq moveLoop
- nop
- adiw Z, 2
- jmp moveSnakeLoop
- nop
- moveLoop:
- rcall moveBasedOnDirection
- nop
- ret
- ;
- ; Flyttar huvudet i det håller som användaren har bestämt.
- ; Hade varit bättre att implementera ett jump-table, men detta insågs alldeles för sent.
- ; Denna metod tar även hand om scenariot där ormen försöker förflytta sig utanför matrisen och
- ; sätter istället koordinaten till att bli den "omvända". Förtydligande:
- ; Om den är på 8 och försöker gå till 9, kommer den istället sättas till 1.
- ; Detta gör så att användaren ej kan dö om den åker in i väggarna, vilket kan vara
- ; bra på en så pass liten spelplan.
- ;
- moveBasedOnDirection:
- cpi rDirection, 0b00000001
- breq moveDown
- nop
- cpi rDirection, 0b00000010
- breq moveUp
- nop
- cpi rDirection, 0b00000100
- breq moveLeft
- nop
- cpi rDirection, 0b00001000
- breq moveRight
- nop
- jmp noMove
- nop
- moveDown:
- ldd rTemp, Y+1
- rol rTemp
- cpi rTemp, 0
- breq YTo0
- nop
- std Y+1, rTemp
- jmp moveEnd
- nop
- moveUp:
- ldd rTemp, Y+1
- ror rTemp
- cpi rTemp, 0
- breq YTo7
- nop
- std Y+1, rTemp
- jmp moveEnd
- nop
- YTo7:
- ldi rTemp, 0b10000000
- std Y+1, rTemp
- jmp moveEnd
- nop
- YTo0:
- ldi rTemp, 0b01
- std Y+1, rTemp
- jmp moveEnd
- nop
- moveLeft:
- ldd rTemp, Y+0
- rol rTemp
- cpi rTemp, 0
- breq XTo0
- nop
- std Y+0, rTemp
- jmp moveEnd
- nop
- moveRight:
- ldd rTemp, Y+0
- ror rTemp
- cpi rTemp, 0
- breq Xto7
- nop
- std Y+0, rTemp
- jmp moveEnd
- nop
- XTo7:
- ldi rTemp, 0b10000000
- std Y+0, rTemp
- jmp moveEnd
- nop
- XTo0:
- ldi rTemp, 0b01
- std Y+0, rTemp
- jmp moveEnd
- nop
- moveEnd:
- jmp noMove
- nop
- noMove:
- ret
- ;
- ; Läser in data från den analoga joysticken, maskar ut de tre sista bitarna
- ; kastar ordningen på dessa bitar för att sedan konvertera om dem till data
- ; som kan sparas som en koordinat i vår frukt.
- ; Subrutinen kommer även att kontrollera om det är en koordinat som vi kan använda,
- ; om den ej är det så kommer den att försöka generera en ny koordinat.
- ;
- generateRandomPoint:
- ldi ZH, HIGH(fruit)
- ldi ZL, LOW(fruit)
- ldi rTemp, 0b00000100
- lds rTemp2, ADMUX
- andi rTemp2, 0b11111000
- or rTemp2, rTemp
- sts ADMUX, rTemp2
- ldi rTemp, (1<<ADSC)
- lds rTemp2, ADCSRA
- or rTemp2, rTemp
- sts ADCSRA, rTemp2
- randomYWait:
- lds rTemp, ADCSRA
- sbrc rTemp, 6
- jmp randomYWait
- lds rTemp, ADCH
- rcall randomY
- nop
- ldi rTemp, 0b00000101
- lds rTemp2, ADMUX
- andi rTemp2, 0b11111000
- or rTemp2, rTemp
- sts ADMUX, rTemp2
- ldi rTemp, (1<<ADSC)
- lds rTemp2, ADCSRA
- or rTemp2, rTemp
- sts ADCSRA, rTemp2
- randomXPoint:
- lds rTemp, ADCSRA
- sbrc rTemp, 6
- jmp randomXPoint
- lds rTemp, ADCH
- rcall randomX
- nop
- validPoint:
- ldi ZH, HIGH(snake_length)
- ldi ZL, LOW(snake_length)
- ld rTemp, Z
- ldi ZH, HIGH(snake)
- ldi ZL, LOW(snake)
- ldi YH, HIGH(fruit)
- ldi YL, LOW(fruit)
- ldi rTemp2, 0
- subi rTemp, 1
- validLoop:
- cp rTemp, rTemp2
- breq endOfValid
- nop
- push rTemp
- push rTemp2
- ldd rTemp, Z+0
- ldd rTemp2, Y+0
- cp rTemp, rTemp2
- breq invalidX
- nop
- jmp nextSnakePart
- nop
- invalidX:
- ldd rTemp, Z+1
- ldd rTemp2, Y+1
- cp rTemp, rTemp2
- breq notValidPoint
- nop
- jmp nextSnakePart
- nop
- nextSnakePart:
- pop rTemp2
- pop rTemp
- inc rTemp2
- adiw Z, 2
- jmp validLoop
- nop
- endOfValid:
- ret
- notValidPoint:
- ldi rTemp, 0b00000100
- lds rTemp2, ADMUX
- andi rTemp2, 0b11111000
- or rTemp2, rTemp
- sts ADMUX, rTemp2
- ldi rTemp, (1<<ADSC)
- lds rTemp2, ADCSRA
- or rTemp2, rTemp
- sts ADCSRA, rTemp2
- ;
- ; Hämtar data från joysticken och skickar vidare den så att det kan sparas
- ; som en koordinat.
- ;
- nextRandomYWait:
- lds rTemp, ADCSRA
- sbrc rTemp, 6
- jmp nextRandomYWait
- lds rTemp, ADCH
- andi rTemp, 0b11110000
- ror rTemp
- ror rTemp
- ror rTemp
- ror rTemp
- rcall randomY
- nop
- ldi rTemp, 0b00000101
- lds rTemp2, ADMUX
- andi rTemp2, 0b11111000
- or rTemp2, rTemp
- sts ADMUX, rTemp2
- ldi rTemp, (1<<ADSC)
- lds rTemp2, ADCSRA
- or rTemp2, rTemp
- sts ADCSRA, rTemp2
- nextRandomXPoint:
- lds rTemp, ADCSRA
- sbrc rTemp, 6
- jmp nextRandomXPoint
- lds rTemp, ADCH
- andi rTemp, 0b11110000
- ror rTemp
- ror rTemp
- ror rTemp
- ror rTemp
- rcall randomX
- nop
- jmp validLoop
- nop
- ;
- ; Kastar om datan så att den ser mer "slumpmartad" ut.
- ;
- randomX:
- ldi ZH, HIGH(fruit)
- ldi ZL, LOW(fruit)
- andi rTemp, 0b00000111
- ldi rTemp2, 0
- bst rTemp, 0
- bld rTemp2, 2
- bst rTemp, 1
- bld rTemp2, 0
- bst rTemp, 2
- bld rTemp2, 1
- ldi rTemp, 0
- ldi rTemp3, 0b00000001
- randomXCalc:
- cp rTemp2, rTemp
- breq storeRandomXPoint
- nop
- inc rTemp
- rol rTemp3
- jmp randomXCalc
- nop
- storeRandomXPoint:
- std Z+0, rTemp3
- ret
- randomY:
- ldi ZH, HIGH(fruit)
- ldi ZL, LOW(fruit)
- andi rTemp, 0b00000111
- ldi rTemp2, 0
- bst rTemp, 0
- bld rTemp2, 2
- bst rTemp, 1
- bld rTemp2, 1
- bst rTemp, 2
- bld rTemp2, 0
- ldi rTemp, 0
- ldi rTemp3, 0b00000001
- randomYCalc:
- cp rTemp2, rTemp
- breq storeRandomYPoint
- nop
- inc rTemp
- rol rTemp3
- jmp randomYCalc
- nop
- storeRandomYPoint:
- std Z+1, rTemp3
- ret
- ;
- ; Läser av joysticken och sätter rDirection baserat på vilket håll joysticken är åt.
- ; Den kontrollerar även om den nuvarande rDirection är motsatsen till det som den försöker sätta den till,
- ; i såna fall så skall ej rDirection uppdateras. Detta gör så att ormen ej kan vända sig in i sig själv.
- ;
- readStick:
- ldi rTemp, 0b00000100
- lds rTemp2, ADMUX
- andi rTemp2, 0b11111000
- or rTemp2, rTemp
- sts ADMUX, rTemp2
- ldi rTemp, (1<<ADSC)
- lds rTemp2, ADCSRA
- or rTemp2, rTemp
- sts ADCSRA, rTemp2
- YWait:
- lds rTemp, ADCSRA
- sbrc rTemp, 6
- jmp YWait
- lds rTemp, ADCH
- std Y+0, rTemp
- cpi rTemp, 0b11111000
- brsh yUp
- nop
- cpi rTemp, 0b00000111
- brlo yDown
- nop
- jmp XLoop
- nop
- yDown:
- cpi rDirection, 0b010
- breq stickEnd
- nop
- ldi rDirection, 0b001
- ret
- yUp:
- cpi rDirection, 0b001
- breq stickEnd
- nop
- ldi rDirection, 0b010
- ret
- XLoop:
- ldi rTemp, 0b00000101
- lds rTemp2, ADMUX
- andi rTemp2, 0b11111000
- or rTemp2, rTemp
- sts ADMUX, rTemp2
- ldi rTemp, (1<<ADSC)
- lds rTemp2, ADCSRA
- or rTemp2, rTemp
- sts ADCSRA, rTemp2
- XWait:
- lds rTemp, ADCSRA
- sbrc rTemp, 6
- jmp XWait
- lds rTemp, ADCH
- cpi rTemp, 0b11111000
- brsh xLeft
- nop
- cpi rTemp, 0b00000111
- brlo xRight
- nop
- jmp stickEnd
- nop
- xLeft:
- cpi rDirection, 0b0100
- breq stickEnd
- nop
- ldi rDirection, 0b1000
- jmp stickEnd
- nop
- xRight:
- cpi rDirection, 0b1000
- breq stickEnd
- nop
- ldi rDirection, 0b0100
- jmp stickEnd
- nop
- stickEnd:
- ret
- ;
- ; Används för att visa att ett avbrott har skett.
- ;
- tick:
- ldi rUpdateFlag, 1
- reti
- ;
- ; Laddar in all data som ligger i snake-listan samt frukten in till matrisen.
- ;
- dataToMatrix:
- ldi ZH, HIGH(snake)
- ldi ZL, LOW(snake)
- dataLoop:
- ldi YH, HIGH(matrix)
- ldi YL, LOW(matrix)
- ldd rTemp, Z+1
- cpi rTemp, 0
- breq notInMatrix
- nop
- rowLoop:
- cpi rTemp, 1
- breq columnLoop
- nop
- ror rTemp
- adiw Y, 1
- jmp rowLoop
- nop
- columnLoop:
- ldd rTemp, Z+0
- cpi rTemp, 0
- breq notInMatrix
- nop
- ld rTemp2, Y
- or rTemp, rTemp2
- st Y, rTemp
- notInMatrix:
- adiw Z, 2
- ldd rTemp, Z+1
- cpi rTemp, 0
- breq yIsEmpty
- nop
- jmp dataLoop
- nop
- yIsEmpty:
- ldd rTemp, Z+0
- cpi rTemp, 0
- breq endOfSnake
- nop
- jmp dataLoop
- nop
- endOfSnake:
- ldi ZH, HIGH(fruit)
- ldi ZL, LOW(fruit)
- ;
- ; Kunde inte låta bli att döpa denna label till detta.
- ;
- fruityLoops:
- ldi YH, HIGH(matrix)
- ldi YL, LOW(matrix)
- ldd rTemp, Z+1
- cpi rTemp, 0
- breq noFruit
- nop
- fruitRowLoop:
- cpi rTemp, 1
- breq fruitColumnLoop
- nop
- ror rTemp
- adiw Y, 1
- jmp fruitRowLoop
- nop
- fruitColumnLoop:
- ldd rTemp, Z+0
- cpi rTemp, 0
- breq noFruit
- nop
- ld rTemp2, Y
- or rTemp, rTemp2
- st Y, rTemp
- noFruit:
- ret
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement