mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-02-05 07:34:41 +00:00
[TUTORIAL] Lesson 8 small audio fixes
This commit is contained in:
@@ -14,7 +14,7 @@ font.part: font.fnt
|
||||
dd if=$< of=$@ bs=1 count=768 skip=256
|
||||
|
||||
font.c: font.part bin2c
|
||||
./bin2c font.part font.c "unsigned char font[]"
|
||||
./bin2c font.part font.c "const unsigned char font[]"
|
||||
|
||||
irqvec.rel: irqvec.s
|
||||
sdasz80 -o $@ $<
|
||||
@@ -59,5 +59,12 @@ run: $(ROM)
|
||||
sx $< <$(TTY) >$(TTY)
|
||||
echo "r" > $(TTY)
|
||||
|
||||
core_update:
|
||||
stty -F $(TTY) speed 115200 raw -echo
|
||||
timeout 1s cp $(TTY) /dev/null || /bin/true
|
||||
echo "x core.rbf `stat -c%s soc.rbf`" > $(TTY)
|
||||
sx soc.rbf <$(TTY) >$(TTY)
|
||||
echo "r" > $(TTY)
|
||||
|
||||
reset:
|
||||
echo "r" > $(TTY)
|
||||
|
||||
@@ -22,24 +22,40 @@ __sfr __at 0x11 PsgDataPort;
|
||||
|
||||
// YM replay is happening in the interrupt
|
||||
void isr(void) __interrupt {
|
||||
BYTE i;
|
||||
BYTE i, *p;
|
||||
|
||||
if(frames) {
|
||||
frames--;
|
||||
|
||||
// write all 16 psg registers
|
||||
for(i=0;i<16;i++) {
|
||||
PsgAddrPort = i;
|
||||
PsgDataPort = ym_buffer[rsec][rptr++];
|
||||
// write all 14 psg sound registers
|
||||
p = ym_buffer[rsec] + rptr;
|
||||
|
||||
// one whole sector processed?
|
||||
if(rptr == 512) {
|
||||
rsec++;
|
||||
rptr=0;
|
||||
|
||||
if(rsec == BUFFERS)
|
||||
rsec = 0;
|
||||
}
|
||||
// unrolled loop for min delay between register writes
|
||||
PsgAddrPort = 0; PsgDataPort = *p++;
|
||||
PsgAddrPort = 1; PsgDataPort = *p++;
|
||||
PsgAddrPort = 2; PsgDataPort = *p++;
|
||||
PsgAddrPort = 3; PsgDataPort = *p++;
|
||||
PsgAddrPort = 4; PsgDataPort = *p++;
|
||||
PsgAddrPort = 5; PsgDataPort = *p++;
|
||||
PsgAddrPort = 6; PsgDataPort = *p++;
|
||||
PsgAddrPort = 7; PsgDataPort = *p++;
|
||||
PsgAddrPort = 8; PsgDataPort = *p++;
|
||||
PsgAddrPort = 9; PsgDataPort = *p++;
|
||||
PsgAddrPort = 10; PsgDataPort = *p++;
|
||||
PsgAddrPort = 11; PsgDataPort = *p++;
|
||||
PsgAddrPort = 12; PsgDataPort = *p++;
|
||||
PsgAddrPort = 13;
|
||||
if(*p != 255) PsgDataPort = *p++;
|
||||
|
||||
rptr += 16;
|
||||
|
||||
// one whole sector processed?
|
||||
if(rptr == 512) {
|
||||
rsec++;
|
||||
rptr=0;
|
||||
|
||||
if(rsec == BUFFERS)
|
||||
rsec = 0;
|
||||
}
|
||||
} else {
|
||||
// not playing? mute all channels
|
||||
@@ -127,7 +143,7 @@ void main() {
|
||||
FATFS fatfs; /* File system object */
|
||||
FRESULT rc;
|
||||
UINT bytes_read;
|
||||
BYTE wsec = 0;
|
||||
BYTE i, wsec = 0;
|
||||
|
||||
ei();
|
||||
cls();
|
||||
@@ -136,6 +152,12 @@ void main() {
|
||||
|
||||
printf("Mounting SD card...\n");
|
||||
|
||||
// not playing? mute all channels
|
||||
for(i=0;i<16;i++) {
|
||||
PsgAddrPort = i;
|
||||
PsgDataPort = 0;
|
||||
}
|
||||
|
||||
rc = pf_mount(&fatfs);
|
||||
if (rc) die(rc);
|
||||
|
||||
|
||||
@@ -1,32 +1,129 @@
|
||||
module sigma_delta_dac(
|
||||
output reg DACout, //Average Output feeding analog lowpass
|
||||
input [MSBI:0] DACin, //DAC input (excess 2**MSBI)
|
||||
input CLK,
|
||||
input RESET
|
||||
// sigmadelta.v
|
||||
// two channel second order sigma delta dac
|
||||
// taken from Minimig
|
||||
|
||||
// audio data processing
|
||||
// stereo sigma/delta bitstream modulator
|
||||
module sigma_delta_dac (
|
||||
input clk, // bus clock
|
||||
input [14:0] ldatasum, // left channel data
|
||||
input [14:0] rdatasum, // right channel data
|
||||
output reg left=0, // left bitstream output
|
||||
output reg right=0 // right bitsteam output
|
||||
);
|
||||
|
||||
parameter MSBI = 7;
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
reg [MSBI+2:0] DeltaAdder; //Output of Delta Adder
|
||||
reg [MSBI+2:0] SigmaAdder; //Output of Sigma Adder
|
||||
reg [MSBI+2:0] SigmaLatch; //Latches output of Sigma Adder
|
||||
reg [MSBI+2:0] DeltaB; //B input of Delta Adder
|
||||
// local signals
|
||||
localparam DW = 15;
|
||||
localparam CW = 2;
|
||||
localparam RW = 4;
|
||||
localparam A1W = 2;
|
||||
localparam A2W = 5;
|
||||
|
||||
always @ (*)
|
||||
DeltaB = {SigmaLatch[MSBI+2], SigmaLatch[MSBI+2]} << (MSBI+1);
|
||||
wire [DW+2+0 -1:0] sd_l_er0, sd_r_er0;
|
||||
reg [DW+2+0 -1:0] sd_l_er0_prev=0, sd_r_er0_prev=0;
|
||||
wire [DW+A1W+2-1:0] sd_l_aca1, sd_r_aca1;
|
||||
wire [DW+A2W+2-1:0] sd_l_aca2, sd_r_aca2;
|
||||
reg [DW+A1W+2-1:0] sd_l_ac1=0, sd_r_ac1=0;
|
||||
reg [DW+A2W+2-1:0] sd_l_ac2=0, sd_r_ac2=0;
|
||||
wire [DW+A2W+3-1:0] sd_l_quant, sd_r_quant;
|
||||
|
||||
always @(*)
|
||||
DeltaAdder = DACin + DeltaB;
|
||||
|
||||
always @(*)
|
||||
SigmaAdder = DeltaAdder + SigmaLatch;
|
||||
|
||||
always @(posedge CLK or posedge RESET)
|
||||
if(RESET) begin
|
||||
SigmaLatch <= 1'b1 << (MSBI+1);
|
||||
DACout <= 1'b0;
|
||||
end else begin
|
||||
SigmaLatch <= SigmaAdder;
|
||||
DACout <= SigmaLatch[MSBI+2];
|
||||
end
|
||||
endmodule
|
||||
// LPF noise LFSR
|
||||
reg [24-1:0] seed1 = 24'h654321;
|
||||
reg [19-1:0] seed2 = 19'h12345;
|
||||
reg [24-1:0] seed_sum=0, seed_prev=0, seed_out=0;
|
||||
always @ (posedge clk) begin
|
||||
if (&seed1)
|
||||
seed1 <= #1 24'h654321;
|
||||
else
|
||||
seed1 <= #1 {seed1[22:0], ~(seed1[23] ^ seed1[22] ^ seed1[21] ^ seed1[16])};
|
||||
end
|
||||
always @ (posedge clk) begin
|
||||
if (&seed2)
|
||||
seed2 <= #1 19'h12345;
|
||||
else
|
||||
seed2 <= #1 {seed2[17:0], ~(seed2[18] ^ seed2[17] ^ seed2[16] ^ seed2[13] ^ seed2[0])};
|
||||
end
|
||||
always @ (posedge clk) begin
|
||||
seed_sum <= #1 seed1 + {5'b0, seed2};
|
||||
seed_prev <= #1 seed_sum;
|
||||
seed_out <= #1 seed_sum - seed_prev;
|
||||
end
|
||||
|
||||
// linear interpolate
|
||||
localparam ID=4; // counter size, also 2^ID = interpolation rate
|
||||
reg [ID+0-1:0] int_cnt = 0;
|
||||
always @ (posedge clk) int_cnt <= #1 int_cnt + 'd1;
|
||||
|
||||
reg [DW+0-1:0] ldata_cur=0, ldata_prev=0;
|
||||
reg [DW+0-1:0] rdata_cur=0, rdata_prev=0;
|
||||
wire [DW+1-1:0] ldata_step, rdata_step;
|
||||
reg [DW+ID-1:0] ldata_int=0, rdata_int=0;
|
||||
wire [DW+0-1:0] ldata_int_out, rdata_int_out;
|
||||
assign ldata_step = {ldata_cur[DW-1], ldata_cur} - {ldata_prev[DW-1], ldata_prev}; // signed subtract
|
||||
assign rdata_step = {rdata_cur[DW-1], rdata_cur} - {rdata_prev[DW-1], rdata_prev}; // signed subtract
|
||||
always @ (posedge clk) begin
|
||||
if (~|int_cnt) begin
|
||||
ldata_prev <= #1 ldata_cur;
|
||||
ldata_cur <= #1 ldatasum; //{~ldatasum[DW-1], ldatasum[DW-2:0]}; // convert to offset binary, samples no longer signed!
|
||||
rdata_prev <= #1 rdata_cur;
|
||||
rdata_cur <= #1 rdatasum; //{~rdatasum[DW-1], rdatasum[DW-2:0]}; // convert to offset binary, samples no longer signed!
|
||||
ldata_int <= #1 {ldata_cur[DW-1], ldata_cur, {ID{1'b0}}};
|
||||
rdata_int <= #1 {rdata_cur[DW-1], rdata_cur, {ID{1'b0}}};
|
||||
end else begin
|
||||
ldata_int <= #1 ldata_int + {{ID{ldata_step[DW+1-1]}}, ldata_step};
|
||||
rdata_int <= #1 rdata_int + {{ID{rdata_step[DW+1-1]}}, rdata_step};
|
||||
end
|
||||
end
|
||||
assign ldata_int_out = ldata_int[DW+ID-1:ID];
|
||||
assign rdata_int_out = rdata_int[DW+ID-1:ID];
|
||||
|
||||
// input gain x3
|
||||
wire [DW+2-1:0] ldata_gain, rdata_gain;
|
||||
assign ldata_gain = {ldata_int_out[DW-1], ldata_int_out, 1'b0} + {{(2){ldata_int_out[DW-1]}}, ldata_int_out};
|
||||
assign rdata_gain = {rdata_int_out[DW-1], rdata_int_out, 1'b0} + {{(2){rdata_int_out[DW-1]}}, rdata_int_out};
|
||||
|
||||
/*
|
||||
// random dither to 15 bits
|
||||
reg [DW-1:0] ldata=0, rdata=0;
|
||||
always @ (posedge clk) begin
|
||||
ldata <= #1 ldata_gain[DW+2-1:2] + ( (~(&ldata_gain[DW+2-1-1:2]) && (ldata_gain[1:0] > seed_out[1:0])) ? 15'd1 : 15'd0 );
|
||||
rdata <= #1 rdata_gain[DW+2-1:2] + ( (~(&ldata_gain[DW+2-1-1:2]) && (ldata_gain[1:0] > seed_out[1:0])) ? 15'd1 : 15'd0 );
|
||||
end
|
||||
*/
|
||||
|
||||
// accumulator adders
|
||||
assign sd_l_aca1 = {{(A1W){ldata_gain[DW+2-1]}}, ldata_gain} - {{(A1W){sd_l_er0[DW+2-1]}}, sd_l_er0} + sd_l_ac1;
|
||||
assign sd_r_aca1 = {{(A1W){rdata_gain[DW+2-1]}}, rdata_gain} - {{(A1W){sd_r_er0[DW+2-1]}}, sd_r_er0} + sd_r_ac1;
|
||||
|
||||
assign sd_l_aca2 = {{(A2W-A1W){sd_l_aca1[DW+A1W+2-1]}}, sd_l_aca1} - {{(A2W){sd_l_er0[DW+2-1]}}, sd_l_er0} - {{(A2W+1){sd_l_er0_prev[DW+2-1]}}, sd_l_er0_prev[DW+2-1:1]} + sd_l_ac2;
|
||||
assign sd_r_aca2 = {{(A2W-A1W){sd_r_aca1[DW+A1W+2-1]}}, sd_r_aca1} - {{(A2W){sd_r_er0[DW+2-1]}}, sd_r_er0} - {{(A2W+1){sd_r_er0_prev[DW+2-1]}}, sd_r_er0_prev[DW+2-1:1]} + sd_r_ac2;
|
||||
|
||||
// accumulators
|
||||
always @ (posedge clk) begin
|
||||
sd_l_ac1 <= #1 sd_l_aca1;
|
||||
sd_r_ac1 <= #1 sd_r_aca1;
|
||||
sd_l_ac2 <= #1 sd_l_aca2;
|
||||
sd_r_ac2 <= #1 sd_r_aca2;
|
||||
end
|
||||
|
||||
// value for quantizaton
|
||||
assign sd_l_quant = {sd_l_ac2[DW+A2W+2-1], sd_l_ac2} + {{(DW+A2W+3-RW){seed_out[RW-1]}}, seed_out[RW-1:0]};
|
||||
assign sd_r_quant = {sd_r_ac2[DW+A2W+2-1], sd_r_ac2} + {{(DW+A2W+3-RW){seed_out[RW-1]}}, seed_out[RW-1:0]};
|
||||
|
||||
// error feedback
|
||||
assign sd_l_er0 = sd_l_quant[DW+A2W+3-1] ? {1'b1, {(DW+2-1){1'b0}}} : {1'b0, {(DW+2-1){1'b1}}};
|
||||
assign sd_r_er0 = sd_r_quant[DW+A2W+3-1] ? {1'b1, {(DW+2-1){1'b0}}} : {1'b0, {(DW+2-1){1'b1}}};
|
||||
always @ (posedge clk) begin
|
||||
sd_l_er0_prev <= #1 (&sd_l_er0) ? sd_l_er0 : sd_l_er0+1;
|
||||
sd_r_er0_prev <= #1 (&sd_r_er0) ? sd_r_er0 : sd_r_er0+1;
|
||||
end
|
||||
|
||||
// output
|
||||
always @ (posedge clk) begin
|
||||
left <= #1 (~|ldata_gain) ? ~left : ~sd_l_er0[DW+2-1];
|
||||
right <= #1 (~|rdata_gain) ? ~right : ~sd_r_er0[DW+2-1];
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
Binary file not shown.
@@ -260,15 +260,15 @@ spi spi (
|
||||
// Audio replay is supposed to run at 50Hz. Vsync is 60 Hz, so
|
||||
// we generate.
|
||||
reg clk50hz;
|
||||
reg [16:0] count_50hz;
|
||||
reg [15:0] count_50hz;
|
||||
always @(posedge cpu_clock) begin
|
||||
if(cpu_reset)
|
||||
count_50hz <= 17'd0;
|
||||
count_50hz <= 16'd0;
|
||||
else begin
|
||||
if(count_50hz < 16'd159999)
|
||||
count_50hz <= count_50hz + 17'd1;
|
||||
if(count_50hz < 16'd39999)
|
||||
count_50hz <= count_50hz + 16'd1;
|
||||
else begin
|
||||
count_50hz <= 17'd0;
|
||||
count_50hz <= 16'd0;
|
||||
clk50hz <= !clk50hz;
|
||||
end
|
||||
end
|
||||
@@ -343,15 +343,14 @@ YM2149 ym2149 (
|
||||
.CLK8 ( cpu_clock ) // 4 MHz CPU bus clock
|
||||
);
|
||||
|
||||
assign AUDIO_L = audio_out;
|
||||
assign AUDIO_R = audio_out;
|
||||
wire audio_out;
|
||||
wire [14:0] audio_data = { psg_audio_out, 7'h00 } - 15'h4000;
|
||||
|
||||
sigma_delta_dac sigma_delta_dac (
|
||||
.DACout ( audio_out ),
|
||||
.DACin ( psg_audio_out ),
|
||||
.CLK ( ram_clock ),
|
||||
.RESET ( cpu_reset )
|
||||
.clk ( ram_clock ),
|
||||
.left ( AUDIO_L ),
|
||||
.right ( AUDIO_R ),
|
||||
.ldatasum ( audio_data ),
|
||||
.rdatasum ( audio_data )
|
||||
);
|
||||
|
||||
// divide 32Mhz sdram clock down to 2MHz
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user