-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsound.asm
162 lines (129 loc) · 3.58 KB
/
sound.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
; file: sound.asm target ATmega128L-4MHz-STK300
; Piezoelectric library for sound
; Copyright 2023: Daniel Panero (342800), Yasmina Jemili (310507)
; Scratch registers (values are preserved via the stack):
.def period = r22
.def durationl = r23
.def durationh = r24
.def scale_index = r25
.dseg
duration_address: .byte 1
scale_address: .byte 1
.cseg
sound_init:
sbi DDRE,SPEAKER ; Make pin SPEAKER an output
push durationh
push scale_index
EEPROM_READ duration_address, durationh
sts duration_address, durationh
EEPROM_READ scale_address, scale_index
sts scale_address, scale_index
pop scale_index
pop durationh
ret
; Plays a note selected using scale selection and the index of note (preloaded)
sound_play_note:
push period ; Saving values of the scratch registers
push durationl
push durationh
push scale_index
lds scale_index, scale_address
LDIZ 2*(notes_tbl)
sound_scale_load: ; Since there eight notes in a scale, it multiplies the pointer by 8 to find the next scale
tst scale_index
breq sound_note_load ; If the selected scale is Do Major, it directly goes to loading the note
adiw zh:zl, 8
DJNZ scale_index, sound_scale_load
sound_note_load: ; Going through the notes_tbl: note_index = 0 --> lowest note, note_index = 6 --> highest note:
ADDZ note_index
lpm
mov period, r0
sound:
clr durationl
lds durationh, duration_address
tst period ; If period equals 0, no sound
brne PC+2
rjmp sound_off
sound_on:
push period ; Saving period before modifying it
sound_loop:
WAIT_US 9
; 4 cycles = 1us
dec period ; 1 cycles
tst period ; 1 cycles
brne sound_loop ; 2 cycles
INVP PORTE,SPEAKER
pop period ; Restoring initial value of period
sub durationl, period
brsh PC+2 ; C = 0 (durationl > period)
subi durationh, 1 ; C = 1 (durationl < period)
brcc PC+2 ; C = 0 (period - duration > 0)
rjmp sound_restore_registers ; C=1 (period - duration < 0)
tst durationh
brne PC+2 ; Z= 0 (period > 0)
rjmp sound_restore_registers; Z=1 (period - duration = 0)
rjmp sound_on
sound_off:
WAIT_US 8
; 8 cacles = 2 us
DEC2 durationh, durationl ; 3 cycles
TST2 durationh, durationl ; 3 cycles
brne sound_off ; 2 cycles
rjmp sound_restore_registers
sound_restore_registers:
pop scale_index
pop durationh
pop durationl
pop period
ret
.equ do = 100000/523
.equ dod = 100000/554
.equ reb = 100000/554
.equ re = 100000/587
.equ red = 100000/622
.equ mib = 100000/622
.equ mi = 100000/659
.equ fa = 100000/698
.equ fad = 100000/739
.equ sob = 100000/739
.equ so = 100000/783
.equ sod = 100000/830
.equ lab = 100000/880
.equ la = 100000/880
.equ lad = 100000/923
.equ sib = 100000/923
.equ si = 100000/987
.equ do2 = do/2
.equ dod2 = dod/2
.equ reb2 = reb/2
.equ re2 = re/2
.equ red2 = red/2
.equ mib2 = mib/2
.equ mi2 = mi/2
.equ fa2 = fa/2
.equ fad2 = fad/2
.equ sob2 = sob/2
.equ so2 = so/2
.equ sod2 = sod/2
.equ lab2 = lab/2
.equ la2 = la/2
.equ lad2 = lad/2
.equ sib2 = sib/2
.equ si2 = si/2
.equ scales_tbl_index_min = 0
.equ scales_tbl_index_max = 5
.equ notes_tbl_index_min = 0
.equ notes_tbl_index_max = 7
.equ DO_M = 0
.equ RE_M = 1
.equ MI_M = 2
.equ SO_M = 3
.equ LA_M = 4
.equ SI_M = 5
.cseg
notes_tbl: .db do, re, mi, fa, so, la, si, do2, ; Do Major
.db so, la, si, do2, re2, mi2, fad2, so2, ; Sol Major
.db re, mi, fad, so, la, si, dod2, re2, ; Re Major
.db la, si, dod2, re2, mi2, fad2, sod2, la2, ; La Major
.db si, dod, red, mi, fad, sod, lad, si2 ; Si Major
.db mi, fad, sod, la, si, dod2, red2, mi2 ;Mi Major