org 8100h
; Используются ячейки внутренней памяти 2eh..34h, 38h..3bh
p4: equ E8h
p5: equ F8h
e: equ 97h
rs: equ 96h
cr: equ 95h
rw: equ 94h
; For scan_btn.asm
start_key: equ 40h
line_key: equ 50h
num_key: equ 51h
btn_num: equ 60h
; For course.asm
oct_num: equ 61h ; номер октавы
note_num: equ 62h ; номер ноты
time10ms: equ 63h ; интервалы в 10мс
next_time: equ 64h ; момент следующей смены T1
lastNum: equ 65h ; номер последней нажатой клавиши
prevNum: equ 6Bh
btn_play: equ 66h ; клавиша для воспроизведения
mode: equ 67h ; режим работы
prevTime: equ 68h
table_num: equ 69h ; номер в таблице длительности
cntMelody: equ 6Ah ; кол-во нот в мелодии (её длительность)
tmp_th0: equ 70h ; временные значения для TH0
tmp_tl0: equ 71h ; временные значения для TL0
;------------------------------------------------------------------------------------------
main: lcall init_display
lcall init_t0
lcall init_t1
lcall init_course
loop: ;clr et0 ; опасно здесь использовать отключение обработчика прерывания
lcall keyboard ; если воспроизводим звук из памяти, то вызывать keyboard не нужно!!!
;setb et0
lcall keynotes
sjmp loop
ret
;------------------------------------------------------------------------------------------
; FUNCTION keynotes
keynotes:
push psw
push dph
push dpl
push a
mov dptr, #notes
; btn_play - для воспроизведения
; btn_num - моментальное нажатие клавиши
; Проверка режима работы
mov a, mode
cjne a, #2, $whichMode
$modeTwo:
; ОБРАБОТКА НАЖАТИЯ 13 КЛАВИШИ!!!!!!!!!!!!!!!!!!!!!!!!!!!!
mov a, btn_play
sjmp $endMode
$whichMode:
jnc $modeThree
$modeOne:
mov a, btn_num
sjmp $endMode
$modeThree:
mov a, btn_num
$endMode:
;mov a, btn_play
jz $zero
cjne a, #13, $next
$next: jnc $over
push a
dec a
rl a
mov dptr, #table
push a
movc a, @a + dptr
mov tmp_th0, a
pop a
inc a
movc a, @a + dptr
mov tmp_tl0, a
pop a
mov dptr, #notes
$pos: inc dptr
inc dptr
djnz a, $pos
ljmp $zero
$over: ; Если нажата кнопка старше 12
cjne a, #13, $above ; если нажата кнопка 13 (смена октавы)
; если не равно 13, то переходим на $above
;cjne a, lastNum, $difkey
;sjmp $zero
;$difkey:
mov a, mode
cjne a, #3, $cntMode
$cntMode:
jnc $overCnt
inc mode
sjmp $endCnt
$overCnt:
mov mode, #1
$endCnt:
$above: ; Если нажата кнопка старше 13
$zero: ; Если номер клавиши равен 0
; Вывод ноты
mov a, #20 ;x (byte)
mov b, #20 ;y (byte)
mov r0, #2 ;size of string
lcall hstr_xy
; Вывод номера режима
mov dptr, #modes
mov a, mode
$posCnt: inc dptr
djnz a, $posCnt
mov a, #23
mov b, #18
mov r0, #1
lcall hstr_xy
pop a
pop dpl
pop dph
pop psw
ret
; FUNCTION init_to
init_t0:
mov a, tmod
anl a, #11110000b
orl a, #00000001b ; 16 bit T/C0
mov tmod, a
clr p1.0 ; вывод сигнала на P1.0
clr p1.2 ; для осциллографа
;setb it0 ; бит управления типом прерывания 0 (INT0)
setb et0 ; бит разрешения прерывания по переполнению T0
setb tr0 ; бит управления T0
setb ea ; бит разрешения работы контроллера прерываний
ret
; FUNCTION init_t1
init_t1:
mov a, tmod
anl a, #00001111b
orl a, #00010000b ; 16 bit T/C1
mov tmod, a
clr p1.1 ; вывод сигнала на P1.1
setb et1 ; бит разрешения прерывания по переполнению T1
setb tr1 ; бит управления T1
setb ea ; бит разрешения работы контроллера прерываний
mov time10ms, #0
ret
; FUNCTION init_course
init_course:
; ВЫБОР РЕЖИМА ПРОГРАММНО
mov mode, #1 ; режим
mov oct_num, #0 ; номер октавы
mov note_num, #0 ; номер ноты
mov lastNum, #0 ; последняя нажатая клавиша
mov prevNum, #0
mov cntMelody, #1 ; счетчик нот в мелодии
mov prevTime, #0
; Значения для вывода мелодии
mov next_time, #0 ; значения следующего момента времени
mov table_num, #0 ; положение в таблице
; Вывод слова SYNTHESIZER
mov a, #15 ;x (byte)
mov b, #11 ;y (byte)
mov r0, #11 ;size of string
mov dptr, #vsim
lcall hstr_xy
; Вывод слова VSIM
mov a, #18 ;x (byte)
mov b, #13 ;y (byte)
mov r0, #4 ;size of string
mov dptr, #vsim+12
lcall hstr_xy
; Вывод слова Octave
mov a, #17
mov b, #16
mov r0, #6
mov dptr, #oct_str
lcall hstr_xy
; Вывод первой октавы
mov a, #24
mov b, #16
mov r0, #1
mov dptr, #octaves+9
lcall hstr_xy
; Вывод слова Mode
mov a, #18
mov b, #18
mov r0, #4
mov dptr, #mode_str
lcall hstr_xy
; Вывод первого режима
mov a, #23
mov b, #18
mov r0, #1
mov dptr, #modes+1
lcall hstr_xy
ret
;------------------------------------------------------------------------------------------
;***************************************************************************
; INTERRUPT intT0
intT0:
push a
push dph
push dpl
push psw
; Проверка режима работы
mov a, mode
cjne a, #2, $whichMode
$modeTwo:
mov a, btn_play
sjmp $endMode
$whichMode:
jnc $modeThree
$modeOne:
mov a, btn_num
sjmp $endMode
$modeThree:
mov a, btn_num
$endMode:
; lastNum - звучание после отпускания клавиши
; btn_num - звучание во время нажатия
;mov a, btn_play
jz $zero
cjne a, #13, $next
$next: jnc $over ; проверка, нажата ли клавиша
mov th0, tmp_th0
mov tl0, tmp_tl0
cpl p1.0 ; вывод сигнала на P1.0
cpl p1.2 ; наблюдение за сигналом по осциллографу на P1.2
$zero:
$over:
pop psw
pop dpl
pop dph
pop a
reti
; INTERRUPT intT1
intT1:
push a
push dph
push dpl
push psw
mov a, #ECh
mov th1, a
mov a, #77h
mov tl1, a
cpl p1.1 ; вывод сигнала на P1.1 (100 Hz)
; Проверка режима работы
mov a, mode
cjne a, #2, $whichMode
$modeTwo:
; Проверка длительности ноты
mov a, next_time
cjne a, time10ms, $not_equal
mov dptr, #melody_MerryChristmas ; длительность
mov a, table_num
movc a, @a + dptr ; get duration from the table
add a, time10ms ; a = next_time
mov next_time, a
mov a, table_num
cjne a, #60, $over1
mov table_num, #0
$over1:
inc table_num
mov dptr, #notes_MerryChristmas ; частоты
mov a, note_num
; Количество нот в мелодии, включая пропуски
cjne a, #60, $over2
mov note_num, #0
$over2:
movc a, @a + dptr
; Следующая нота для вывода
mov btn_play, a
inc note_num
sjmp $endMode
$whichMode:
jnc $modeThree
$modeOne:
sjmp $endMode
$modeThree:
mov a, btn_num
cjne a, prevNum, $difKey
jz $zeroNum
jmp $same
$zeroNum:
sjmp $endMode
$difKey: mov prevNum, a
; сохранение частоты
mov a, cntMelody
cjne a, #60, $next
$next: jnc $delete
sjmp $notdelete
$delete: mov cntMelody, #1
$notdelete:
mov dptr, #notes_MerryChristmas - 1
$posNote:
inc dptr
djnz a, $posNote
mov a, prevNum
movx @dptr, a
; сохранение длительности
mov dptr, #melody_MerryChristmas - 2
mov a, cntMelody
$posMel:
inc dptr
djnz a, $posMel
mov a, time10ms
clr c
subb a, prevTime
mov prevTime, time10ms
movx @dptr, a
inc cntMelody
$same:
$endMode:
$not_equal:
; Для воспроизведения мелодии переменная time10ms должна инкрементироваться!
inc time10ms
pop psw
pop dpl
pop dph
pop a
reti
;***************************************************************************
vsim: db 'SYNTHESIZER VSIM'
notes: db ' C C#D D#E F F#G G#A A#B '
octaves: db '-4-3-2-1 1 2 3 4 5'
oct_str: db 'Octave'
mode_str: db 'Mode'
modes: db ' 123'
; table of frequency C1 - B1
table: dw F89Ch, F907h, F96Dh, F9CCh, FA26h, FA7Ch, FACCh, FB18h, FB5Fh, FBA3h, FBE3h, FC1Fh
; gamma Octave 1
gamma: dw F89Ch, F96Dh, FA26h, FA7Ch, FB18h, FBA3h, FC1Fh
org 9900h
;new_notes: blkb 100
;new_melody: blkb 100
notes_MerryChristmas:
db 3, 0, 8, 0, 8, 0, 10, 0
db 8, 0, 7, 0, 5, 0, 5, 0
db 5, 0, 10, 0, 10, 0, 12, 0
db 10, 0, 8, 0, 7, 0, 3, 0
db 3, 0, 12, 0, 12, 0, 1, 0 ; (C2 вместо 1)
db 12, 0, 10, 0, 8, 0, 5, 0
db 3, 0, 3, 0, 5, 0, 10, 0
db 7, 0, 8, 0
division: db 0
melody_MerryChristmas:
db 100, 1, 100, 1, 50, 1, 50, 1
db 50, 1, 50 ,1, 100, 1, 100, 1
db 100, 1, 100, 1, 50, 1, 50, 1
db 50, 1, 50, 1, 100, 1, 100, 1
db 100, 1, 100, 1, 50, 1, 50, 1
db 50, 1, 50, 1, 100, 1, 100, 1
db 50, 1, 50, 1, 100, 1, 100, 1
db 100, 1, 200, 1
config_lcd:
db 01h ;1-й байт: тип ЖКИ: 01 - монохромный, 02 - цветной
db F8h ;2-й байт: адрес порта команд/данных (90h - P1, E8h - P4, F8h - P5)
db 90h ;3-й байт: адрес порта управления (90h - P1, E8h - P4, F8h - P5)
db 02h ;4-й байт: номер тетрады порта управления (2 - ст, 1 - мл)
db 02h,00h,00h,02h,00h,00h,02h,00h,00h,02h,00h,00h,02h,00h,00h,02h,00h,00h
;5-й - 22-й байты: зарезервированы; не изменять
include C:\\ASMS\3531201\Course\scan_btn.asm
include C:\\ASMS\3531201\Course\freq_tbl.asm
include C:\\ASMS\3531201\Course\lcd_api.asm
; Точки входа в обработчики прерываний
; Прерывание от таймера 0
org 800bh
ljmp intT0
; Прерывание от таймера 1
org 801bh
ljmp intT1