Advertisement
Guest User

Snaaaaaake.asm

a guest
May 29th, 2016
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ;
  2. ; FirstArduinoProject.asm
  3. ;
  4. ; Created: 4/25/2016 5:38:18 PM
  5. ; Author : Oscar Wennergren, Herman Nylén, Eric Johnsson
  6. ;
  7.  
  8. ;[En lista med registerdefinitioner]
  9. .DEF rTemp          = r16
  10. .DEF rTemp2         = r21
  11. .DEF rTemp3         = r23
  12. .DEF rUpdateFlag    = r25
  13. .DEF rUpdateDelay   = r24
  14. .DEF rColumn        = r22
  15. .DEF rRow           = r18
  16. .DEF rDirection     = r20
  17.  
  18. ;[En lista med konstanter]
  19. .EQU NUM_COLUMNS    = 8
  20. .EQU MAX_LENGTH     = 25
  21. .EQU START_X        = 0b00000001
  22. .EQU START_Y        = 0b00000001
  23. //.SET SNAKE_LENGTH = 3
  24. ;[Datasegmentet]
  25. .DSEG
  26. matrix:     .BYTE NUM_COLUMNS
  27. snake:      .BYTE MAX_LENGTH+1
  28. fruit:      .BYTE 2
  29. snake_length: .BYTE 1
  30.  
  31.  
  32. .CSEG
  33. .org 0x0000
  34.     jmp init
  35.     nop
  36. .org 0x0020
  37.     jmp tick
  38.     nop
  39.  
  40. /*
  41.  * Sätter stackpekaren på rätt position, startar timern samt sätter analog-digital konverteraren  till att
  42.  * använda 8-bit register som resultat.
  43. */
  44. init:
  45.     sei
  46.     ldi     rTemp, HIGH(RAMEND)
  47.     out     SPH, rTemp
  48.     ldi     rTemp, LOW(RAMEND)
  49.     out     SPL, rTemp
  50.  
  51.     ldi     rTemp, 0b01100000
  52.     sts     ADMUX,rTemp
  53.     ldi     rTemp,0b10000111
  54.     sts     ADCSRA,rTemp
  55.  
  56.     lds     rTemp, TCCR0B
  57.     ori     rTemp, 0b00000110
  58.     sts     0x45,r17
  59.  
  60.     ldi     rTemp, (1<<TOIE0)
  61.     lds     rTemp2, TIMSK0
  62.     or      rTemp, rTemp2
  63.     sts     TIMSK0, rTemp
  64.  
  65. /*
  66.  * 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
  67.  * nollsätta nästintill alla register som kan tänkas användas under exekvering.
  68.  * Kallar sedan på funktionen populate och hoppar vidare till metoden för att ta hand om spelet.
  69. */
  70.     reset:
  71.     ldi     rTemp, 0b00001111
  72.     out     DDRC, rTemp
  73.     ldi     rTemp, 0b11111100
  74.     out     DDRD, rTemp
  75.     ldi     rTemp, 0b00111111
  76.     out     DDRB, rTemp
  77.     ldi     ZH, HIGH(snake_length)
  78.     ldi     ZL, LOW(snake_length)
  79.     ldi     rTemp, 3
  80.     st      Z, rTemp
  81.     ldi     rTemp, 0
  82.     ldi     rTemp2, 0
  83.     ldi     rTemp3, 0
  84.     ldi     rUpdateDelay, 0
  85.     ldi     rUpdateFlag, 0
  86.     ldi     rDirection, 0b0001
  87.     rcall   populate
  88.     nop
  89.     jmp     print
  90.     nop
  91.  
  92. /*
  93.  * Laddar in värden i listan med delar för ormen samt skapar en frukt.
  94.  * Genom att använda sig av en lista med både frukter och kroppsdelar till ormen så
  95.  * är det enklare i ett senare skede att märka av kollisioner mellan ormen och frukter.
  96. */
  97. populate:
  98.     ldi     ZH, HIGH(snake)
  99.     ldi     ZL, LOW(snake)
  100.     ldi     rTemp, 0b00001000
  101.     std     Z+0, rTemp
  102.     ldi     rTemp, 0b00010000
  103.     std     Z+1, rTemp
  104.     ldi     rTemp, 0b00001000
  105.     std     Z+2, rTemp
  106.     ldi     rTemp, 0b00100000
  107.     std     Z+3, rTemp
  108.     ldi     rTemp, 0b00001000
  109.     std     Z+4, rTemp
  110.     ldi     rTemp, 0b01000000
  111.     std     Z+5, rTemp
  112.     ldi     rTemp, 0
  113.     std     Z+6, rTemp
  114.     std     Z+7, rTemp
  115.     ldi     ZH, HIGH(fruit)
  116.     ldi     ZL, LOW(fruit)
  117.     ldi     rTemp, 0b00000010
  118.     std     Z+0, rTemp
  119.     ldi     rTemp, 0b00000100
  120.     std     Z+1, rTemp
  121.     rcall   resetMatrix
  122.     nop
  123.     ret
  124.  
  125. /*
  126.  * Använder sig av olika temp-register som har skapats för att skriva data till de portarna där
  127.  * LED-matrisen befinner sig. Därefter "väntar" den några cykler genom att räkna upp till 90.
  128.  * Detta är ej en "snygg" lösning, skulle gå att använda sig av samma register som resten av koden använder sig av
  129.  * som förlitar sig på avbrott från timern. Problemet som uppstod var att både räkna antalet gånger som avbrott hade
  130.  * registrerats samt hantera att ett avbrott faktiskt hade skett. Detta hade kunnat lösas genom att enbart använda sig
  131.  * av en rUpdateDelay och inte använda sig av rUpdateFlag, för att sedan enbart öka rUpdateDelay med ett.
  132.  * Vi gjorde aldrig detta då denna lösning fungerade och den här lösningen disktuterades först i slutet av projektet.
  133. */
  134. printAndReset:
  135.     out     PORTC, rTemp
  136.     out     PORTD, rTemp2
  137.     out     PORTB, rTemp3
  138.     ldi     rTemp, 0b0
  139.     ldi     rTemp2, 0b0
  140.     ldi     rTemp3, 0b0
  141.     resetLoop:
  142.     inc     rTemp
  143.     cpi     rTemp, 90
  144.     brlo    resetLoop
  145.     nop
  146.     ldi     rTemp, 0
  147.     ret
  148.  
  149. /*
  150. * Följande subrutin används för att räkna om vår data som vi lagrar för koordinater
  151. * till användbar data som kan skrivas till portarna som hanterar LED-matrisen.
  152. * 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:
  153. * Men eftersom portarna ligger förskjutna samt att alla rader/kolumner ej ligger på samma portar, så behövde
  154. * vi skriva ut de på olika portar. Denna subrutin tar enbart hand om kolumnerna medan raderna är hårdkodade i
  155. * subrutinen "print".
  156. */
  157. calcColumn:
  158.     push    rTemp
  159.     mov     rTemp, rColumn
  160.     andi    rTemp, 0b00000011
  161.     ldi     rTemp2, 64
  162.     mul     rTemp, rTemp2
  163.     movw    rTemp, r0
  164.     mov     rTemp2, rTemp
  165.     mov     rTemp, rColumn
  166.     andi    rTemp, 0b11111100
  167.     ror     rTemp
  168.     ror     rTemp
  169.     mov     rTemp3, rTemp
  170.     pop     rTemp
  171.     ret
  172.  
  173. /*
  174.  * Gör som namnet antyder, återställer matrisen som lagrar vilka LEDs som skall tändas.
  175.  * Värt att notera, denna matris är ej densamma som LED-matrisen, utan denna är lagrad i minnet
  176.  * Medan LED-matrisen är den fysiska 8x8-matrisen med LEDs.
  177. */
  178. resetMatrix:
  179.     ldi     YH, HIGH(matrix)
  180.     ldi     YL, LOW(matrix)
  181.     ldi     rTemp, 0b0
  182.     std     Y+0, rTemp
  183.     std     Y+1, rTemp
  184.     std     Y+2, rTemp
  185.     std     Y+3, rTemp
  186.     std     Y+4, rTemp
  187.     std     Y+5, rTemp
  188.     std     Y+6, rTemp
  189.     std     Y+7, rTemp
  190.     ret
  191.  
  192. /*
  193. * Denna subrutin börjar med anropa subrutinen som återställer matrisen till
  194. * en tom matris, sedan anropar den en subrutin som fyller denna matris med data
  195. * som vi skall sedan använda för att tänka LEDs.
  196. * Subrutinen börjar med att läsa om första raden i matrisen, anropar subrutinen som konverterar
  197. * den raden till användbar data, anropar den subrutin som skriver ut data till portarna för LED-matrisen
  198. * och släcker sedan den första raden. Subrutinen upprepar sedan detta för alla rader.
  199. * Slutligen kollar subrutinen ifall det har skett ett avbrott från timern, om det har gjort det så hoppar den till
  200. * en subrutin som skall ta hand om detta.
  201. */
  202. print:
  203.     rcall   resetMatrix
  204.     nop
  205.     rcall   dataToMatrix
  206.     nop
  207.     ldi     YH, HIGH(matrix)
  208.     ldi     YL, LOW(matrix)
  209.     ldi     rTemp, 0
  210.     ldi     rTemp2, 0
  211.     ldi     rTemp3, 0
  212.     ldd     rColumn, Y+0
  213.     rcall   calcColumn
  214.     nop
  215.     ori     rTemp, 0b00000001
  216.     rcall   printAndReset
  217.     nop
  218.     cbi     PORTC, 0
  219.     ldd     rColumn, Y+1
  220.     rcall   calcColumn
  221.     nop
  222.     ori     rTemp, 0b00000010
  223.     rcall   printAndReset
  224.     nop
  225.     cbi     PORTC, 1
  226.  
  227.     ldd     rColumn, Y+2
  228.     rcall   calcColumn
  229.     nop
  230.     ori     rTemp, 0b00000100
  231.     rcall   printAndReset
  232.     nop
  233.     cbi     PORTC, 2
  234.  
  235.     ldd     rColumn, Y+3
  236.     rcall   calcColumn
  237.     nop
  238.     ori     rTemp, 0b00001000
  239.     rcall   printAndReset
  240.     nop
  241.     cbi     PORTC, 3
  242.  
  243.     ldd     rColumn, Y+4
  244.     rcall   calcColumn
  245.     nop
  246.     ori     rTemp2, 0b00000100
  247.     rcall   printAndReset
  248.     nop
  249.     cbi     PORTD, 2
  250.  
  251.     ldd     rColumn, Y+5
  252.     rcall   calcColumn
  253.     nop
  254.     ori     rTemp2, 0b00001000
  255.     rcall   printAndReset
  256.     nop
  257.     cbi     PORTD, 3
  258.  
  259.     ldd     rColumn, Y+6
  260.     rcall   calcColumn
  261.     nop
  262.     ori     rTemp2, 0b00010000
  263.     rcall   printAndReset
  264.     nop
  265.     cbi     PORTD, 4
  266.  
  267.     ldd     rColumn, Y+7
  268.     rcall   calcColumn
  269.     nop
  270.     ori     rTemp2, 0b00100000
  271.     rcall   printAndReset
  272.     nop
  273.     cbi     PORTD, 5
  274.  
  275.     cpi     rUpdateFlag, 1
  276.     breq    gameloop
  277.     nop
  278.     jmp     print
  279.     nop
  280.     ret
  281.  
  282. /*
  283.  * Subrutin som ansvarar för att nollställa avbrottsflaggan
  284.  * och anropa andra subrutiner om tillräckligt många avbrott har skett.
  285. */
  286. gameloop:
  287.     ldi     rUpdateFlag, 0
  288.     inc     rUpdateDelay
  289.     cpi     rUpdateDelay, 5
  290.     breq    updateSnake
  291.     nop
  292.     jmp     print
  293.     nop
  294.  
  295. /*
  296. * Subrutin för att uppdatera ormen.
  297. * Den anropar en subrutin som läser av den analoga joysticken,
  298. * en annan som kollar om ormen har kolliderat med något, sedan anropar den en subrutin som
  299. * flyttar ormen. Sedan anropar den en subrutin som kollar om ormen har ätit sig själv, för att
  300. * därefter hoppa tillbaka till den subrutinen som tar hand om belysningen av LED-matrisen.
  301. */
  302. updateSnake:
  303.     ldi     rUpdateDelay, 0
  304.     rcall   readStick
  305.     nop
  306.     rcall   detectCollision
  307.     nop
  308.     rcall   moveSnake
  309.     nop
  310.     rcall   snakeAteItself
  311.     nop
  312.     jmp     print
  313.     nop
  314.  
  315. /*
  316.  * En subrutin för att kolla om ormens huvud har kolliderat med en frukt.
  317.  * I och med att vi enbart har en frukt aktiv så behöver vi enbart jämföra
  318.  * huvudets plats med fruktens plats. Detta gör denna subrutin väldigt simpel
  319.  * och snabb. Om den dock identiferar en kollision så kommer subrutinen att anropa
  320.  * en annan subrutin som ändrar positionen av frukten och en annan som får ormen att
  321.  * växa.
  322. */
  323. detectCollision:
  324.     rcall   findSnakeHead
  325.     ldi     ZH, HIGH(fruit)
  326.     ldi     ZL, LOW(fruit)
  327.     ldd     rTemp, Y+0
  328.     ldd     rTemp2, Z+0
  329.     cp      rTemp, rTemp2
  330.     breq    collisionX
  331.     nop
  332.     jmp     noCollision
  333.     nop
  334.  
  335.     collisionX:
  336.     ldd     rTemp, Y+1
  337.     ldd     rTemp2, Z+1
  338.     cp      rTemp, rTemp2
  339.     brne    noCollision
  340.     nop
  341.     rcall   generateRandomPoint
  342.     nop
  343.     rcall   snakeWillGrow
  344.     nop
  345.     noCollision:
  346.     ret
  347.  
  348. /*
  349.  * Används för att få ormen att växa. Sker enbart när ormen har
  350.  * ätit en frukt. Kommer att jämföra ormens längd med 12, vilket är den
  351.  * storleken som vi har suttit som max (MAX_LENGTH+1 / 2), om den är lika stor som
  352.  * max längden så kommer ormen ej att växa.
  353.  * Den lägger till en kroppsdel framför huvudet och gör denna till det nya huvudet.
  354.  * Därefter så anropar den en subrutin som kommer att flytta huvudet baserat på den nuvarande
  355.  * riktingen som användaren har valt. Sedan kolla om detta resulterade i att ormen åt sig själv
  356.  * för att slutligen hoppa tillbaka till subrutinen som tar hand om belysningen.
  357. */
  358. snakeWillGrow:
  359.     rcall   findSnakeHead
  360.     nop
  361.     ldi     ZH, HIGH(snake_length)
  362.     ldi     ZL, LOW(snake_length)
  363.     ld      rTemp, Z
  364.     ldi     rTemp2, 12
  365.     cp      rTemp, rTemp2
  366.     breq    noGrow
  367.     nop
  368.     ldd     rTemp, Y+0
  369.     ldd     rTemp2, Y+1
  370.     std     Y+2, rTemp
  371.     std     Y+3, rTemp2
  372.     ldi     rTemp, 0
  373.     std     Y+4, rTemp
  374.     std     Y+5, rTemp
  375.     ld      rTemp, Z
  376.     inc     rTemp
  377.     st      Z, rTemp
  378.     adiw    Y, 2
  379.  
  380.     rcall   moveBasedOnDirection
  381.     nop
  382.  
  383.     rcall   snakeAteItself
  384.     nop
  385.  
  386.     jmp     print
  387.     nop
  388.    
  389.     noGrow:
  390.     ret
  391.  
  392.  
  393. /*
  394.  * Kollar om ormens huvud ligger på samma plats som en annan kroppsdel. Om den gör det
  395.  * så skall spelet resetas, annars returnar subrutinen.
  396. */
  397. snakeAteItself:
  398.     rcall   findSnakeHead
  399.     nop
  400.     ldi     ZH, HIGH(snake_length)
  401.     ldi     ZL, LOW(snake_length)
  402.     ld      rTemp, Z
  403.     ldi     ZH, HIGH(snake)
  404.     ldi     ZL, LOW(snake)
  405.     ldi     rTemp2, 0
  406.     subi    rTemp, 1
  407.  
  408.     detectSelfkill:
  409.     cp      rTemp, rTemp2
  410.     breq    endOfSelfkill
  411.     nop
  412.  
  413.     push    rTemp
  414.     push    rTemp2
  415.     ldd     rTemp, Z+0
  416.     ldd     rTemp2, Y+0
  417.     cp      rTemp, rTemp2
  418.     breq    XIsTheSame
  419.     nop
  420.     jmp     nextBodyPart
  421.     nop
  422.     XIsTheSame:
  423.     ldd     rTemp, Z+1
  424.     ldd     rTemp2, Y+1
  425.     cp      rTemp, rTemp2
  426.     brne    nextBodyPart
  427.     nop
  428.     jmp     reset
  429.     nop
  430.  
  431.     nextBodyPart:
  432.     adiw    Z, 2
  433.     pop     rTemp2
  434.     pop     rTemp
  435.     inc     rTemp2
  436.     jmp     detectSelfkill
  437.     nop
  438.  
  439.     endOfSelfkill:
  440.     ret
  441.  
  442. /*
  443.  * Simpel subrutin som hämtar positionen av ormens huvud.
  444.  * Resultaten kommer att sparas i Y.
  445.  * Istället för att leta efter en instans av '0', så kommer
  446.  * den att iterera och lägga till 2 på Y lika många gånger
  447.  * som snake_length.
  448. */
  449. findSnakeHead:
  450.     push    rTemp
  451.     push    rTemp2
  452.     ldi     YH, HIGH(snake)
  453.     ldi     YL, LOW(snake)
  454.     ldi     ZH, HIGH(snake_length)
  455.     ldi     ZL, LOW(snake_length)
  456.     ldi     rTemp2, 0
  457.     ld      rTemp, Z
  458.     subi    rTemp, 1
  459.     snakeHeadLoop:
  460.     cp      rTemp, rTemp2
  461.     breq    foundSnakeHead
  462.     dec     rTemp
  463.     adiw    Y, 2
  464.     jmp     snakeHeadLoop
  465.     nop
  466.  
  467.     foundSnakeHead:
  468.     pop     rTemp2
  469.     pop     rTemp
  470.     ret
  471.  
  472. /*
  473. * Flyttar alla kroppsdelar så att deras värde blir
  474. * detsamma som kroppsdelen efter. Detta görs tills det hittas en 0:a.
  475. * Detta gör så att den sista delen av ormen kommer att ha två instanser,
  476. * så då anropas subrutinen som tar hand om förflyttningen baserat på riktningen
  477. * som användaren har valt.
  478. */
  479. moveSnake:
  480.     rcall   findSnakeHead
  481.     nop
  482.     moveSnakeList:
  483.     ldi     ZH, HIGH(snake)
  484.     ldi     ZL, LOW(snake)
  485.     moveSnakeLoop:
  486.     ldd     rTemp, Z+2
  487.     std     Z+0, rTemp
  488.     ldd     rTemp, Z+3
  489.     std     Z+1, rTemp
  490.     ldd     rTemp, Z+4
  491.     cpi     rTemp, 0
  492.     breq    moveLoop
  493.     nop
  494.     adiw    Z, 2
  495.     jmp     moveSnakeLoop
  496.     nop
  497.  
  498.     moveLoop:
  499.     rcall   moveBasedOnDirection
  500.     nop
  501.     ret
  502.  
  503. /*
  504.  * Flyttar huvudet i det håller som användaren har bestämt.
  505.  * Hade varit bättre att implementera ett jump-table, men detta insågs alldeles för sent.
  506.  * Denna metod tar även hand om scenariot där ormen försöker förflytta sig utanför matrisen och
  507.  * sätter istället koordinaten till att bli den "omvända". Förtydligande:
  508.  * Om den är på 8 och försöker gå till 9, kommer den istället sättas till 1.
  509.  * Detta gör så att användaren ej kan dö om den åker in i väggarna, vilket kan vara
  510.  * bra på en så pass liten spelplan.
  511. */
  512. moveBasedOnDirection:
  513.     cpi     rDirection, 0b00000001
  514.     breq    moveDown
  515.     nop
  516.     cpi     rDirection, 0b00000010
  517.     breq    moveUp
  518.     nop
  519.     cpi     rDirection, 0b00000100
  520.     breq    moveLeft
  521.     nop
  522.     cpi     rDirection, 0b00001000
  523.     breq    moveRight
  524.     nop
  525.  
  526.     jmp     noMove
  527.     nop
  528.  
  529.     moveDown:
  530.     ldd     rTemp, Y+1
  531.     rol     rTemp
  532.     cpi     rTemp, 0
  533.     breq    YTo0
  534.     nop
  535.     std     Y+1, rTemp
  536.     jmp     moveEnd
  537.     nop
  538.  
  539.     moveUp:
  540.     ldd     rTemp, Y+1
  541.     ror     rTemp
  542.     cpi     rTemp, 0
  543.     breq    YTo7
  544.     nop
  545.     std     Y+1, rTemp
  546.     jmp     moveEnd
  547.     nop
  548.  
  549.     YTo7:
  550.     ldi     rTemp, 0b10000000
  551.     std     Y+1, rTemp
  552.     jmp     moveEnd
  553.     nop
  554.  
  555.     YTo0:
  556.     ldi     rTemp, 0b01
  557.     std     Y+1, rTemp
  558.     jmp     moveEnd
  559.     nop
  560.  
  561.     moveLeft:
  562.     ldd     rTemp, Y+0
  563.     rol     rTemp
  564.     cpi     rTemp, 0
  565.     breq    XTo0
  566.     nop
  567.     std     Y+0, rTemp
  568.     jmp     moveEnd
  569.     nop
  570.  
  571.     moveRight:
  572.     ldd     rTemp, Y+0
  573.     ror     rTemp
  574.     cpi     rTemp, 0
  575.     breq    Xto7
  576.     nop
  577.     std     Y+0, rTemp
  578.     jmp     moveEnd
  579.     nop
  580.  
  581.     XTo7:
  582.     ldi     rTemp, 0b10000000
  583.     std     Y+0, rTemp
  584.     jmp     moveEnd
  585.     nop
  586.  
  587.     XTo0:
  588.     ldi     rTemp, 0b01
  589.     std     Y+0, rTemp
  590.     jmp     moveEnd
  591.     nop
  592.  
  593.     moveEnd:
  594.     jmp     noMove
  595.     nop
  596.  
  597.     noMove:
  598.     ret
  599.  
  600. /*
  601.  * Läser in data från den analoga joysticken, maskar ut de tre sista bitarna
  602.  * kastar ordningen på dessa bitar för att sedan konvertera om dem till data
  603.  * som kan sparas som en koordinat i vår frukt.
  604.  * Subrutinen kommer även att kontrollera om det är en koordinat som vi kan använda,
  605.  * om den ej är det så kommer den att försöka generera en ny koordinat.
  606. */
  607. generateRandomPoint:
  608.     ldi     ZH, HIGH(fruit)
  609.     ldi     ZL, LOW(fruit)
  610.     ldi     rTemp, 0b00000100          
  611.     lds     rTemp2, ADMUX
  612.     andi    rTemp2, 0b11111000
  613.     or      rTemp2, rTemp
  614.     sts     ADMUX, rTemp2
  615.  
  616.     ldi     rTemp, (1<<ADSC)
  617.     lds     rTemp2, ADCSRA
  618.     or      rTemp2, rTemp
  619.     sts     ADCSRA, rTemp2
  620.  
  621.     randomYWait:
  622.     lds     rTemp, ADCSRA
  623.     sbrc    rTemp, 6
  624.     jmp     randomYWait
  625.     lds     rTemp, ADCH
  626.  
  627.     rcall   randomY
  628.     nop
  629.  
  630.     ldi     rTemp, 0b00000101          
  631.     lds     rTemp2, ADMUX
  632.     andi    rTemp2, 0b11111000
  633.     or      rTemp2, rTemp
  634.     sts     ADMUX, rTemp2
  635.  
  636.     ldi     rTemp, (1<<ADSC)
  637.     lds     rTemp2, ADCSRA
  638.     or      rTemp2, rTemp
  639.     sts     ADCSRA, rTemp2
  640.  
  641.     randomXPoint:
  642.     lds     rTemp, ADCSRA
  643.     sbrc    rTemp, 6
  644.     jmp     randomXPoint
  645.     lds     rTemp, ADCH
  646.  
  647.     rcall   randomX
  648.     nop
  649.  
  650.     validPoint:
  651.     ldi     ZH, HIGH(snake_length)
  652.     ldi     ZL, LOW(snake_length)
  653.     ld      rTemp, Z
  654.     ldi     ZH, HIGH(snake)
  655.     ldi     ZL, LOW(snake)
  656.     ldi     YH, HIGH(fruit)
  657.     ldi     YL, LOW(fruit)
  658.     ldi     rTemp2, 0
  659.     subi    rTemp, 1
  660.  
  661.     validLoop:
  662.     cp      rTemp, rTemp2
  663.     breq    endOfValid
  664.     nop
  665.     push    rTemp
  666.     push    rTemp2
  667.     ldd     rTemp, Z+0
  668.     ldd     rTemp2, Y+0
  669.     cp      rTemp, rTemp2
  670.     breq    invalidX
  671.     nop
  672.  
  673.     jmp     nextSnakePart
  674.     nop
  675.  
  676.  
  677.     invalidX:
  678.     ldd     rTemp, Z+1
  679.     ldd     rTemp2, Y+1
  680.     cp      rTemp, rTemp2
  681.     breq    notValidPoint
  682.     nop
  683.     jmp     nextSnakePart
  684.     nop
  685.  
  686.     nextSnakePart:
  687.     pop     rTemp2
  688.     pop     rTemp
  689.     inc     rTemp2
  690.     adiw    Z, 2
  691.     jmp     validLoop
  692.     nop
  693.  
  694.     endOfValid:
  695.     ret
  696.  
  697.     notValidPoint:
  698.     ldi     rTemp, 0b00000100          
  699.     lds     rTemp2, ADMUX
  700.     andi    rTemp2, 0b11111000
  701.     or      rTemp2, rTemp
  702.     sts     ADMUX, rTemp2
  703.  
  704.     ldi     rTemp, (1<<ADSC)
  705.     lds     rTemp2, ADCSRA
  706.     or      rTemp2, rTemp
  707.     sts     ADCSRA, rTemp2
  708.     /*
  709.      * Hämtar data från joysticken och skickar vidare den så att det kan sparas
  710.      * som en koordinat.
  711.     */
  712.     nextRandomYWait:
  713.     lds     rTemp, ADCSRA
  714.     sbrc    rTemp, 6
  715.     jmp     nextRandomYWait
  716.     lds     rTemp, ADCH
  717.     andi    rTemp, 0b11110000
  718.     ror     rTemp
  719.     ror     rTemp
  720.     ror     rTemp
  721.     ror     rTemp
  722.     rcall   randomY
  723.     nop
  724.  
  725.     ldi     rTemp, 0b00000101          
  726.     lds     rTemp2, ADMUX
  727.     andi    rTemp2, 0b11111000
  728.     or      rTemp2, rTemp
  729.     sts     ADMUX, rTemp2
  730.  
  731.     ldi     rTemp, (1<<ADSC)
  732.     lds     rTemp2, ADCSRA
  733.     or      rTemp2, rTemp
  734.     sts     ADCSRA, rTemp2
  735.  
  736.     nextRandomXPoint:
  737.     lds     rTemp, ADCSRA
  738.     sbrc    rTemp, 6
  739.     jmp     nextRandomXPoint
  740.     lds     rTemp, ADCH
  741.     andi    rTemp, 0b11110000
  742.     ror     rTemp
  743.     ror     rTemp
  744.     ror     rTemp
  745.     ror     rTemp
  746.     rcall   randomX
  747.     nop
  748.  
  749.     jmp     validLoop
  750.     nop
  751.  
  752.     /*
  753.      * Kastar om datan så att den ser mer "slumpmartad" ut.
  754.     */
  755.     randomX:
  756.     ldi     ZH, HIGH(fruit)
  757.     ldi     ZL, LOW(fruit)
  758.     andi    rTemp, 0b00000111
  759.     ldi     rTemp2, 0
  760.  
  761.     bst     rTemp, 0
  762.     bld     rTemp2, 2
  763.  
  764.     bst     rTemp, 1
  765.     bld     rTemp2, 0
  766.  
  767.     bst     rTemp, 2
  768.     bld     rTemp2, 1
  769.  
  770.     ldi     rTemp, 0
  771.     ldi     rTemp3, 0b00000001
  772.     randomXCalc:
  773.     cp      rTemp2, rTemp
  774.     breq    storeRandomXPoint
  775.     nop
  776.     inc     rTemp
  777.     rol     rTemp3
  778.     jmp     randomXCalc
  779.     nop
  780.     storeRandomXPoint:
  781.     std     Z+0, rTemp3
  782.     ret
  783.  
  784.     randomY:
  785.     ldi     ZH, HIGH(fruit)
  786.     ldi     ZL, LOW(fruit)
  787.     andi    rTemp, 0b00000111
  788.     ldi     rTemp2, 0
  789.  
  790.     bst     rTemp, 0
  791.     bld     rTemp2, 2
  792.  
  793.     bst     rTemp, 1
  794.     bld     rTemp2, 1
  795.  
  796.     bst     rTemp, 2
  797.     bld     rTemp2, 0
  798.  
  799.     ldi     rTemp, 0
  800.     ldi     rTemp3, 0b00000001
  801.     randomYCalc:
  802.     cp      rTemp2, rTemp
  803.     breq    storeRandomYPoint
  804.     nop
  805.     inc     rTemp
  806.     rol     rTemp3
  807.     jmp     randomYCalc
  808.     nop
  809.  
  810.     storeRandomYPoint:
  811.     std     Z+1, rTemp3
  812.     ret
  813.  
  814.  
  815. /*
  816.  * Läser av joysticken och sätter rDirection baserat på vilket håll joysticken är åt.
  817.  * Den kontrollerar även om den nuvarande rDirection är motsatsen till det som den försöker sätta den till,
  818.  * 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.
  819. */
  820. readStick:
  821.     ldi     rTemp, 0b00000100          
  822.     lds     rTemp2, ADMUX
  823.     andi    rTemp2, 0b11111000
  824.     or      rTemp2, rTemp
  825.     sts     ADMUX, rTemp2
  826.  
  827.     ldi     rTemp, (1<<ADSC)
  828.     lds     rTemp2, ADCSRA
  829.     or      rTemp2, rTemp
  830.     sts     ADCSRA, rTemp2
  831.  
  832.     YWait:
  833.     lds     rTemp, ADCSRA
  834.     sbrc    rTemp, 6
  835.     jmp     YWait
  836.     lds     rTemp, ADCH
  837.  
  838.     std     Y+0, rTemp
  839.     cpi     rTemp, 0b11111000
  840.     brsh    yUp
  841.     nop
  842.     cpi     rTemp, 0b00000111
  843.     brlo    yDown
  844.     nop
  845.     jmp     XLoop
  846.     nop
  847.  
  848.     yDown:
  849.     cpi     rDirection, 0b010
  850.     breq    stickEnd
  851.     nop
  852.     ldi     rDirection, 0b001
  853.     ret
  854.  
  855.     yUp:
  856.     cpi     rDirection, 0b001
  857.     breq    stickEnd
  858.     nop
  859.     ldi     rDirection, 0b010
  860.     ret
  861.  
  862.     XLoop:
  863.     ldi     rTemp, 0b00000101      
  864.     lds     rTemp2, ADMUX
  865.     andi    rTemp2, 0b11111000
  866.     or      rTemp2, rTemp
  867.     sts     ADMUX, rTemp2
  868.  
  869.     ldi     rTemp, (1<<ADSC)
  870.     lds     rTemp2, ADCSRA
  871.     or      rTemp2, rTemp
  872.     sts     ADCSRA, rTemp2
  873.  
  874.     XWait:
  875.     lds     rTemp, ADCSRA
  876.     sbrc    rTemp, 6
  877.     jmp     XWait
  878.     lds     rTemp, ADCH
  879.  
  880.     cpi     rTemp, 0b11111000
  881.     brsh    xLeft
  882.     nop
  883.     cpi     rTemp, 0b00000111
  884.     brlo    xRight
  885.     nop
  886.     jmp     stickEnd
  887.     nop
  888.  
  889.     xLeft:
  890.     cpi     rDirection, 0b0100
  891.     breq    stickEnd
  892.     nop
  893.     ldi     rDirection, 0b1000
  894.     jmp     stickEnd
  895.     nop
  896.  
  897.     xRight:
  898.     cpi     rDirection, 0b1000
  899.     breq    stickEnd
  900.     nop
  901.     ldi     rDirection, 0b0100
  902.     jmp     stickEnd
  903.     nop
  904.  
  905.     stickEnd:
  906.     ret
  907.  
  908. /*
  909.  * Används för att visa att ett avbrott har skett.
  910. */
  911. tick:
  912.     ldi     rUpdateFlag, 1
  913.     reti
  914.  
  915. /*
  916.  * Laddar in all data som ligger i snake-listan samt frukten in till matrisen.
  917. */
  918. dataToMatrix:
  919.     ldi     ZH, HIGH(snake)
  920.     ldi     ZL, LOW(snake)
  921.     dataLoop:
  922.     ldi     YH, HIGH(matrix)
  923.     ldi     YL, LOW(matrix)
  924.     ldd     rTemp, Z+1
  925.     cpi     rTemp, 0
  926.     breq    notInMatrix
  927.     nop
  928.     rowLoop:
  929.     cpi     rTemp, 1
  930.     breq    columnLoop
  931.     nop
  932.     ror     rTemp
  933.     adiw    Y, 1
  934.     jmp     rowLoop
  935.     nop
  936.  
  937.     columnLoop:
  938.     ldd     rTemp, Z+0
  939.     cpi     rTemp, 0
  940.     breq    notInMatrix
  941.     nop
  942.     ld      rTemp2, Y
  943.     or      rTemp, rTemp2
  944.     st      Y, rTemp
  945.  
  946.     notInMatrix:
  947.     adiw    Z, 2
  948.     ldd     rTemp, Z+1
  949.     cpi     rTemp, 0
  950.     breq    yIsEmpty
  951.     nop
  952.     jmp     dataLoop
  953.     nop
  954.     yIsEmpty:
  955.     ldd     rTemp, Z+0
  956.     cpi     rTemp, 0
  957.     breq    endOfSnake
  958.     nop
  959.     jmp     dataLoop
  960.     nop
  961.  
  962.     endOfSnake:
  963.     ldi     ZH, HIGH(fruit)
  964.     ldi     ZL, LOW(fruit)
  965.  
  966.     /*
  967.      * Kunde inte låta bli att döpa denna label till detta.
  968.     */
  969.     fruityLoops:
  970.     ldi     YH, HIGH(matrix)
  971.     ldi     YL, LOW(matrix)
  972.     ldd     rTemp, Z+1
  973.     cpi     rTemp, 0
  974.     breq    noFruit
  975.     nop
  976.     fruitRowLoop:
  977.     cpi     rTemp, 1
  978.     breq    fruitColumnLoop
  979.     nop
  980.     ror     rTemp
  981.     adiw    Y, 1
  982.     jmp     fruitRowLoop
  983.     nop
  984.  
  985.     fruitColumnLoop:
  986.     ldd     rTemp, Z+0
  987.     cpi     rTemp, 0
  988.     breq    noFruit
  989.     nop
  990.     ld      rTemp2, Y
  991.     or      rTemp, rTemp2
  992.     st      Y, rTemp
  993.  
  994.     noFruit:
  995.     ret
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement