1
0
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:
Till Harbaum
2016-01-14 13:57:54 +01:00
parent 288104fc11
commit ac0eca2f1a
6 changed files with 179 additions and 54 deletions

View File

@@ -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)

View File

@@ -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);

View File

@@ -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.

View File

@@ -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.