Advertisement
Guest User

Snaaaaaake.asm

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