refactored

This commit is contained in:
Sergey Yarkov 2022-05-25 23:51:13 +03:00
parent 26143bef1a
commit 079637a034
3 changed files with 1245 additions and 1094 deletions

View File

@ -16,6 +16,7 @@
;
; Registers
.def seq_length_r = r10 ; Current length of sequence
.def wdt_counter = r11 ; Counter for wathdog timer
.def temp_r = r16 ; Temp general register A
.def temp_r_b = r23 ; Temp general register B
.def temp_r_c = r26 ; Temp general register C
@ -75,25 +76,22 @@
.dseg ; Data segment
.org SRAM_START
;
; MCU Global states addresses
CURRENT_STATE_ADDRESS: .byte 0x01
PREVIOUS_STATE_ADDRESS: .byte 0x01
;
; Button flags
SW_FLAGS_ADDRESS: .byte 0x01
.cseg ; Code segment
.org 0x00
;
; Setup vectors
rjmp start ; Program start at RESET vector
; MCU vectors
rjmp RESET_vect ; Program start at RESET vector
reti ; External Interrupt Request 0 / inactive
rjmp PCINT0_vect ; Pin Change Interrupt Request 0 / active
reti ; Pin Change Interrupt Request 1 / inactive
reti ; Watchdog Time-out / inactive
rjmp WDT_vect ; Watchdog Time-out / active
reti ; Timer/Counter1 Capture Event / inactive
reti ; Timer/Counter1 Compare Match A / inactive
reti ; Timer/Counter1 Compare Match B / inactive
@ -107,27 +105,44 @@ reti ; EEPROM Ready / inactive
reti ; USI START / inactive
reti ; USI Overflow / inactive
;
; Interrupt service routines
PCINT0_vect: ; Button handler
; watchdog time-out interrupt handler
WDT_vect:
in temp_r_c, WDTCSR
ldi temp_r_c, (1<<WDIE)
out WDTCSR, temp_r_c
inc wdt_counter
reti
; pin change on button interrupt handler
PCINT0_vect:
push r17
push r18
in r18, SREG ; Save status register
in r18, MCUCR
cbr r18, (1<<SE)
; turn off the sleep mode
out MCUCR, r18
; save status register
in r18, SREG
lds mcu_state_r, CURRENT_STATE_ADDRESS
cpi mcu_state_r, POLLING_STATE
brne quit ; Do not change button flags unless in POLLING state of mcu
in r17, PINA ; Load current pins status of PINA
andi r17, 0xf0 ; Get pins status of only buttons
rcall delay_20ms ; Delay for button
sts SW_FLAGS_ADDRESS, r17 ; Update flag status in SRAM
; do not change button flags unless in POLLING state of mcu
brne quit
in r17, PINA
; get pins status of only buttons
andi r17, 0xf0
; button debounce
rcall delay_20ms
; update flag status in SRAM
sts SW_FLAGS_ADDRESS, r17
out SREG, r18
quit:
pop r18
pop r17
reti
reti
TIM0_OVF_vect: ; Random byte generator
; random byte generator
TIM0_OVF_vect:
push temp_r_b
in temp_r_b, SREG
@ -142,15 +157,17 @@ TIM0_OVF_vect: ; Random byte generator
add r21, temp_r
out SREG, temp_r_b
pop temp_r_b
reti
reti
MCU_Init: ; This function executes once on start the main program
; initialize MCU
MCU_Init:
rcall init_ports
rcall init_interrupts
rcall init_buzzer
rcall init_sm
; rcall init_wdt
;
; Init important registers for game
; init important registers for game
ldi delay_counter_r, 0xff
ldi poll_step_r, 1
ldi temp_r_c, SEQ_LENGTH
@ -158,10 +175,11 @@ MCU_Init: ; This function executes once on start the main program
clr ZH
ldi ZL, $80
rcall MCU_Delay ; Wait 1 sec before start main program
; delay before start main loop
rcall MCU_Delay
sei ; Enable Global Interrupts
ret
sei
ret
MCU_Delay:
ldi temp_r_b, 3
@ -171,33 +189,39 @@ MCU_Delay:
brne _init_loop_loading
rcall delay_1s
clr temp_r_b
ret
ret
;
; Program start at reset
start:
; program start at reset vector
RESET_vect:
init_stack_p temp_r, RAMEND
set_state INIT_STATE
loop: ; Program loop
; main program loop
loop:
lds mcu_state_r, CURRENT_STATE_ADDRESS
init: ; Init state
; init state
init:
cpi mcu_state_r, INIT_STATE
brne showing
rcall MCU_Init
set_state SHOWING_STATE
showing: ; Showing state
; showing state
showing:
cpi mcu_state_r, SHOWING_STATE
brne polling
rcall show_sequence ; Generate sequence and save answer to SRAM
; generate sequence and save answer to SRAM
rcall show_sequence
set_state POLLING_STATE
polling: ; Polling state
; polling state
polling:
cpi mcu_state_r, POLLING_STATE
brne default
btn_1:
lds r18, SW_FLAGS_ADDRESS
cpi r18, SW_FLAG_1
brne btn_2 ; Check next button
brne btn_2
led_on_1:
outi OCR0A, 142
sbi LED_PORT, 0
@ -206,6 +230,7 @@ loop: ; Program loop
cbi LED_PORT, 0
cbi BUZZ_DIR, BUZZ_PIN
rjmp btn_1
btn_2:
lds r18, SW_FLAGS_ADDRESS
cpi r18, SW_FLAG_2
@ -218,6 +243,7 @@ loop: ; Program loop
cbi LED_PORT, 1
cbi BUZZ_DIR, BUZZ_PIN
rjmp btn_2
btn_3:
lds r18, SW_FLAGS_ADDRESS
cpi r18, SW_FLAG_3
@ -230,6 +256,7 @@ loop: ; Program loop
cbi LED_PORT, 2
cbi BUZZ_DIR, BUZZ_PIN
rjmp btn_3
btn_4:
lds r18, SW_FLAGS_ADDRESS
cpi r18, SW_FLAG_4
@ -242,12 +269,13 @@ loop: ; Program loop
cbi LED_PORT, 3
cbi BUZZ_DIR, BUZZ_PIN
rjmp btn_4
default:
rcall OCR0A_reset
rjmp loop
rjmp loop
btn_handler: ; Check the input value with answer in SRAM
; check the input value with answer in SRAM
btn_handler:
push r18
rcall delay_50ms
rcall delay_50ms
@ -260,8 +288,10 @@ btn_handler: ; Check the input value with answer in SRAM
sts SW_FLAGS_ADDRESS, temp_r_c
ld r24, Z+
cp r25, r24 ; Check answer
brne _game_over ; Game over
; check answer
cp r25, r24
; game over
brne _game_over
mov r18, seq_length_r
cp r18, poll_step_r
@ -290,10 +320,11 @@ btn_handler: ; Check the input value with answer in SRAM
rcall effect_2
rcall reset_game
ret
_btn_handler_exit:
pop r18
ret
ret
ret
reset_game:
clr ZH
@ -305,49 +336,53 @@ reset_game:
set_state SHOWING_STATE
ldi poll_step_r, 1
inc seq_length_r
ret
ret
gen_ran_seq: ; Generate random sequence of bytes for leds and save answer to SRAM
; generate random sequence of bytes for leds and save answer to SRAM
gen_ran_seq:
mov temp_r_b, seq_length_r
clr YH
ldi YL, $80
_gen_ran_loop:
rcall delay_50ms ; Delay is required!
mov r22, r21
_gen_ran_loop:
; delay is required
rcall delay_50ms
mov r22, r21
cpi r22, 70
brlo _gen_answ_1
cpi r22, 140
brlo _gen_answ_2
cpi r22, 200
brlo _gen_answ_3
cpi r22, 255
brlo _gen_answ_4
_gen_answ_1:
ldi temp_r_c, 0x01
rjmp _gen_ran_write
_gen_answ_2:
ldi temp_r_c, 0x02
rjmp _gen_ran_write
_gen_answ_3:
ldi temp_r_c, 0x04
rjmp _gen_ran_write
_gen_answ_4:
ldi temp_r_c, 0x08
_gen_ran_write:
st Y+, temp_r_c
dec temp_r_b
cpi temp_r_b, 0
brne _gen_ran_loop
nop
ret
ret
show_sequence:
rcall gen_ran_seq ; Answer stored in SRAM in addr $80:{SEQ_LENGTH}
; answer stored in SRAM in addr $80:{SEQ_LENGTH}
rcall gen_ran_seq
show_start:
mov temp_r_b, seq_length_r
@ -357,17 +392,13 @@ show_sequence:
_sequence_loop:
cpi temp_r_b, 0
breq _seq_quit
ld temp_r_c, Y+
cpi temp_r_c, 0x01
breq beep_1
cpi temp_r_c, 0x02
breq beep_2
cpi temp_r_c, 0x04
breq beep_3
cpi temp_r_c, 0x08
breq beep_4
@ -375,17 +406,21 @@ show_sequence:
beep_led_1
rcall OCR0A_reset
rjmp beep_quit
beep_2:
beep_led_2
rcall OCR0A_reset
rjmp beep_quit
beep_3:
beep_led_3
rcall OCR0A_reset
rjmp beep_quit
beep_4:
beep_led_4
rcall OCR0A_reset
beep_quit:
rcall delay
dec temp_r_b
@ -395,14 +430,20 @@ show_sequence:
_seq_quit:
rcall dec_delay_counter
rcall delay_50ms
ret
OCR0A_reset: ; This function need to set the OCR0A register to 0xff for overflow interrupt
; in temp_r_c, MCUCR
; sbr temp_r_c, (1<<SE)
; out MCUCR, temp_r_c
; sleep
ret
; this function need to set the OCR0A register to 0xff for overflow interrupt
OCR0A_reset:
push temp_r_b
ldi temp_r_b, 0xff
out OCR0A, temp_r_b
pop temp_r_b
ret
ret
dec_delay_counter:
subi delay_counter_r, 10
@ -411,13 +452,14 @@ dec_delay_counter:
ret
_reset_counter:
ldi delay_counter_r, 0xff
ret
ret
effect_1: ; Shift bits of an leds in port every 50ms
push r17
push r18
push r19
push r20
cli
in r20, LED_PORT
@ -425,7 +467,9 @@ effect_1: ; Shift bits of an leds in port every 50ms
rcall delay_50ms
ldi r17, 0x01
ldi r19, 3
_eff_1_shift_l: ; Shift bits to left loop
; shift bits to left loop
_eff_1_shift_l:
ldi r18, 0xf0
lsl r17
add r18, r17
@ -438,7 +482,9 @@ effect_1: ; Shift bits of an leds in port every 50ms
rcall delay_50ms
ldi r17, 0x08
ldi r19, 3
_eff_1_shift_r: ; Shift bits to right loop
; shift bits to right loop
_eff_1_shift_r:
ldi r18, 0xf0
lsr r17
add r18, r17
@ -448,13 +494,14 @@ effect_1: ; Shift bits of an leds in port every 50ms
brne _eff_1_shift_r
sei
; Out saved PORT values
; out saved PORT values
out LED_PORT, r20
pop r20
pop r19
pop r18
pop r17
ret
ret
effect_2:
outi OCR0A, 142
@ -488,49 +535,75 @@ effect_2:
rcall delay_50ms
cbi LED_PORT, 3
cbi BUZZ_DIR, BUZZ_PIN
ret
ret
init_interrupts:
;
; Enable Port Change Interrupt
; enable Port Change Interrupt
ldi temp_r, (1<<PCIE0)
out GIMSK, temp_r
;
; Set Pin Change Mask Register
; set Pin Change Mask Register
ldi temp_r, (1<<PCINT4) | (1<<PCINT5)| (1<<PCINT6) | (1<<PCINT7)
out PCMSK0, temp_r
clr temp_r
ret
ret
init_buzzer:
cbi BUZZ_DIR, BUZZ_PIN
; Setup timer
ldi temp_r, (1<<COM0A0) | (1<<WGM01) ; Set CTC timer mode and toggle OC0A pin on Compare Match
; setup timer
ldi temp_r, (1<<COM0A0) | (1<<WGM01)
; set CTC timer mode and toggle OC0A pin on Compare Match
out TCCR0A, temp_r
ldi temp_r, 255
out OCR0A, temp_r
ldi temp_r, (1<<CS01) ; Prescale on 8
ldi temp_r, (1<<CS01)
; prescale on 8
out TCCR0B, temp_r
ldi temp_r, (1<<TOIE0) ; Enable Timer/Counter0 Overflow Interrupt
ldi temp_r, (1<<TOIE0)
; enable Timer/Counter0 Overflow Interrupt
out TIMSK0, temp_r
ret
ret
init_ports: ; Init MCU ports
ldi temp_r, 0x0f ; Setup PORTA
out DDRA, temp_r ; Set directions of leds and buttons
; setup PORTA
ldi temp_r, 0x0f
; set directions of leds and buttons
out DDRA, temp_r
swap temp_r
out PORTA, temp_r ; Set low signal on leds and pull-up on buttons
; set low signal on leds and pull-up on buttons
out PORTA, temp_r
; Setup PORTB
; setup PORTB
sbi DDRB, BUZZ_PIN ; Set direction of buzzer pin to output
cbi PORTB, BUZZ_PIN ; Set low signal on buzzer
ret
ret
init_sm:
in temp_r, MCUCR
ori temp_r, (1<<SM1)
; config sleep mode to power-down
out MCUCR, temp_r
ret
init_wdt:
cli
wdr
in temp_r, WDTCSR
ori temp_r, (1<<WDCE) | (1<<WDE)
; allow changing the watchdog bits and enable watchdog
out WDTCSR, temp_r
ldi temp_r, (1<<WDE) | (1<<WDIE) | (1<<WDP2) | (1<<WDP0)
; config watchdog to interrupt mode and setup prescaler (0.5 sec)
out WDTCSR, temp_r
sei
ret
delay: ; For 1MHz frequency
push r18
@ -547,7 +620,7 @@ delay: ; For 1MHz frequency
nop
pop r20
pop r18
ret
ret
delay_20ms:
push r18
@ -562,7 +635,7 @@ delay_20ms:
brne _loop_d_20ms
pop r19
pop r18
ret
ret
delay_50ms: ; For 1MHz frequency
push r18
@ -578,20 +651,21 @@ delay_50ms: ; For 1MHz frequency
nop
pop r19
pop r18
ret
ret
delay_1s: ; For 1MHz frequency
push r24
push r25
.equ outer_count = 100
.equ inner_count = 2499
ldi r18, outer_count
_reset:
_reset:
ldi r24, low(inner_count)
ldi r25, high(inner_count)
_loop:
_loop:
sbiw r24, 1
brne _loop
dec r18
@ -599,6 +673,6 @@ _loop:
ldi r18, outer_count
pop r25
pop r24
ret
ret
info: .db "Memory led game. Written by Sergey Yarkov 27.09.2021"

