diff --git a/doc/irqctrl.md b/doc/irqctrl.md
index bf76999..580c123 100644
--- a/doc/irqctrl.md
+++ b/doc/irqctrl.md
@@ -9,13 +9,12 @@ The interrupt controller uses a single register at address: $980
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
-|_Value_|t |t |t |t |t |t |t |t |- |- |- |- |- |p2 |p1 |p0 |
+|_Value_|t |t |t |t |t |t |t |t |- |- |- |- |- |- |p1 |p0 |
|Bitfields|Description|
|---------|-----------|
| _t_ | unsigned 24 bit counter of timer ticks since reset
-| _p2_ | IRQ 2 (audio) interrupt pending if 1
| _p1_ | IRQ 1 (timer tick) interrupt pending if 1
| _p0_ | IRQ 0 (UART) interrupt pending if 1
diff --git a/doc/tdraudio.md b/doc/tdraudio.md
deleted file mode 100644
index 999ebfc..0000000
--- a/doc/tdraudio.md
+++ /dev/null
@@ -1,104 +0,0 @@
-# Audio Controller
-The audio controller provides four channels of 16-bit PCM audio playback.
-
-It uses multiple registers starting at address $A00.
-
-Each of the four channels has three registers.
-
-For the first channel the register addresses are:
-
-|Address|Description|
-|-------|-----------|
-| $A00 | Control Register |
-| $A01 | Clock Divider Register |
-| $A02 | Amplitude Register |
-
-The register addresses for the second channel start at $A04,
-the third channel at $A08
-and the fourth channel at $A0C.
-
-## Reading the control register
-
-|_bit_ |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
-|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
-|_Value_|- |- |- |- |- |- |- |- |- |-|- |- |- |- |- |- |
-
-|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
-|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
-|_Value_|- |- |- |- |- |- |- |- |- |- |- |i |f | e | p | c |
-
-
-|Bitfields|Description|
-|---------|-----------|
-| _i_ | interrupt is enabled for this channel when 1 |
-| _f_ | sample buffer is full when 1 |
-| _e_ | sample buffer is empty when 1 |
-| _p_ | changes from 0 to 1 and vice versa on each sample clock |
-| _c_ | channel is enabled if 1 |
-
-## Writing the control register
-
-|_bit_ |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
-|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
-|_Value_|- |- |- |- |- |- |- |- |- |-|- |- |- |- |- |- |
-
-|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
-|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
-|_Value_|- |- |- |- |- |- |- |- |- |- |- |i |- | - | - | c |
-
-
-|Bitfields|Description|
-|---------|-----------|
-| _c_ | enable channel if 1, disable if 0 |
-| _i_ | enable channel interrupt if 1, disable if 0 |
-
-
-## Writing the clock divider register
-
-|_bit_ |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
-|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
-|_Value_|d |d |d |d |d |d |d |d |d |d|d |d |d |d |d |d |
-
-|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
-|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
-|_Value_|d |d |d |d |d |d |d |d |d |d|d |d |d |d |d |d |
-
-
-|Bitfields|Description|
-|---------|-----------|
-| _d_ | an unsigned 32-bit value for the clock divider |
-
-
-## Writing the amplitude register
-
-|_bit_ |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
-|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
-|_Value_|- |- |- |- |- |- |- |- |- |-|- |- |- |- |- |- |
-
-|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
-|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
-|_Value_|a |a |a |a |a |a |a |a |a |a |a |a |a | a | a | a |
-
-
-|Bitfields|Description|
-|---------|-----------|
-| _a_ | an unsigned 16-bit value for the amplitude (sample) value with a bias of 32768 |
-
-## Notes
-The clock divider specifies the number of CPU clock ticks between two samples.
-
-Writing to the amplitude register adds the sample value to the sample buffer. The sample buffer is organized as a FIFO with 16 elements.
-
-Amplitude (sample) values are represented as unsigned, biased 16-bit numbers. The bias is 32768, so given an amplitude range of 1.0 to -1.0, a 1.0 is represented by 65535, 0.0 by 32768 and -1.0 by 0.
-
-Interrupt processing needs to be enabled for each channel if required.
-
-An interrupt on any channel will be signalled to the interrupt controller
-as IRQ 2. The interrupt service routine should check all running channels
-for an emtpy buffer.
-
-If an audio interrupt has occured on a channel, the interrupt enable flag
-is cleared for that channel. It needs to be re-enabled in the interrupt service routine.
-
-Interrupts also need to be enabled on the interrupt controller,
-and re-enabled there after each interrupt.
diff --git a/examples/pcmtest.pas b/examples/pcmtest.pas
deleted file mode 100644
index 423faaf..0000000
--- a/examples/pcmtest.pas
+++ /dev/null
@@ -1,47 +0,0 @@
-{$H1536}
-program pcmtest;
-uses pcmaudio;
-
-var filename:string;
- buf:SndBufPtr;
- f:file;
- size:integer;
- i:integer;
- c:char;
- sampleRate:integer;
- err:integer;
-begin
- if ParamCount > 0 then
- filename := ParamStr(1)
- else
- begin
- write('Filename> ');
- readln(filename);
- end;
-
- err := 1;
- if ParamCount > 1 then
- val(ParamStr(2),sampleRate, err);
-
- if err <> 0 then
- sampleRate := 16000;
-
- open(f, filename, ModeReadOnly);
- size := FileSize(f);
- new(buf, size);
-
- buf^ := '';
- write('Reading ', size, ' bytes...');
- for i := 1 to size do
- begin
- read(f,c);
- AppendChar(buf^,c);
- end;
- writeln;
-
- close(f);
-
- PlaySample(buf, sampleRate);
-
- dispose(buf);
-end.
diff --git a/examples/pcmtest2.pas b/examples/pcmtest2.pas
deleted file mode 100644
index 56ecb95..0000000
--- a/examples/pcmtest2.pas
+++ /dev/null
@@ -1,60 +0,0 @@
-{$H1536}
-program pcmtest2;
-uses pcmaudio;
-
-var filename:string;
- buf:SndBufPtr;
- f:file;
- size:integer;
- i:integer;
- c:char;
- sampleRate:integer;
- err:integer;
- done:boolean;
-begin
- if ParamCount > 0 then
- filename := ParamStr(1)
- else
- begin
- write('Filename> ');
- readln(filename);
- end;
-
- err := 1;
- if ParamCount > 1 then
- val(ParamStr(2), sampleRate, err);
- if err > 0 then
- sampleRate := 16000;
-
- open(f, filename, ModeReadOnly);
- size := FileSize(f);
- new(buf, size);
-
- buf^ := '';
- write('Reading ', size, ' bytes...');
- for i := 1 to size do
- begin
- read(f,c);
- AppendChar(buf^,c);
- end;
- writeln;
-
- close(f);
-
- SampleQStart(buf, sampleRate);
-
- write('Press Q to stop> ');
- done := false;
- while not done do
- begin
- read(c);
- if upcase(c) = 'Q' then
- done := true
- else
- writeln('Queue size: ', SampleQSize);
- end;
-
- SampleQStop;
-
- dispose(buf);
-end.
diff --git a/lib/pcmaudio.inc b/lib/pcmaudio.inc
deleted file mode 100644
index 4c3cdb3..0000000
--- a/lib/pcmaudio.inc
+++ /dev/null
@@ -1,7 +0,0 @@
-type SndBuf = string[32768];
-type SndBufPtr = ^SndBuf;
-
-procedure PlaySample(buf:SndBufPtr;sampleRate:integer); external;
-procedure SampleQStart(buf:SndBufPtr;sampleRate:integer); external;
-procedure SampleQStop; external;
-function SampleQSize:integer; external;
diff --git a/lib/pcmaudio.s b/lib/pcmaudio.s
deleted file mode 100644
index a030985..0000000
--- a/lib/pcmaudio.s
+++ /dev/null
@@ -1,241 +0,0 @@
- .EQU AUDIO_BASE $A00
- .EQU IRQC_REG $980
- .EQU IRQC_EN $80
-
-; args: sample rate
-START_PCMAUDIO:
- ; calculate clock divider
- LOADCP 77000000
- SWAP
- LOADCP _DIV
- CALL
-
- LOADC AUDIO_BASE + 1
- SWAP ; put clock divider on ToS
-; LOADCP 4812 ; clock divider for 16KHz sample rate
-; LOADCP 2406 ; clock divider for 32KHz sample rate
- STOREI 1
- LOADCP 32768 ; set amplitude to biased 0
- STOREI
- DROP
- LOADC AUDIO_BASE
- LOADC 17 ; enable channel, enable interrupt
- STOREI
- DROP
- RET
-
-STOP_AUDIO:
- LOADC AUDIO_BASE
- LOADC 0
- STOREI
- DROP
- RET
-
-; args: pointer to pascal string, sample rate
- .EQU PS_PTR 0
- .EQU PS_COUNT 4
- .EQU PS_FS 12
-PLAYSAMPLE:
- FPADJ -PS_FS
-
- LOADCP START_PCMAUDIO
- CALL
-
- DUP
- LOADI ; get string size from header
- SHR ; divide by 4 to get word count
- SHR
-
- STORE PS_COUNT
- INC 8 ; skip rest of header
- STORE PS_PTR ; store sample data pointer
-
-PS_L0:
- LOAD PS_PTR ; load pointer
- INC.S1.X2Y 4 ; increment and keep old value
- STORE PS_PTR ; store incremented value
-
- LOADI ; load 32 bit word
- DUP
- BROT ; get upper 16 bit word
- BROT
- LOADCP $FFFF
- AND
-
- LOADCP PLAY_1SAMPLE
- CALL
-
- LOADCP $FFFF ; get lower 16 bit word
- AND
- LOADCP PLAY_1SAMPLE
- CALL
-
- LOAD PS_COUNT ; load word count
- DEC 1 ; decrement
- DUP
- STORE PS_COUNT
- CBRANCH.NZ PS_L0 ; loop if not zero
-
- LOADCP STOP_AUDIO
- CALL
-
- FPADJ PS_FS
- RET
-
-; play one sample, waiting
-; for the clock divider, which
-; is visible via the phase flag
-; args: 16-bit unsigned sample
-PLAY_1SAMPLE:
-
-PLAY1_L0:
- LOADC AUDIO_BASE
- LOADI
- LOADC 8 ; get fifo_full flag
- AND
- CBRANCH.NZ PLAY1_L0 ; loop if fifo is full
-
- LOADC AUDIO_BASE+2 ; store amplitude value
- SWAP
- STOREI
- DROP
- RET
-
-; start interrupt-driven sample playback
-; args: pointer to pascal string, sample rate
-SAMPLEQSTART:
- LOADCP START_PCMAUDIO
- CALL
-
- LOADCP SMPLQ_COUNT
- OVER
- LOADI ; get string size from header
- SHR ; divide by 4 to get word count
- SHR
-
- STOREI
- DROP
-
- LOADCP SMPLQ_PTR
- SWAP
- INC 8 ; skip rest of header
- STOREI ; store sample data pointer
- DROP
-
- LOADCP SMPLQ_ISR ; set interrupt handler
- STOREREG IV
-
- LOADC IRQC_REG ; enable irq
- LOADC IRQC_EN
- STOREI
- DROP
-
- RET
-
-SAMPLEQSTOP:
- LOADCP SMPLQ_PTR
- LOADC 0
- STOREI
- DROP
-
- LOADCP STOP_AUDIO
- CALL
-
- LOADC IRQC_REG ; disable irq
- LOADC 0
- STOREI
- DROP
- RET
-
-SAMPLEQSIZE:
- LOADCP SMPLQ_COUNT
- LOADI
- RET
-
-SMPLQ_PTR: .WORD 0
-SMPLQ_COUNT: .WORD 0
-
-SMPLQ_ISR:
- LOADC IRQC_REG
- LOADI
- LOADC 4 ; check for audio interrupt
- AND
- CBRANCH.Z SMPLQ_I_XT ; if flag not set, exit
-
-SMPLQ_I_L:
- LOADCP SMPLQ_PTR
- LOADI ; load word pointer
- DUP
- CBRANCH.NZ SMPLQ_I_B ; check for null pointer
- DROP
- BRANCH SMPLQ_I_XT ; if null, end interrupt routine
-SMPLQ_I_B:
- LOADI ; load next word
- DUP
-
- BROT ; get high half-word
- BROT
- LOADCP $FFFF
- AND
-
- LOADC AUDIO_BASE+2
- SWAP
- STOREI ; write sample, keep addr
-
- SWAP ; addr to NoS, lower halfword on ToS
- LOADCP $FFFF
- AND
- STOREI ; write sample
- DROP
-
- ; decrement word count
- LOADCP SMPLQ_COUNT
- LOADI.S1.X2Y ; load counter, keep addr
- DEC 1
- DUP
- CBRANCH.Z SMPLQ_I_END ; end if zero
-
- STOREI ; store new counter value
- DROP
-
- ; increment pointer
- LOADCP SMPLQ_PTR
- LOADI.S1.X2Y
- INC 4
- STOREI
- DROP
-
- ; check if fifo is full
- LOADC AUDIO_BASE
- LOADI
- LOADC 8 ; fifo_full
- AND
- CBRANCH.Z SMPLQ_I_L ; next sample if not full
-
- LOADC AUDIO_BASE
- LOADC 17 ; re-enable channel interrupt
- STOREI
- DROP
-
- BRANCH SMPLQ_I_XT
-
- ; end playback, set ptr and counter to zero
-SMPLQ_I_END:
- DROP
- DROP
- LOADCP SMPLQ_PTR
- LOADC 0
- STOREI
- DROP
- LOADCP SMPLQ_COUNT
- LOADC 0
- STOREI
- DROP
-
-SMPLQ_I_XT:
- LOADC IRQC_REG ; re-enable interrupts
- LOADC IRQC_EN
- STOREI
- DROP
- LOADREG IR ; jump via interrupt return register
- JUMP
diff --git a/lib/runtime.s b/lib/runtime.s
index 9eb35d7..ce60b8d 100644
--- a/lib/runtime.s
+++ b/lib/runtime.s
@@ -1931,12 +1931,6 @@ _CLEARESTACK_XT:
; Terminate program: clear estack and
; jump to coreloader
PTERM:
- ; just to be safe, disable interrupts
- LOADC $980
- LOADC 0
- STOREI
- DROP
-
LOADCP _CLEARESTACK
CALL
LOADCP LOADER_START
diff --git a/lib/stdlib.pas b/lib/stdlib.pas
index 84025b3..dd6294c 100644
--- a/lib/stdlib.pas
+++ b/lib/stdlib.pas
@@ -1844,8 +1844,6 @@ end;
function filesize(var fil:file):integer;
begin
- checkerror(fil);
-
if fil.typ = IOChannel then
filesize := -1
else
diff --git a/tridoracpu/tridoracpu.srcs/tdraudio.v b/tridoracpu/tridoracpu.srcs/tdraudio.v
index 0cc055e..b9ecc94 100644
--- a/tridoracpu/tridoracpu.srcs/tdraudio.v
+++ b/tridoracpu/tridoracpu.srcs/tdraudio.v
@@ -42,12 +42,12 @@ module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
assign fifo_rd_en = (div_count == 0) && channel_enable && ~fifo_empty;
assign fifo_wr_en = wr_en && (reg_sel == TDRAU_REG_AMP);
- reg irq_buf, irq_enable;
- assign irq = channel_enable && irq_buf;
+ reg irq_buf, irq_done;
+ assign irq = irq_buf;
reg [DATA_WIDTH-1:0] rd_data_buf;
assign rd_data = rd_data_buf;
-
+ // assign rd_data = {{DATA_WIDTH-8{1'b0}}, {4{1'b0}}, fifo_full, fifo_empty, amp_phase, channel_enable};
assign amp_val = amp_out;
assign running = channel_enable;
@@ -56,8 +56,7 @@ module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
/* update read data buffer */
always @(posedge clk)
begin
- rd_data_buf <= {{DATA_WIDTH-8{1'b0}},
- {3{1'b0}}, irq_enable, fifo_full, fifo_empty, amp_phase, channel_enable};
+ rd_data_buf <= {{DATA_WIDTH-8{1'b0}}, {4{1'b0}}, fifo_full, fifo_empty, amp_phase, channel_enable};
end
/* irq signal to interrupt controller */
@@ -66,23 +65,23 @@ module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
if(reset)
irq_buf <= 0;
else
- if(fifo_empty && irq_enable)
+ if(fifo_empty && ~irq_done)
irq_buf <= 1;
else
irq_buf <= 0;
end
- /* interrupt enable flag */
+ /* interrupt done flag, used to ensure the irq signal is set for just one clock tick */
always @(posedge clk)
begin
if(reset)
- irq_enable <= 0;
+ irq_done <= 0;
else
- if(ctl_reg_write)
- irq_enable <= wr_data[4];
+ if(rd_en) // reset irq done flag on any register read
+ irq_done <= 0;
else
if(irq_buf)
- irq_enable <= 0; // disable interrupts after an interrupt
+ irq_done <= 1;
end
/* channel enable flag */
@@ -140,8 +139,8 @@ module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
amp_out <= AMP_BIAS;
// reset phase bit when enabling the channel
- if (ctl_reg_write && wr_data[0] && ~channel_enable)
- // when channel is being enabled, phase will be flipped on next tick
+ if (ctl_reg_write && wr_data[0])
+ // when channel is enabled, phase will be flipped on next tick
// because div_count will become zero
amp_phase <= 1;
end
@@ -233,6 +232,9 @@ module tdraudio #(DATA_WIDTH=32) (
chan3_amp,
chan3_running, chan3_irq);
+ reg irq_out_buf;
+ assign irq_out = irq_out_buf;
+
reg [DAC_WIDTH:0] deltasigma_acc; // one extra bit
wire [DAC_WIDTH:0] amp_sum = chan0_amp + chan1_amp + chan2_amp + chan3_amp; // also one overflow bit here
assign gain_sel = 1; // gain select: 0 -> 12dB, 1 -> 6dB
@@ -240,9 +242,6 @@ module tdraudio #(DATA_WIDTH=32) (
// assign shutdown_n = running;
assign shutdown_n = 1; /* don't enable shutdown mode, it creates a mains hum */
- reg irq_out_buf;
- assign irq_out = irq_out_buf;
-
always @(posedge clk) irq_out_buf <= chan0_irq || chan1_irq || chan2_irq || chan3_irq;
/* delta-sigma DAC */
diff --git a/tridoracpu/tridoracpu.xpr b/tridoracpu/tridoracpu.xpr
index 3767063..3b60ca9 100644
--- a/tridoracpu/tridoracpu.xpr
+++ b/tridoracpu/tridoracpu.xpr
@@ -378,18 +378,16 @@
-
+
-
- Similar to Performance_ExplorePostRoutePhysOpt, but enables logic optimization step (opt_design) with the ExploreWithRemap directive.
+
+ Includes alternate algorithms for timing-driven optimization
-
-
-
+
-
+
@@ -397,11 +395,8 @@
-
-
-
-
+