Zorbing icon

[TGI] Versuch 11

Zorbing | PRO | 01/30/14 08:03:20 PM UTC | 0 ⭐ | 271 👁️ | Never ⏰ | []
ASM (NASM) |

0 B

|

None

|

0 👍

/

0 👎

.include "m16def.inc"
 
#define     SIMULATOR   1           ; set to 1 when running on the simulator to deactivate the UART and the delay
 
; *********************************************************************
; Command headers
; *********************************************************************
.equ    PROD_HEADER     = 0x40
.equ    COIN_HEADER     = 0x00
.equ    DISPLAY_HEADER  = 0x80
 
 
; *********************************************************************
; Registers symbolic name
; *********************************************************************
.def    cmd     = r17               ; command, used in all the UART operation
.def    tmp1    = r18               ; Temp register
.def    tmp2    = r16               ; Temp register
.def    coinVal = r19
.def    creditTmp = r20
 
 
; *********************************************************************
; UART parameter
; *********************************************************************
.equ F_CPU = 1000000                ; Systemtakt in Hz
.equ BAUD  = 9600                   ; Baudrate
 
; Berechnungen
.equ UBRR_VAL   = ((2*F_CPU+BAUD*8)/(BAUD*16)-1)    ; clever runden
.equ BAUD_REAL  = (2*F_CPU/(16*(UBRR_VAL+1)))       ; Reale Baudrate
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)      ; Fehler in Promille
 
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))           ; max. +/-10 Promille Fehler
    .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
.endif
 
; *********************************************************************
; RAM allocation: current credit, and products' price
; *********************************************************************
.dseg
.org 0x00060
CREDIT: .byte 1                     ; allocate RAM for CREDIT
PRICE:  .byte 64                    ; allocate RAM for PRICE
_RAM_:                              ; to mark the end of the allocated ram: DO NOT CHANGE IT!
 
.cseg
.org 0000
    rjmp    main_init
 
; *********************************************************************
; Constants in PROGRAM memory
; *********************************************************************
.org 0x0030
; Products price array. It is possible to add values or change the existing ones
const_PP:   .db 15, 12, 10, 30, 35, 8;
_PP_end_:   ; to mark the end of the array
 
main_init:
    ldi     r17,    high(_RAM_)
    out     SPH,    r17
    ldi     r17,    low(_RAM_)
    out     SPL,    r17
 
    clr     r17
    ldi     r19,    (_RAM_-CREDIT+1)
__clear_ram:
    push    r17
    dec     r19
    brne    __clear_ram
 
    ldi     XL,     low(PRICE)
    ldi     XH,     high(PRICE)
    ldi     ZL,     low(const_PP<<1)
    ldi     ZH,     high(const_PP<<1)
 
    ldi     r19,    (_PP_end_-const_PP)
__init__ram:
    lpm     r17,    Z               ; first byte
    ori     ZL,     0x01
    lpm     r18,    Z+              ; second byte
 
    st      X+,     r17
    st      X+,     r18
 
    dec     r19
    brne    __init__ram
 
; Baudrate einstellen
    ldi     tmp1,   HIGH(UBRR_VAL)
    out     UBRRH,  tmp1
    ldi     tmp1,   LOW(UBRR_VAL)
    out     UBRRL,  tmp1
 
; Frame-Format: 8 Bit
    ldi     tmp1,   (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0)
    out     UCSRC,  tmp1
    sbi     UCSRA,  U2X
 
    sbi     UCSRB,  TXEN            ; TX aktivieren
    sbi     UCSRB,  RXEN            ; RX aktivieren
 
; TODO: Stackpointer initialisieren
    ldi     tmp1,   high(RAMEND)
    out     SPH,    tmp1
    ldi     tmp1,   low(RAMEND)
    out     SPL,    tmp1
 
; TODO: setze das Display auf 0
    ldi     cmd,    (1<<7)
    call    serout
 
main:
    call    serin
    sbrc    cmd,    7
    rjmp    main
    ; decode the command
    sbrs    cmd,    6
    call    coin
    sbrc    cmd,    6
    call    product
    rjmp    main
; end main
 
 
; *********************************************************************
; COIN
;
; Decode, update the CREDIT
; *********************************************************************
coin:
    ldi     YL,     low(CREDIT)
    ldi     YH,     high(CREDIT)
    ld      creditTmp, Y            ; load the credit value
    sbrc    cmd,    5
    rjmp    coins_back              ; eject all coins (bit 5 is set)
    ; decode coin value
    call    decode_coin             ; get coinVal from cmd
    ; check new credit
    add     creditTmp, coinVal      ; add coin to credit
    cpi     creditTmp, 100          ; compare with 100 (represents 10,0 Euro)
    brsh    last_coin_back          ; more than allowed? -> return last coin
    ; update CREDIT
    st      Y,      creditTmp       ; save credit value to RAM
    call    display_update          ; update the display
    ret
 
