diff options
Diffstat (limited to 'Source/UnitTests/Core/DSP/HermesText.cpp')
| -rw-r--r-- | Source/UnitTests/Core/DSP/HermesText.cpp | 1086 |
1 files changed, 1086 insertions, 0 deletions
diff --git a/Source/UnitTests/Core/DSP/HermesText.cpp b/Source/UnitTests/Core/DSP/HermesText.cpp new file mode 100644 index 0000000000..f7f83a9737 --- /dev/null +++ b/Source/UnitTests/Core/DSP/HermesText.cpp @@ -0,0 +1,1086 @@ +/* DSP_MIXER -> PCM VOICE SOFTWARE PROCESSOR (8-16 Bits Mono/Stereo Voices) + +// Thanks to Duddie for you hard work and documentation + +Copyright (c) 2008 Hermes <www.entuwii.net> +All rights reserved. + +SPDX-License-Identifier: BSD-3-Clause + +*/ + +#include "HermesText.h" + +const char s_hermes_text[21370] = R"( +/********************************/ +/** REGISTER NAMES **/ +/********************************/ + +AR0: equ 0x00 ; address registers +AR1: equ 0x01 +AR2: equ 0x02 +AR3: equ 0x03 // used as jump function selector + +IX0: equ 0x04 // LEFT_VOLUME accel +IX1: equ 0x05 // RIGHT_VOLUME accel +IX2: equ 0x06 // ADDRH_SMP accel +IX3: equ 0x07 // ADDRL_SMP accel + +R08: equ 0x08 // fixed to 48000 value +R09: equ 0x09 // problems using this +R0A: equ 0x0a // ADDREH_SMP accel +R0B: equ 0x0b // ADDREL_SMP accel + +ST0: equ 0x0c +ST1: equ 0x0d +ST2: equ 0x0e +ST3: equ 0x0f + +CONFIG: equ 0x12 +SR: equ 0x13 + +PRODL: equ 0x14 +PRODM: equ 0x15 +PRODH: equ 0x16 +PRODM2: equ 0x17 + +AXL0: equ 0x18 +AXL1: equ 0x19 +AXH0: equ 0x1A // SMP_R accel +AXH1: equ 0x1b // SMP_L accel + +ACC0: equ 0x1c // accumulator (global) +ACC1: equ 0x1d + +ACL0: equ 0x1c // Low accumulator +ACL1: equ 0x1d +ACM0: equ 0x1e // Mid accumulator +ACM1: equ 0x1f +ACH0: equ 0x10 // Sign extended 8 bit register 0 +ACH1: equ 0x11 // Sign extended 8 bit register 1 + +/********************************/ +/** HARDWARE REGISTER ADDRESS **/ +/********************************/ + +DSCR: equ 0xffc9 ; DSP DMA Control Reg +DSBL: equ 0xffcb ; DSP DMA Block Length +DSPA: equ 0xffcd ; DSP DMA DMEM Address +DSMAH: equ 0xffce ; DSP DMA Mem Address H +DSMAL: equ 0xffcf ; DSP DMA Mem Address L + +DIRQ: equ 0xfffb ; DSP Irq Request +DMBH: equ 0xfffc ; DSP Mailbox H +DMBL: equ 0xfffd ; DSP Mailbox L +CMBH: equ 0xfffe ; CPU Mailbox H +CMBL: equ 0xffff ; CPU Mailbox L + +DMA_TO_DSP: equ 0 +DMA_TO_CPU: equ 1 + +/**************************************************************/ +/* NUM_SAMPLES SLICE */ +/**************************************************************/ + +NUM_SAMPLES: equ 1024 ; 1024 stereo samples 16 bits + + +/**************************************************************/ +/* SOUND CHANNEL REGS */ +/**************************************************************/ + +MEM_REG2: equ 0x0 +MEM_VECTH: equ MEM_REG2 +MEM_VECTL: equ MEM_REG2+1 +RETURN: equ MEM_REG2+2 + +/**************************************************************/ +/* CHANNEL DATAS */ +/**************************************************************/ + +MEM_REG: equ MEM_REG2+0x10 + +ADDRH_SND: equ MEM_REG // Output buffer +ADDRL_SND: equ MEM_REG+1 + +DELAYH_SND: equ MEM_REG+2 // Delay samples High word +DELAYL_SND: equ MEM_REG+3 // Delay samples Low word + +CHAN_REGS: equ MEM_REG+4 // specific regs for the channel + +FLAGSH_SMP: equ CHAN_REGS+0 // countain number of bytes for step (1-> Mono 8 bits, 2-> Stereo 8 bits and Mono 16 bits, 4-> Stereo 16 bits) +FLAGSL_SMP: equ CHAN_REGS+1 // 0->Mono 8 bits, 1->Stereo 8 bits, 2->Mono 16 bits 3 -> Stereo 16 bits + +ADDRH_SMP: equ CHAN_REGS+2 // start address +ADDRL_SMP: equ CHAN_REGS+3 + +ADDREH_SMP: equ CHAN_REGS+4 // end address +ADDREL_SMP: equ CHAN_REGS+5 + +FREQH_SMP: equ CHAN_REGS+6 // Freq in Hz to play +FREQL_SMP: equ CHAN_REGS+7 + +SMP_L: equ CHAN_REGS+8 // last sample for left (used to joint various buffers) +SMP_R: equ CHAN_REGS+9 // last sample for right (used to joint various buffers) + +COUNTERH_SMP: equ CHAN_REGS+10 // pitch counter +COUNTERL_SMP: equ CHAN_REGS+11 + +LEFT_VOLUME: equ CHAN_REGS+12 // volume (0 to 255) +RIGHT_VOLUME: equ CHAN_REGS+13 + +ADDR2H_SMP: equ CHAN_REGS+14 // start address of buffer two (to joint) +ADDR2L_SMP: equ CHAN_REGS+15 + +ADDR2EH_SMP: equ CHAN_REGS+16 // end address of buffer two (to joint) +ADDR2EL_SMP: equ CHAN_REGS+17 + +LEFT_VOLUME2: equ CHAN_REGS+18 // volume (0 to 255) for buffer two +RIGHT_VOLUME2: equ CHAN_REGS+19 + +BACKUPH_SMP: equ CHAN_REGS+20 // start address backup +BACKUPL_SMP: equ CHAN_REGS+21 + +/**************************************************************/ +/* VOICE SAMPLE BUFFER DATAS */ +/**************************************************************/ + +MEM_SAMP: equ CHAN_REGS+0x20 + + +data_end: equ MEM_SAMP+0x20 + +/**************************************************************/ +/* SND OUTPUT DATAS */ +/**************************************************************/ + +MEM_SND: equ data_end ; it need 2048 words (4096 bytes) + + + +/*** START CODE ***/ + +/**************************************************************/ +/* EXCEPTION TABLE */ +/**************************************************************/ + + jmp exception0 + jmp exception1 + jmp exception2 + jmp exception3 + jmp exception4 + jmp exception5 + jmp exception6 + jmp exception7 + + lri $CONFIG, #0xff + lri $SR,#0 + s16 + clr15 + m0 + +/**************************************************************/ +/* main */ +/**************************************************************/ + +main: + +// send init token to CPU + + si @DMBH, #0xdcd1 + si @DMBL, #0x0000 + si @DIRQ, #1 + +recv_cmd: +// check if previous mail is received from the CPU + + call wait_for_dsp_mail + +// wait a mail from CPU + + call wait_for_cpu_mail + + si @DMBH, #0xdcd1 + + clr $ACC0 + lri $ACM0,#0xcdd1 + cmp + jz sys_command + + clr $ACC1 + lrs $ACM1, @CMBL + + cmpi $ACM1, #0x111 // fill the internal sample buffer and process the voice internally + jz input_samples + + cmpi $ACM1, #0x112 // get samples from the external buffer to the internal buffer and process the voice mixing the samples internally + jz input_samples2 + + cmpi $ACM1, #0x123 // get the address of the voice datas buffer (CHANNEL DATAS) + jz get_data_addr + + cmpi $ACM1, #0x222 // process the voice mixing the samples internally + jz input_next_samples + + cmpi $ACM1, #0x666 // send the samples for the internal buffer to the external buffer + jz send_samples + + cmpi $ACM1, #0x777 // special: to dump the IROM Datas (remember disable others functions from the interrupt vector to use) + jz rom_dump_word // (CMBH+0x8000) countain the address of IROM + + cmpi $ACM1, #0x888 // Used for test + jz polla_loca + + cmpi $ACM1, #0x999 + jz task_terminate + + si @DMBL, #0x0004 // return 0 as ignore command + si @DIRQ, #0x1 // set the interrupt + jmp recv_cmd + +task_terminate: + si @DMBL, #0x0003 + si @DIRQ, #0x1 + jmp recv_cmd + +sys_command: + clr $ACC1 + lrs $ACM1, @CMBL + + cmpi $ACM1,#0x0001 + jz run_nexttask + + cmpi $ACM1,#0x0002 + jz 0x8000 + + jmp recv_cmd + +run_nexttask: + s16 + call wait_for_cpu_mail + lrs $29,@CMBL + call wait_for_cpu_mail + lrs $29,@CMBL + call wait_for_cpu_mail + lrs $29,@CMBL + call wait_for_cpu_mail + lr $5,@CMBL + andi $31,#0x0fff + mrr $4,$31 + call wait_for_cpu_mail + lr $7,@CMBL + call wait_for_cpu_mail + lr $6,@CMBL + call wait_for_cpu_mail + lr $0,@CMBL + call wait_for_cpu_mail + lrs $24,@CMBL + andi $31,#0x0fff + mrr $26,$31 + call wait_for_cpu_mail + lrs $25,@CMBL + call wait_for_cpu_mail + lrs $27,@CMBL + sbclr #0x05 + sbclr #0x06 + jmp 0x80b5 + halt + +/**************************************************************************************************************************************/ +// send the samples for the internal buffer to the external buffer + +send_samples: + + lri $AR0, #MEM_SND + lris $AXL1, #DMA_TO_CPU; + lri $AXL0, #NUM_SAMPLES*4 ; len + lr $ACM0, @ADDRH_SND + lr $ACL0, @ADDRL_SND + + call do_dma + si @DMBL, #0x0004 + si @DIRQ, #0x1 // set the interrupt + jmp recv_cmd + +/**************************************************************************************************************************************/ +// get the address of the voice datas buffer (CHANNEL DATAS) + +get_data_addr: + call wait_for_cpu_mail + + lrs $ACM0, @CMBH + lr $ACL0, @CMBL + + sr @MEM_VECTH, $ACM0 + sr @MEM_VECTL, $ACL0 + + si @DIRQ, #0x0 // clear the interrupt + jmp recv_cmd + +/**************************************************************************************************************************************/ +// fill the internal sample buffer and process the voice internally + +input_samples: + + clr $ACC0 + lr $ACM0, @MEM_VECTH + lr $ACL0, @MEM_VECTL + + lris $AXL0, #0x0004 + sr @RETURN, $AXL0 + si @DIRQ, #0x0000 + + // program DMA to get datas + + lri $AR0, #MEM_REG + lris $AXL1, #DMA_TO_DSP + lris $AXL0, #64 ; len + + call do_dma + + lri $AR1, #MEM_SND + lri $ACL1, #0; + + lri $AXL0, #NUM_SAMPLES + bloop $AXL0, loop_get1 + + srri @$AR1, $ACL1 + srri @$AR1, $ACL1 + +loop_get1: + nop + + lr $ACM0, @ADDRH_SND + lr $ACL0, @ADDRL_SND + jmp start_main + +/**************************************************************************************************************************************/ +// get samples from the external buffer to the internal buffer and process the voice mixing the samples internally + +input_samples2: + + clr $ACC0 + lr $ACM0, @MEM_VECTH + lr $ACL0, @MEM_VECTL + + lris $AXL0, #0x0004 + sr @RETURN, $AXL0 + si @DIRQ, #0x0000 + + // program DMA to get datas + + lri $AR0, #MEM_REG + lri $AXL1, #DMA_TO_DSP + lris $AXL0, #64 ; len + + call do_dma + + lr $ACM0, @ADDRH_SND + lr $ACL0, @ADDRL_SND + + lri $AR0, #MEM_SND + lris $AXL1, #DMA_TO_DSP; + lri $AXL0, #NUM_SAMPLES*4; len + + call do_dma + + jmp start_main + +/**************************************************************************************************************************************/ +// process the voice mixing the samples internally + +input_next_samples: + + clr $ACC0 + lr $ACM0, @MEM_VECTH + lr $ACL0, @MEM_VECTL + + lris $AXL0, #0x0004 + sr @RETURN, $AXL0 + si @DIRQ, #0x0000 + + // program DMA to get datas + + lri $AR0, #MEM_REG + lris $AXL1, #DMA_TO_DSP + lris $AXL0, #64 ; len + + call do_dma + +/**************************************************************************************************************************************/ +// mixing and control pitch to create 1024 Stereo Samples at 16 bits from here + +start_main: + + lri $R08, #48000 + + // load the previous samples used + + lr $AXH0, @SMP_R + lr $AXH1, @SMP_L + +// optimize the jump function to get MONO/STEREO 8/16 bits samples + + lr $ACM1, @FLAGSL_SMP + andi $ACM1, #0x3 + addi $ACM1, #sample_selector + mrr $AR3, $ACM1 + ilrr $ACM1, @$AR3 + mrr $AR3, $ACM1 // AR3 countain the jump loaded from sample selector + + clr $ACC0 + +// test for channel paused + + lr $ACM0, @FLAGSL_SMP + andcf $ACM0, #0x20 + jlz end_main + +// load the sample address + + lr $ACM0, @ADDRH_SMP + lr $ACL0, @ADDRL_SMP + +// test if ADDR_SMP & ADDR2H_SMP are zero + + tst $ACC0 + jnz do_not_change1 + +// set return as "change of buffer" + + lris $AXL0, #0x0004 + sr @RETURN, $AXL0 + +// change to buffer 2 if it is possible + + call change_buffer + +// stops if again 0 address + + tst $ACC0 + jz save_datas_end + +do_not_change1: + + +// backup the external sample address + + mrr $IX2, $ACM0 + mrr $IX3, $ACL0 + + +// load the counter pitch + + //lr $r08, @COUNTERH_SMP + //lr $r09, @COUNTERL_SMP + +// load the end address of the samples + + lr $r0a, @ADDREH_SMP + lr $r0b, @ADDREL_SMP + +// load AR1 with internal buffer address + + lri $AR1, #MEM_SND + +///////////////////////////////////// +// delay time section +///////////////////////////////////// + +// load AXL0 with the samples to be processed + + lri $AXL0, #NUM_SAMPLES + +// test if DELAY == 0 and skip or not + + clr $ACC0 + clr $ACC1 + lr $ACH0, @DELAYH_SND + lr $ACM0, @DELAYL_SND + tst $ACC0 + jz no_delay + +// samples left and right to 0 + + lris $AXH0, #0 + lris $AXH1, #0 + +// load the samples to be processed in ACM1 + + mrr $ACM1, $AXL0 +l_delay: + iar $AR1 // skip two samples + iar $AR1 + decm $ACM1 + jz exit_delay1 // exit1 if samples to be processed == 0 + + decm $ACM0 + jz exit_delay2 // exit2 if delay time == 0 + jmp l_delay + +// store the remanent delay and ends + +exit_delay1: + decm $ACM0 + + sr @DELAYH_SND, $ACH0 + sr @DELAYL_SND, $ACM0 + + lris $AXL0,#0 ; exit from loop + + jmp no_delay + + +exit_delay2: + + // store delay=0 and continue + + sr @DELAYH_SND, $ACH0 + sr @DELAYL_SND, $ACM0 + mrr $AXL0, $ACL1 // load remanent samples to be processed in AXL0 + +no_delay: + +///////////////////////////////////// +// end of delay time section +///////////////////////////////////// +)" // Work around C2026 on MSVC, which allows at most 16380 single-byte characters in a single + // non-concatenated string literal (but you can concatenate multiple shorter string literals to + // produce a longer string just fine). (This comment is not part of the actual test program, + // and instead there is a single blank line at this location.) + R"( +/* bucle de generacion de samples */ + + +// load the sample buffer with address aligned to 32 bytes blocks (first time) + + si @DSCR, #DMA_TO_DSP // very important!: load_smp_addr_align and jump_load_smp_addr need fix this DMA Register (I gain some cycles so) + +// load_smp_addr_align input: $IX2:$IX3 + + call load_smp_addr_align + +// load the volume registers + + lr $IX0, @LEFT_VOLUME + lr $IX1, @RIGHT_VOLUME + +// test the freq value + + clr $ACL0 + lr $ACH0, @FREQH_SMP + lr $ACM0, @FREQL_SMP + + clr $ACC1 + ;lri $ACM1,#48000 + mrr $ACM1, $R08 + cmp + +// select the output of the routine to process stereo-mono 8/16bits samples + + lri $AR0, #get_sample // fast method <=48000 + +// if number is greater freq>48000 fix different routine + + ifg + lri $AR0, #get_sample2 // slow method >48000 + +// loops for samples to be processed + + bloop $AXL0, loop_end + + //srri @$AR1, $AXH0 // put sample R + //srri @$AR1, $AXH1 // put sample L + +// Mix right sample section + + lrr $ACL0, @$AR1 // load in ACL0 the right sample from the internal buffer + movax $ACC1, $AXL1 // big trick :) load the current sample <<16 and sign extended + + asl $ACC0,#24 // convert sample from buffer to 24 bit number with sign extended (ACH0:ACM0) + asr $ACC0,#-8 + + add $ACC0,$ACC1 // current_sample+buffer sample + + cmpi $ACM0,#32767 // limit to 32767 + jle right_skip + + lri $ACM0, #32767 + jmp right_skip2 + +right_skip: + + cmpi $ACM0,#-32768 // limit to -32768 + ifle + lri $ACM0, #-32768 + +right_skip2: + + srri @$AR1, $ACM0 // store the right sample mixed to the internal buffer and increment AR1 + +// Mix left sample section + + lrr $ACL0, @$AR1 // load in ACL0 the left sample from the internal buffer + + movax $ACC1, $AXL0 // big trick :) load the current sample <<16 and sign extended + + asl $ACC0, #24 // convert sample from buffer to 24 bit number with sign extended (ACH0:ACM0) + asr $ACC0, #-8 + + add $ACC0, $ACC1 // current_sample+buffer sample + + cmpi $ACM0,#32767 // limit to 32767 + jle left_skip + + lri $ACM0, #32767 + jmp left_skip2 + +left_skip: + + cmpi $ACM0,#-32768 // limit to -32768 + ifle + lri $ACM0, #-32768 + +left_skip2: + + srri @$AR1, $ACM0 // store the left sample mixed to the internal buffer and increment AR1 + +// adds the counter with the voice frequency and test if it >=48000 to get the next sample + + clr $ACL1 + lr $ACH1, @COUNTERH_SMP + lr $ACM1, @COUNTERL_SMP + clr $ACL0 + lr $ACH0, @FREQH_SMP + lr $ACM0, @FREQL_SMP + + add $ACC1,$ACC0 + clr $ACC0 + //lri $ACM0,#48000 + mrr $ACM0, $R08 + + cmp + + jrnc $AR0 //get_sample or get_sample2 method + + sr @COUNTERH_SMP, $ACH1 + sr @COUNTERL_SMP, $ACM1 + + jmp loop_end + +// get a new sample for freq > 48000 Hz + +get_sample2: // slow method + + sub $ACC1,$ACC0 // restore the counter + +// restore the external sample buffer address + + clr $ACC0 + mrr $ACM0, $IX2 // load ADDRH_SMP + mrr $ACL0, $IX3 // load ADDRL_SMP + + lr $AXL1, @FLAGSH_SMP // add the step to get the next samples + addaxl $ACC0, $AXL1 + + mrr $IX2, $ACM0 // store ADDRH_SMP + mrr $IX3, $ACL0 // store ADDRL_SMP + + mrr $ACM0, $ACL0 + andf $ACM0, #0x1f + +// load_smp_addr_align input: $IX2:$IX3 call if (ACM0 & 0x1f)==0 + + calllz load_smp_addr_align + + clr $ACC0 + //lri $ACM0,#48000 + mrr $ACM0, $R08 + + cmp + + jle get_sample2 + + sr @COUNTERH_SMP, $ACH1 + sr @COUNTERL_SMP, $ACM1 + + mrr $ACM0, $IX2 // load ADDRH_SMP + mrr $ACL0, $IX3 // load ADDRL_SMP + + clr $ACC1 + mrr $ACM1, $r0a // load ADDREH_SMP + mrr $ACL1, $r0b // load ADDREL_SMP + +// compares if the current address is >= end address to change the buffer or stops + + cmp + +// if addr>addr end get a new buffer (if you uses double buffer) + + jc get_new_buffer + +// load samples from dma, return $ar2 with the addr to get the samples and return using $ar0 to the routine to process 8-16bits Mono/Stereo + + jmp jump_load_smp_addr + +// get a new sample for freq <= 48000 Hz + +get_sample: // fast method + + sub $ACC1,$ACC0 // restore the counter + sr @COUNTERH_SMP, $ACH1 + sr @COUNTERL_SMP, $ACM1 + +// restore the external sample buffer address + + clr $ACC0 + mrr $ACM0, $IX2 // load ADDRH_SMP + mrr $ACL0, $IX3 // load ADDRL_SMP + + lr $AXL1, @FLAGSH_SMP // add the step to get the next samples + addaxl $ACC0, $AXL1 + + clr $ACC1 + mrr $ACM1, $r0a // load ADDREH_SMP + mrr $ACL1, $r0b // load ADDREL_SMP + +// compares if the current address is >= end address to change the buffer or stops + + cmp + jc get_new_buffer + +// load the new sample from the buffer + + mrr $IX2, $ACM0 // store ADDRH_SMP + mrr $IX3, $ACL0 // store ADDRL_SMP + +// load samples from dma, return $ar2 with the addr and return using $ar0 to the routine to process 8-16bits Mono/Stereo or addr_get_sample_again + + jmp jump_load_smp_addr + +sample_selector: + cw mono_8bits + cw mono_16bits + cw stereo_8bits + cw stereo_16bits + +get_new_buffer: + +// set return as "change of buffer": it need to change the sample address + + lris $AXL0, #0x0004 + sr @RETURN, $AXL0 + + call change_buffer // load add from addr2 + +// addr is 0 ? go to zero_samples and exit + + tst $acc0 + jz zero_samples + +// load_smp_addr_align input: $IX2:$IX3 + + call load_smp_addr_align // force the load the samples cached (address aligned) + +// jump_load_smp_addr: $IX2:$IX3 +// load samples from dma, return $ar2 with the addr to get the samples and return using $ar0 to the routine to process 8-16bits Mono/Stereo + + jmp jump_load_smp_addr + +// set to 0 the current samples + +zero_samples: + + lris $AXH0, #0 + lris $AXH1, #0 + jmp out_samp + +mono_8bits: + +// 8 bits mono + mrr $ACM1, $IX3 + lrri $ACL0, @$AR2 + andf $ACM1, #0x1 + + iflz // obtain sample0-sample1 from 8bits packet + asr $ACL0, #-8 + asl $ACL0, #8 + + mrr $AXH1,$ACL0 + mrr $AXH0,$ACL0 + jmp out_samp + +stereo_8bits: + +// 8 bits stereo + + lrri $ACL0, @$AR2 + mrr $ACM0, $ACL0 + andi $ACM0, #0xff00 + mrr $AXH1, $ACM0 + lsl $ACL0, #8 + mrr $AXH0, $ACL0 + + jmp out_samp + +mono_16bits: + +// 16 bits mono + + lrri $AXH1, @$AR2 + mrr $AXH0,$AXH1 + jmp out_samp + +stereo_16bits: + +// 16 bits stereo + + lrri $AXH1, @$AR2 + lrri $AXH0, @$AR2 + +out_samp: + +// multiply sample x volume + + // LEFT_VOLUME + mrr $AXL0,$IX0 + mul $AXL0,$AXH0 + movp $ACL0 + asr $ACL0,#-8 + mrr $AXH0, $ACL0 + + // RIGHT VOLUME + mrr $AXL1,$IX1 + mul $AXL1,$AXH1 + movp $ACL0 + asr $ACL0,#-8 + mrr $AXH1, $ACL0 + +loop_end: + nop + +end_process: + + // load the sample address + + clr $ACC0 + mrr $ACM0, $IX2 + mrr $ACL0, $IX3 + + tst $ACC0 + jnz save_datas_end + +// set return as "change of buffer" + + lris $AXL0, #0x0004 + sr @RETURN, $AXL0 + +// change to buffer 2 if it is possible + + call change_buffer + +save_datas_end: + + sr @ADDRH_SMP, $IX2 + sr @ADDRL_SMP, $IX3 + sr @SMP_R, $AXH0 + sr @SMP_L, $AXH1 + +end_main: + +// program DMA to send the CHANNEL DATAS changed + + clr $ACC0 + lr $ACM0, @MEM_VECTH + lr $ACL0, @MEM_VECTL + + lri $AR0, #MEM_REG + lris $AXL1, #DMA_TO_CPU + lris $AXL0, #64 ; len + + call do_dma + + si @DMBH, #0xdcd1 + lr $ACL0, @RETURN + + sr @DMBL, $ACL0 + si @DIRQ, #0x1 // set the interrupt + + jmp recv_cmd + +change_buffer: + + clr $ACC0 + lr $ACM0, @LEFT_VOLUME2 + lr $ACL0, @RIGHT_VOLUME2 + sr @LEFT_VOLUME, $ACM0 + sr @RIGHT_VOLUME, $ACL0 + mrr $IX0, $ACM0 + mrr $IX1, $ACL0 + + lr $ACM0, @ADDR2EH_SMP + lr $ACL0, @ADDR2EL_SMP + sr @ADDREH_SMP, $ACM0 + sr @ADDREL_SMP, $ACL0 + mrr $r0a, $ACM0 + mrr $r0b, $ACL0 + + lr $ACM0, @ADDR2H_SMP + lr $ACL0, @ADDR2L_SMP + sr @ADDRH_SMP, $ACM0 + sr @ADDRL_SMP, $ACL0 + sr @BACKUPH_SMP, $ACM0 + sr @BACKUPL_SMP, $ACL0 + mrr $IX2, $ACM0 + mrr $IX3, $ACL0 + + lr $ACM1, @FLAGSL_SMP + andcf $ACM1, #0x4 + retlz + + sr @ADDR2H_SMP, $ACH0 + sr @ADDR2L_SMP, $ACH0 + sr @ADDR2EH_SMP, $ACH0 + sr @ADDR2EL_SMP, $ACH0 + ret + +/**************************************************************/ +/* DMA ROUTINE */ +/**************************************************************/ + +do_dma: + + sr @DSMAH, $ACM0 + sr @DSMAL, $ACL0 + sr @DSPA, $AR0 + sr @DSCR, $AXL1 + sr @DSBL, $AXL0 + +wait_dma: + + lrs $ACM1, @DSCR + andcf $ACM1, #0x4 + jlz wait_dma + ret + + +wait_for_dsp_mail: + + lrs $ACM1, @DMBH + andcf $ACM1, #0x8000 + jlz wait_for_dsp_mail + ret + +wait_for_cpu_mail: + + lrs $ACM1, @cmbh + andcf $ACM1, #0x8000 + jlnz wait_for_cpu_mail + ret + +load_smp_addr_align: + + mrr $ACL0, $IX3 // load ADDRL_SMP + + lsr $ACC0, #-5 + lsl $ACC0, #5 + sr @DSMAH, $IX2 + sr @DSMAL, $ACL0 + si @DSPA, #MEM_SAMP + ;si @DSCR, #DMA_TO_DSP + si @DSBL, #0x20 + +wait_dma1: + lrs $ACM0, @DSCR + andcf $ACM0, #0x4 + jlz wait_dma1 + + lri $AR2, #MEM_SAMP + ret + + +////////////////////////////////////////// + +jump_load_smp_addr: + + mrr $ACM0, $IX3 // load ADDRL_SMP + asr $ACC0, #-1 + andi $ACM0, #0xf + jz jump_load_smp_dma + + addi $ACM0, #MEM_SAMP + mrr $AR2, $ACM0 + jmpr $AR3 + +jump_load_smp_dma: + + sr @DSMAH, $IX2 + sr @DSMAL, $IX3 + si @DSPA, #MEM_SAMP + ;si @DSCR, #DMA_TO_DSP // to gain some cycles + si @DSBL, #0x20 + +wait_dma2: + lrs $ACM0, @DSCR + andcf $ACM0, #0x4 + jlz wait_dma2 + + lri $AR2, #MEM_SAMP + jmpr $AR3 + +// exception table + +exception0: // RESET + rti + +exception1: // STACK OVERFLOW + rti + +exception2: + rti + +exception3: + rti + +exception4: + rti + +exception5: // ACCELERATOR ADDRESS OVERFLOW + rti + +exception6: + rti + +exception7: + rti + +// routine to read a word of the IROM space + +rom_dump_word: + + clr $ACC0 + + lr $ACM0, @CMBH + ori $ACM0, #0x8000 + mrr $AR0, $ACM0 + clr $ACC0 + ilrr $ACM0, @$AR0 + sr @DMBH, $ACL0 + sr @DMBL, $ACM0 + ;si @DIRQ, #0x1 // set the interrupt + clr $ACC0 + jmp recv_cmd + +polla_loca: + + clr $ACC0 + lri $acm0, #0x0 + andf $acm0,#0x1 + + sr @DMBH, $sr + sr @DMBL, $acm0 + ;si @DIRQ, #0x1 // set the interrupt + clr $ACC0 + jmp recv_cmd + +)"; |