View File

@ -1,64 +1,67 @@
:020000020000FC
:100000003EC018950EC01895189518951895189516
:1000100018951895189515C0189518951895189550
:1000200018951F932F932FB710916000133031F460
:1000300019B3107F93D1109362002FBF2F911F919E
:1000400018957F937FB702C008EA52B7052702953B
:10005000500F7FBF7F9118956CD15BD160D13FEF7E
:1000600041E0A2E0AA2EFF27E0E802D078940895AC
:1000700073E0FDD07A95E9F788D1772708950FEDE1
:100080000DBF0027109361000F9301E00093600003
:100090000F9110916000113041F4DEDF1093610088
:1000A0000F9302E0009360000F91123041F493D05F
:1000B000109361000F9303E0009360000F911330E1
:1000C000C1F520916200203E51F40F930EE806BF67
:1000D0000F91D89ABA9A2FD0D898BA98F2CF209187
:1000E0006200203D51F40F9307E406BF0F91D99AA7
:1000F000BA9A21D0D998BA98F2CF20916200203BC9
:1001000051F40F9309E606BF0F91DA9ABA9A13D009
:10011000DA98BA98F2CF20916200203751F40F9309
:1001200000E506BF0F91DB9ABA9A05D0DB98BA9822
:10013000F2CF92D0AECF2F931CD11BD11AD1A9B33D
:100140009A2FA07F9F70AA27A09362008191981791
:1001500029F42A2D241751F0439510C02F9187D0F0
:100160003FEFA2E0AA95AA2E0CD008952F9100EFA0
:100170000BBBBA98FED0A4D004D008952F91089557
:100180000895FF27E0E8BA9800EF0BBBFED010936C
:1001900061000F9302E0009360000F9141E0A3948F
:1001A00008957A2DDD27C0E8E4D0652F663430F05D
:1001B0006C3830F0683C30F06F3F30F0A1E005C0A3
:1001C000A2E003C0A4E001C0A8E0A9937A95703032
:1001D00059F700000895E5DF7A2DDD27C0E870307B
:1001E000C1F1A991A13031F0A23079F0A430C1F071
:1001F000A83009F10F930EE806BF0F91D89ABA9A6A
:100200009FD0D898BA9828D020C00F9307E406BF93
:100210000F91D99ABA9A94D0D998BA981DD015C08E
:100220000F9309E606BF0F91DA9ABA9A89D0DA9845
:10023000BA9812D00AC00F9300E506BF0F91DB9A5F
:10024000BA9A7ED0DB98BA9807D07AD07A95703077
:1002500031F607D08ED008957F937FEF76BF7F91E0
:1002600008953A50383208F008953FEF08951F93EB
:100270002F933F934F93F8944BB30F9301EF0BBB26
:100280000F9177D011E033E020EF110F210F2BBB3E
:1002900070D03A95C9F70F9308EF0BBB0F9169D057
:1002A00018E033E020EF1695210F2BBB62D03A9572
:1002B000C9F778944BBB4F913F912F911F910895AF
:1002C0000F930EE806BF0F91D89ABA9A52D051D028
:1002D000D898BA980F9309E606BF0F91D99ABA9A9F
:1002E00048D047D0D998BA980F9300E506BF0F9130
:1002F000DA9ABA9A3ED03DD0DA98BA980F9307E4CA
:1003000006BF0F91DB9ABA9A34D033D0DB98BA98F3
:10031000089500E10BBF00EF02BB00270895BA98D3
:1003200002E400BF0FEF06BF02E003BF01E009BF18
:1003300008950FE00ABB02950BBBBA9AC2980895C4
:100340002F934F932FEF432F00002A95E9F70000DA
:100350004A95D1F700004F912F9108952F933F9325
:100360002AE139EF3A95F1F72A95E1F73F912F917C
:1003700008952F933F9321E43FEE3A95F1F72A95A4
:10038000E1F700003F912F9108958F939F9324E60A
:1003900083EC99E00197F1F72A95D1F724E69F9134
:1003A0008F9108954D656D6F7279206C656420673B
:1003B000616D652E205772697474656E20627920B4
:1003C000536572676579205961726B6F7620323799
:0803D0002E30392E323032319B
:1000000047C0189513C018950CC0189518951895E9
:100010001895189518951DC0189518951895189548
:100020001895A1B5A0E4A1BDB39418951F932F9383
:1000300025B72F7D25BF2FB710916000133031F405
:1000400019B3107FA1D1109362002FBF2F911F9180
:1000500018957F937FB702C008EA52B7052702952B
:10006000500F7FBF7F9118956DD15CD161D171D157
:100070003FEF41E0A2E0AA2EFF27E0E802D078940B
:10008000089573E0FDD07A95E9F795D17727089523
:100090000FED0DBF0027109361000F9301E0009357
:1000A00060000F9110916000113041F4DDDF10937A
:1000B00061000F9302E0009360000F91123041F451
:1000C00093D0109361000F9303E0009360000F91B1
:1000D0001330C1F520916200203E51F40F930EE8D9
:1000E00006BF0F91D89ABA9A2FD0D898BA98F2CF63
:1000F00020916200203D51F40F9307E406BF0F9159
:10010000D99ABA9A21D0D998BA98F2CF20916200A0
:10011000203B51F40F9309E606BF0F91DA9ABA9A81
:1001200013D0DA98BA98F2CF20916200203751F4B8
:100130000F9300E506BF0F91DB9ABA9A05D0DB98C2
:10014000BA98F2CF92D0AECF2F9329D128D127D110
:10015000A9B39A2FA07F9F70AA27A09362008191D4
:10016000981729F42A2D241751F0439510C02F9188
:1001700087D03FEFA2E0AA95AA2E0CD008952F9128
:1001800000EF0BBBBA980BD1A4D004D008952F91E7
:1001900008950895FF27E0E8BA9800EF0BBB0BD154
:1001A000109361000F9302E0009360000F9141E013
:1001B000A39408957A2DDD27C0E8F1D0652F663429
:1001C00030F06C3830F0683C30F06F3F30F0A1E038
:1001D00005C0A2E003C0A4E001C0A8E0A9937A95FD
:1001E000703059F700000895E5DF7A2DDD27C0E86B
:1001F0007030C1F1A991A13031F0A23079F0A43072
:10020000C1F0A83009F10F930EE806BF0F91D89AFC
:10021000BA9AACD0D898BA9828D020C00F9307E4E7
:1002200006BF0F91D99ABA9AA1D0D998BA981DD081
:1002300015C00F9309E606BF0F91DA9ABA9A96D0C5
:10024000DA98BA9812D00AC00F9300E506BF0F9152
:10025000DB9ABA9A8BD0DB98BA9807D087D07A9578
:10026000703031F607D09BD008957F937FEF76BF33
:100270007F9108953A50383208F008953FEF08957D
:100280001F932F933F934F93F8944BB30F9301EF2A
:100290000BBB0F9184D011E033E020EF110F210F41
:1002A0002BBB7DD03A95C9F70F9308EF0BBB0F918D
:1002B00076D018E033E020EF1695210F2BBB6FD0DE
:1002C0003A95C9F778944BBB4F913F912F911F916D
:1002D00008950F930EE806BF0F91D89ABA9A5FD08F
:1002E0005ED0D898BA980F9309E606BF0F91D99AB5
:1002F000BA9A55D054D0D998BA980F9300E506BF52
:100300000F91DA9ABA9A4BD04AD0DA98BA980F93EA
:1003100007E406BF0F91DB9ABA9A41D040D0DB9830
:10032000BA98089500E10BBF00EF02BB00270895C3
:10033000BA9802E400BF0FEF06BF02E003BF01E07E
:1003400009BF08950FE00ABB02950BBBBA9AC29889
:10035000089505B7006105BF0895F894A89501B503
:10036000086101BD0DE401BD789408952F934F936A
:100370002FEF432F00002A95E9F700004A95D1F7A7
:1003800000004F912F9108952F933F932AE139EF69
:100390003A95F1F72A95E1F73F912F9108952F9320
:1003A0003F9321E43FEE3A95F1F72A95E1F70000FB
:1003B0003F912F9108958F939F9324E683EC99E0CA
:1003C0000197F1F72A95D1F724E69F918F9108952F
:1003D0004D656D6F7279206C65642067616D652E67
:1003E000205772697474656E206279205365726754
:1003F0006579205961726B6F762032372E30392E35
:040400003230323133
:00000001FF

File diff suppressed because it is too large Load Diff