coins_back:
    call    change_back
    call    display_update          ; update the display
    ret
 
last_coin_back:
    call    serout                  ; cmd is still the coin command
    ret
 
 
decode_coin:
    clr     coinVal                 ; ready to store the coin value
    ; 10 Cent
    sbrc    cmd,    0
    ldi     coinVal, 1
    ; 20 Cent
    sbrc    cmd,    1
    ldi     coinVal, 2
    ; 50 Cent
    sbrc    cmd,    2
    ldi     coinVal, 5
    ; 1 Euro
    sbrc    cmd,    3
    ldi     coinVal, 10
    ; 2 Euro
    sbrc    cmd,    4
    ldi     coinVal, 20
    ret
 
 
; *********************************************************************
; PRODUCT
;
; Decode, lookup price, release or show the price
; *********************************************************************
product:
    ldi     XL,     low(PRICE)
    ldi     XH,     high(PRICE)
    andi    cmd,    0b00111111      ; remove the first two bits (2 MSB)
    add     XL,     cmd
    clr     tmp1
    adc     XH,     tmp1
; TODO: pre-decrement or not?
; is the first product 0b00000001?
;   ld      tmp1,   -X              ; load the price
    ld      tmp1,   X               ; load the price
    tst     tmp1
    brne    product_ret
    ldi     YL,     low(CREDIT)
    ldi     YH,     high(CREDIT)
    ld      creditTmp, Y            ; load the credit value
    sub     creditTmp, tmp1         ; substract the price from the credits
    brmi    display_blink           ; not enough credits
    ; output the product
    call    serout                  ; cmd is still the command of the requested product
    st      Y,      creditTmp       ; save the new credits
    call    change_back             ; return the change
    call    display_update
    ret
 
display_blink:
    mov     cmd,    tmp1
    ori     cmd,    (1<<7)
    call    serout                  ; output price
    call    delay_500ms
    call    delay_500ms
 
    ser     cmd                     ; set cmd to $FF (display off)
    call    serout
    call    delay_500ms
 
    mov     cmd,    tmp1
    ori     cmd,    (1<<7)
    call    serout                  ; output price
    call    delay_500ms
    call    delay_500ms
 
    call    display_update
product_ret:
    ret
 
; *********************************************************************
; Give CHANGE back
;
; Return the change minimizing the number of returned coins
; *********************************************************************
change_back:
    push    cmd
    push    YL
    push    YH
 
    ldi     YL,     low(CREDIT)
    ldi     YH,     high(CREDIT)
    ld      creditTmp, Y            ; load the credit value
    ldi     cmd,    (1<<4)          ; set cmd to highest coin
change_loop:
    tst     creditTmp
    breq    change_end              ; is credit empty?
    call    decode_coin             ; get coin value
    sub     creditTmp, coinVal      ; substract!
    ; maybe brmi?
    brlo    next_coin               ; next coin?
    call    serout                  ; return that coin
    rjmp    change_loop
 
next_coin:
    lsr     cmd
    add     creditTmp, coinVal
    rjmp    change_loop
 
change_end:
    clr     creditTmp
    st      Y, creditTmp
    pop     YH
    pop     YL
    pop     cmd
    ret
 
; *********************************************************************
; Display Update
;
; Update the display, based on the current CREDIT
; *********************************************************************
display_update:
    push    cmd
    ld      creditTmp, Y                ; load the credit value
    mov     cmd,    creditTmp
    ori     cmd,    (1<<7)          ; set the display bit
    call    serout
    pop     cmd
    ret
 
 
; *********************************************************************
; Delay routine
; *********************************************************************
.equ    N1  =   234
.equ    N2  =   255
delay_500ms:
#if !SIMULATOR                      ; prevent the simulator by executing the actual delay.
    push    tmp1
    push    tmp2
    ldi     tmp2,   N1
_delay_loop1:
    dec     tmp2
    breq    _delay_return
    ldi     tmp1,   N2
_delay_loop2:
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    dec     tmp1
    brne    _delay_loop2
    nop
    rjmp    _delay_loop1
 
_delay_return:
    pop     tmp2
    pop     tmp1
#endif
    ret
 
serout:
#if !SIMULATOR
    sbis    UCSRA,  UDRE
    rjmp    serout
    out     UDR,    cmd
#endif
    ret
 
serin:
#if !SIMULATOR
    sbis    UCSRA,  RXC
    rjmp    serin                   ; loop back
    in      cmd,    UDR             ; else get received byte in cmd
#endif
    ret

Comments