Zorbing

[TGI] Versuch12

Feb 5th, 2014
300
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ; ############################################################
  2. ;
  3. ;   Fügen Sie in diese Datei bitte Ihren selbst erarbeiteten
  4. ;   Assemblercode ein! Nehmen Sie keine Änderungen am vorge-
  5. ;   gebenen Code vor!
  6. ;
  7. ; ############################################################
  8.  
  9.  
  10. .include "m16def.inc"
  11.                             ; Symbolische Registernamen und bausteinspezifische
  12.                             ; Konstanten importieren
  13.  
  14. .dseg
  15. .org    $60
  16.  
  17. ; Blockvariablen
  18. ; ================
  19.     ; ================================
  20.     ; Diese Variablen nicht verändern!
  21.     ; ================================
  22.     block4:
  23.         .byte   8
  24.     block5:
  25.         .byte   8
  26.     block6:
  27.         .byte   8
  28.     block7:
  29.         .byte   8
  30.     block_y:
  31.         .byte   1
  32.     ; ================================
  33.     ; Diese Variablen nicht verändern!
  34.     ; ================================
  35.    
  36.     ; Variablen
  37.     ; ========================
  38.     ; ***  (Ihre Lösung aus Abschnitt 3.1)  ***
  39.     figure_pos:
  40.         .byte   1
  41.     block_pos_x:
  42.         .byte   1
  43.     block_pos_y:
  44.         .byte   1
  45.     gameover:
  46.         .byte   1
  47.     seed:
  48.         .byte   1
  49.     start_pos:
  50.         .byte   1
  51.  
  52.  
  53. ; Interrupt-Vektor-Tabelle
  54. ; ========================
  55. ; ***  (Ihre Lösung aus Abschnitt 3.6)  ***
  56. .cseg
  57. .org    $000                ; Dillsauce
  58.     jmp init
  59. .org    $00C                ; OC1Aaddr
  60.     jmp t1comp_isr
  61. .org    $026                ; OC0addr
  62.     jmp t0comp_isr
  63.  
  64.  
  65.  
  66. ; Unterprogramme
  67. ; ==============
  68. .cseg                       ; Programmspeicher
  69. .org    $030                ; ab Adresse $030 verwenden.
  70.  
  71.  
  72.  
  73. ; Vorgegebene Unterprogramme einbinden
  74. ; ------------------------------------
  75. .include "lcd.asm"
  76. .include "draw.asm"
  77.  
  78.  
  79.  
  80. ; INIT_ADC
  81. ; ----------
  82. ; Initialisierung von A/D-Converter
  83. ; I: -
  84. ; O: -
  85. init_adc:
  86. ; ***  (Ihre Lösung aus Abschnitt 3.2)  ***
  87.     push    r16
  88.     ldi     r16,    (1<<REFS0) | (1<<ADLAR)
  89.     out     ADMUX, r16
  90.     ldi     r16,    (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0)
  91.     out     ADCSRA, r16
  92.     pop     r16
  93.     ret
  94.  
  95.  
  96. ; INIT_TIMER0
  97. ; ----------
  98. ; Initialisierung von Timer/Counter0
  99. ; I: -
  100. ; O: -
  101. init_timer0:
  102. ; ***  (Ihre Lösung aus Abschnitt 3.3)  ***
  103.     push    r16                                 ; Register retten.
  104.     clr     r16                                 ; Normale Betriebsart,
  105.     ldi     r16,    (1<<WGM01) | (1<<CS02) | (1<<CS00)  ; Bits für Timer Control Register setzen
  106.     out     TCCR0,  r16                         ; setzen des Timer/Counter 0 Control Register
  107.     ldi     r16,    39                          ; Vergleichswert setzen (entspricht Abtastung von 25Hz)
  108.     out     OCR0,   r16                         ; und speichern
  109.     ldi     r16,    (1<<OCIE0)                  ; Interrupterzeugung bei Erreichen des Vergleichswerts A von Timer 0 aktivieren.
  110.     out     TIMSK,  r16                         ; Setzen des Timer/Counter Interrupt Mask Register
  111.     pop     r16                                 ; Register wiederherstellen.
  112.     ret                                         ; Zurueck.
  113.  
  114.  
  115. ; INIT_TIMER1
  116. ; ----------
  117. ; Initialisierung von Timer/Counter1
  118. ; I: -
  119. ; O: -
  120. init_timer1:
  121. ; ***  (Ihre Lösung aus Abschnitt 3.4)  ***
  122.     push    r16                                 ; Register retten.
  123.     clr     r16                                 ; Normale Betriebsart,
  124.     out     TCCR1A, r16                         ; Setzen des Timer/Counter 1 Control Register A
  125.     ldi     r16,    (1<<WGM12) | (1<<CS11) | (1<<CS10)  ; keine Ausgabe über OC1A/OC1B, Bits für Timer Control Register setzen
  126.     out     TCCR1B, r16                         ; Setzen des Timer/Counter 1 Control Register B
  127.     ldi     r16,    high(3906)                  ; Vergleichswert setzen erst High-...dann Low-Byte
  128.     out     OCR1AH, r16                         ;
  129.     ldi     r16,    low(3906)                   ;
  130.     out     OCR1AL, r16                         ;
  131.     in      r16,    TIMSK                       ; Interrupterzeugung bei Erreichen des Vergleichswerts A von Timer 1 aktivieren.
  132.     ori     r16,    (1<<OCIE1A)                 ;   Hinweis: Beachten Sie dass die Interrupts für alle Timer in dem selben Register gesetzt werden!
  133.     out     TIMSK,  r16                         ; Setzen des Timer/Counter Interrupt Mask Register
  134.     pop     r16                                 ; Register wiederherstellen.
  135.     ret                                         ; Zurueck.
  136.  
  137.  
  138. ; READ_ADC
  139. ; ----------
  140. ; Liest Daten vom ADC und gibt sie in R16 zurück
  141. ; I: -
  142. ; O: Der gewandelte Wert in R16
  143. read_adc:
  144. ; ***  (Ihre Lösung aus Abschnitt 3.2) ***
  145.     sbi     ADCSRA, ADSC
  146. wait_adc:
  147.     sbic    ADCSRA, ADSC
  148.     rjmp    wait_adc
  149.     in      r16,    ADCH
  150.     ret
  151.  
  152.  
  153. ; T0COMP_ISR
  154. ; ----------
  155. ; (Interrupt-Service-Routine)
  156. ; ADC auslesen und Display ansteuern
  157. t0comp_isr:
  158. ; ***  (Ihre Lösung aus Abschnitt 3.3)  ***
  159.     push    r16
  160.     in      r16,    SREG
  161.     push    r16
  162.     push    r17
  163.     call    read_adc                            ; Wert vom Poti auslesen
  164.     ldi     r17,    12
  165.     call    div8u                               ; AD-Wert durch 12 teilen
  166.     sts     figure_pos, r16                     ; neue Position speichern
  167.     call    draw_figure                         ; Figur zeichnen
  168.     pop     r17
  169.     pop     r16
  170.     out     SREG,   r16
  171.     pop     r16
  172.     reti
  173.  
  174.  
  175. ; T1COMP_ISR
  176. ; ----------
  177. ; (Interrupt-Service-Routine)
  178. ; Inkrementiert die Blockposition und zeichnet Block neu
  179. t1comp_isr:
  180. ; ***  (Ihre Lösung aus Abschnitt 3.4)  ***
  181.     push    r16
  182.     in      r16,    SREG
  183.     push    r16
  184.     push    r17
  185.     push    r18
  186.  
  187.     lds     r17,    block_pos_y                 ; lade block_pos_y
  188.     inc     r17                                 ; inkrementiere
  189.     cpi     r17,    70                          ; vergleiche mit 70
  190.     brlo    no_collision_check                  ; ueberpruefe die kollision nur, falls
  191.     call    check_collision                     ; die y-Position des Blocks >= 70 ist
  192. no_collision_check:
  193.     cpi     r17,    78                          ; ist die y-Position des Blocks gleich 78,
  194.     brne    not_grounded                        ; dann setze den Block zurueck
  195.     lds     r17,    start_pos                   ; auf die Startposition
  196.     call    lfsr
  197.     sts     block_pos_x, r16                    ; setze die x-Position des Blocks auf einen Zufallswert (lfsr)
  198.  
  199. not_grounded:
  200.     sts     block_pos_y, r17
  201.     call    draw_box
  202.     ; passe die Block-Geschwindigkeit an
  203.     in      r16,    OCR1AL
  204.     in      r17,    OCR1AH
  205.     subi    r16,    10
  206.     brpl    sub_fertig
  207.     cpi     r17,    5
  208.     brlo    reached_limit                       ; hart am Limit!
  209.     ldi     r18,    0xFF
  210.     add     r16,    r18                         ; Zimt
  211.     subi    r17,    1                           ; Muskatnuss
  212.     rjmp    sub_fertig
  213.  
  214. reached_limit:
  215.     ldi     r16,    0                           ; zurueck mit dir
  216.     ldi     r17,    4                           ; weiche Teufel...
  217. sub_fertig:
  218.     out     OCR1AL, r16                         ; setze zaehler
  219.     out     OCR1AH, r17                         ; neu
  220.  
  221.     pop     r18
  222.     pop     r17
  223.     pop     r16
  224.     out     SREG,   r16
  225.     pop     r16
  226.     reti
  227.  
  228.  
  229. ; CHECK_COLLISION
  230. ; Überprüft, ob Box und Figur kollidieren
  231. ; I: -
  232. ; O: -
  233. check_collision:
  234. ; ***  (Ihre Lösung aus Abschnitt 3.5)  ***
  235.     push    r16
  236.     push    r17
  237.     lds     r16,    block_pos_x
  238.     lds     r17,    figure_pos
  239.     sub     r16,    r17
  240.     cpi     r16,    0
  241.     brlo    collision_end                       ; die Box ist links von der Figur
  242.     cpi     r16,    9
  243.     brsh    collision_end                       ; die Box ist rechts von der Figur
  244.     ldi     r16,    1
  245.     sts     gameover, r16                       ; Spiel vorbei...
  246. collision_end:
  247.     pop     r17
  248.     pop     r16
  249.     ret
  250.  
  251.  
  252. ; Systeminitialisierung und Hauptprogramm
  253. ; =======================================
  254.  
  255.  
  256. ; Systeminitalisierung
  257. ; --------------------
  258. init:
  259. ; ***  (Ihre Lösung aus Abschnitt 3.6)  ***
  260.     ldi     r16,    high(RAMEND)
  261.     out     SPH,    r16
  262.     ldi     r16,    low(RAMEND)
  263.     out     SPL,    r16
  264.     call    lcd_init
  265.     call    init_timer0
  266.     call    init_timer1
  267.     call    init_adc
  268.     sbi     PINC,   PINC0
  269.  
  270.  
  271. ; Hauptprogramm
  272. ; -------------
  273. main:
  274. ; ***  (Ihre Lösung aus Abschnitt 3.7)  ***
  275. ; ***   Eigene Lösungsvorschläge sind auch erlaubt ***
  276.     call    lcd_startdisplay                ; rufe den Startdisplay auf
  277.     ldi     r16,    0                       ; setze gamover auf '0'
  278.     sts     gameover, r16                   ; und speichere dies
  279.     in      r17,    PINC                    ; lade PINC in r16
  280. startloop:
  281.     in      r16,    PINC                    ; solange es keine Veränderung gibt
  282.     cp      r16,    r17
  283.     breq    startloop                       ; springe zurück
  284.  
  285.     call    lcd_clear
  286.     in      r16,    TCNT1L                  ; wenn Taster gedrückt wurde
  287.     cpi     r16,    0                       ; dann lade den Timerwert als seed
  288.     brne    set_seed                        ; wenn er gleich 0 ist
  289.     ldi     r16,    $42                     ; dann wähle eine andere Zahl als seed
  290. set_seed:
  291.     sts     seed,   r16                     ; und speichere den seed
  292.     call    lfsr
  293.     sts     block_pos_x, r16                ; setze auch gleich den Start des Blocks
  294.     lds     r17,    start_pos
  295.     sts     block_pos_y, r17                ; auch in y-Richtung
  296.  
  297.     sei                                     ; und aktiveier die Interrupts
  298. mainloop:  
  299.     lds     r16,    gameover                ; gameover?
  300.     cpi     r16,    1                       ; wenn nein, dann warte weiter
  301.     brne    mainloop               
  302. maingameover:                               ; wenn doch,
  303.     cli                                     ; dann sperre Interrupts
  304.     call    lcd_gameover                    ; und schreibe gameover
  305.     call    init_timer1                     ; Timer 1 initialisieren
  306.     rjmp    main
  307.  
  308.  
  309.  
  310.  
  311.  
  312. ; =======================================
  313. ; =======================================
  314. ;       VORGEGEBENE UNTERPROGRAMME
  315. ; =======================================
  316. ; =======================================
  317.  
  318. ; LFSR
  319. ; --------
  320. ; Linear rückgekoppeltes Schieberegister
  321. ; Verwendet für das Fibonacci-LFSR das Generatorpolynom x^8+x^6+x^5+x^4+1
  322. ; Gibt eine Zufallszahl zwischen 11 und 15 zurück
  323. ; I: Erwartet in der Variablen "seed" einen Seed bzw. den alten Schieberegisterwert
  324. ; O: R16: Zufallszahl
  325. lfsr:
  326.     push    R15                             ; Register sichern
  327.     push    R17
  328.  
  329.     clr     R17
  330.     lds     R16, seed
  331.     sbrc    R16, 7                          ; Bit x^8
  332.     inc     R17
  333.     sbrc    R16, 5                      ; Bit x^6
  334.     inc     R17
  335.     sbrc    R16, 4                      ; Bit x^5
  336.     inc     R17
  337.     sbrc    R16, 3                      ; Bit x^4
  338.     inc     R17
  339.     inc     R17                         ; +1
  340.     andi    R17, 1                      ; Bitmaske mit 1
  341.     lsl     R16                         ; shifte alten Wert nach links
  342.     or      R16, R17                    ; und addiere Wert aus Polynom drauf
  343.     sts     seed, R16                   ; speichere Wert wieder ab.
  344.  
  345.     ldi     R17, 12                     ; lade 12 in R17
  346.     call    div8u                       ; und berechne R15 = R16/12
  347.     mov     R16, R15                    ; schreibe das Ergebnis in R16 zurück
  348.     subi    R16, -4                     ; und addiere eine 4 drauf
  349.  
  350.     pop     R17                         ; Register wieder herstellen
  351.     pop     R15
  352.     ret
  353.  
  354.  
  355. ; DIV8U
  356. ; ----------
  357. ; 8/8 Division (unsigned)
  358. ; I: R16: Dividend, R17: Divisor
  359. ; O: R16: Ergebnis, R15: Rest
  360. div8u:  push    R18
  361.         clr     r15         ; clear remainder and carry
  362.         ldi     r18,9       ; init loop counter
  363. d8u_1:  rol     r16         ; shift left dividend
  364.         dec     r18         ; decrement counter
  365.         brne    d8u_2       ; if done
  366.         pop     R18
  367.         ret                 ; return
  368. d8u_2:  rol     r15         ; shift dividend into remainder
  369.         sub     r15,r17     ; remainder = remainder - divisor
  370.         brcc    d8u_3       ; if result negative
  371.         add     r15,r17     ;  restore remainder
  372.         clc                 ;  clear carry to be shifted into result
  373.         rjmp    d8u_1       ; else
  374. d8u_3:  sec                 ;  set carry to be shifted into result
  375.         rjmp    d8u_1
  376.  
  377.  
  378. ; Vorgegebenes Unterprogramm "warte":
  379. ; Routine zur Verzoegerung des Programmablaufs
  380. ; Parameter: R16: Verzoegerungszeit in 100us
  381.  
  382. warte:  push    R16                     ; Register sichern
  383.         push    R17
  384. warte_schleife1:
  385.         ldi     R17, 32    
  386.         nop
  387. warte_schleife2:
  388.         dec     R17                     ; innere Schleife (Laufzeit 100us)
  389.         brne    warte_schleife2         ; die dann R16 mal abgearbeitet wird
  390.         dec     R16
  391.         brne    warte_schleife1
  392.         pop     R17
  393.         pop     R16                     ; Register wiederherstellen
  394.         ret
  395.  
  396. ; Vorgegebenes Unterprogramm "warte_1s":
  397. ; Routine zur Verzoegerung des Programmablaufs
  398. ; Wartet 1 Sekunde
  399. warte_1s:
  400.         push    R16
  401.         push    R17
  402.         ldi     R17, 250
  403. warte_1s_schleife:
  404.         ldi     R16, 250
  405.         call    warte
  406.         dec     R17
  407.         brne    warte_1s_schleife
  408.         pop     R17
  409.         pop     R16
  410.         ret
Advertisement
Add Comment
Please, Sign In to add comment