Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- .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
Advertisement
Add Comment
Please, Sign In to add comment