Compare commits
No commits in common. "main" and "tdraudio" have entirely different histories.
26 changed files with 193 additions and 1285 deletions
21
README.md
21
README.md
|
|
@ -41,25 +41,6 @@ Other inspirations were, among others, in no particular order:
|
||||||
- the Magic-1 by Bill Buzbee
|
- the Magic-1 by Bill Buzbee
|
||||||
- the OPC by revaldinho
|
- the OPC by revaldinho
|
||||||
|
|
||||||
## October 2025 Update
|
|
||||||
This update introduces a data cache for the Tridora-CPU. It is similar to the instruction cache
|
|
||||||
as it caches the 16 bytes coming from the DRAM memory controller. It is a write-back cache, i.e.
|
|
||||||
when a word inside the cached area is written, it updates the cache instead of invalidating it.
|
|
||||||
|
|
||||||
This is important because there are many idioms in the stack machine assembly language where you
|
|
||||||
store a local variable and then read it again (e.g. updating a loop variable).
|
|
||||||
|
|
||||||
Since for most programs, the user stack and parts of the heap are inside the DRAM area, the data cache
|
|
||||||
has a more noticable impact. In the benchmark program that was already used for the last update,
|
|
||||||
the data cache results in a 50% improvement for the empty loop test. This is in comparison to the version
|
|
||||||
without data cache but with the instruction cache, both running code out of DRAM.
|
|
||||||
|
|
||||||
It is also noticable for compile times: With the data cache, compiling and assembling the
|
|
||||||
"hello,world" program takes 16 seconds instead of 20. With a little tweak of the SD-Card controller
|
|
||||||
that slightly increased the data transfer rate, the build time goes down to 15 seconds.
|
|
||||||
|
|
||||||
Also, an audio controller was added that allows interrupt-driven sample playback via an AMP2 PMOD.
|
|
||||||
|
|
||||||
## April 2025 Update
|
## April 2025 Update
|
||||||
The clock has been reduced to 77 MHz from 83 MHz. Apparently the design was at the limit and
|
The clock has been reduced to 77 MHz from 83 MHz. Apparently the design was at the limit and
|
||||||
timing problems were cropping up seemingly at random. Reducing the clock speed made some
|
timing problems were cropping up seemingly at random. Reducing the clock speed made some
|
||||||
|
|
@ -81,7 +62,7 @@ on the emulator image.
|
||||||
- the [Hackaday project](https://hackaday.io/project/198324-tridora-cpu) (mostly copy-paste from this README)
|
- the [Hackaday project](https://hackaday.io/project/198324-tridora-cpu) (mostly copy-paste from this README)
|
||||||
- the [YouTube channel](https://www.youtube.com/@tridoracpu/videos) with some demo videos
|
- the [YouTube channel](https://www.youtube.com/@tridoracpu/videos) with some demo videos
|
||||||
- the [emulator](https://git.insignificance.de/slederer/-/packages/generic/tridoraemu/0.0.5/files/12) (source and windows binary)
|
- the [emulator](https://git.insignificance.de/slederer/-/packages/generic/tridoraemu/0.0.5/files/12) (source and windows binary)
|
||||||
- the [FPGA bitstream](https://git.insignificance.de/slederer/-/packages/generic/tdr-bitstream/0.0.4/files/16) for the Arty-A7-35T board
|
- the [FPGA bitstream](https://git.insignificance.de/slederer/-/packages/generic/tdr-bitstream/0.0.2/files/14) for the Arty-A7-35T board
|
||||||
- an [SD-card image](https://git.insignificance.de/slederer/-/packages/generic/tdr-cardimage/0.0.4/files/13)
|
- an [SD-card image](https://git.insignificance.de/slederer/-/packages/generic/tdr-cardimage/0.0.4/files/13)
|
||||||
|
|
||||||
Contact the author here: tridoracpu [at] insignificance.de
|
Contact the author here: tridoracpu [at] insignificance.de
|
||||||
|
|
|
||||||
|
|
@ -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|
|
|_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|
|
|Bitfields|Description|
|
||||||
|---------|-----------|
|
|---------|-----------|
|
||||||
| _t_ | unsigned 24 bit counter of timer ticks since reset
|
| _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
|
| _p1_ | IRQ 1 (timer tick) interrupt pending if 1
|
||||||
| _p0_ | IRQ 0 (UART) interrupt pending if 1
|
| _p0_ | IRQ 0 (UART) interrupt pending if 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,4 +34,3 @@ Currently, only I/O slots 0-3 are being used.
|
||||||
| 1 | $880 | SPI-SD |
|
| 1 | $880 | SPI-SD |
|
||||||
| 2 | $900 | VGA |
|
| 2 | $900 | VGA |
|
||||||
| 3 | $980 | IRQC |
|
| 3 | $980 | IRQC |
|
||||||
| 4 | $A00 | TDRAUDIO |
|
|
||||||
|
|
|
||||||
104
doc/tdraudio.md
104
doc/tdraudio.md
|
|
@ -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.
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
const FIREWIDTH = 319; FIREHEIGHT = 79; (* keep in sync with fastfire.s! *)
|
|
||||||
type FireBuf = array [0..FIREHEIGHT, 0..FIREWIDTH] of integer;
|
|
||||||
|
|
||||||
procedure FastFireUpdate(var f:FireBuf); external;
|
|
||||||
procedure FastFireDraw(var f:FireBuf;screenx, screeny:integer); external;
|
|
||||||
|
|
@ -1,326 +0,0 @@
|
||||||
; width and height of the fire cell matrix
|
|
||||||
; Be sure to sync this with fastfire.inc!
|
|
||||||
.EQU FIREWIDTH 319
|
|
||||||
.EQU FIREHEIGHT 79
|
|
||||||
|
|
||||||
;
|
|
||||||
; The cell matrix actually has one column
|
|
||||||
; and one row more than FIREWIDTH and
|
|
||||||
; FIREHEIGHT to handle the negative
|
|
||||||
; X offsets when calculating new
|
|
||||||
; cell values.
|
|
||||||
; Likewise, there is one more row.
|
|
||||||
; So rows are processed from 0 to FIREHEIGHT - 2
|
|
||||||
; and columms from 1 to FIREWIDTH - 1.
|
|
||||||
|
|
||||||
; cells considered for calculating new
|
|
||||||
; value for cell O (reference cells):
|
|
||||||
; .....O......
|
|
||||||
; ....123.....
|
|
||||||
; .....4......
|
|
||||||
|
|
||||||
; args: pointer to fire cell buffer
|
|
||||||
.EQU FF_ROW_COUNT 0
|
|
||||||
.EQU FF_COL_COUNT 4
|
|
||||||
.EQU FF_ROW_OFFS 8
|
|
||||||
.EQU FF_OFFS1 12
|
|
||||||
.EQU FF_OFFS2 16
|
|
||||||
.EQU FF_OFFS3 20
|
|
||||||
.EQU FF_OFFS4 24
|
|
||||||
.EQU FF_CELL_PTR 28
|
|
||||||
.EQU FF_FS 32
|
|
||||||
FASTFIREUPDATE:
|
|
||||||
FPADJ -FF_FS
|
|
||||||
STORE FF_CELL_PTR
|
|
||||||
LOADC FIREHEIGHT-1
|
|
||||||
STORE FF_ROW_COUNT
|
|
||||||
|
|
||||||
; calculate offsets for reference cells
|
|
||||||
LOADC FIREWIDTH+1
|
|
||||||
SHL 2
|
|
||||||
DUP
|
|
||||||
STORE FF_ROW_OFFS ; offset to next row: WIDTH*4
|
|
||||||
DEC 4 ; offset to cell 1: row offset - 4
|
|
||||||
DUP
|
|
||||||
STORE FF_OFFS1
|
|
||||||
INC 4
|
|
||||||
DUP
|
|
||||||
STORE FF_OFFS2 ; offset to cell 2: + 4
|
|
||||||
INC 4
|
|
||||||
STORE FF_OFFS3 ; offset to cell 3: + 4
|
|
||||||
LOAD FF_ROW_OFFS
|
|
||||||
SHL 1 ; offset to cell 4: row offset * 2
|
|
||||||
STORE FF_OFFS4
|
|
||||||
|
|
||||||
; start at column 1
|
|
||||||
LOAD FF_CELL_PTR
|
|
||||||
INC 4
|
|
||||||
STORE FF_CELL_PTR
|
|
||||||
FF_ROW:
|
|
||||||
LOADC FIREWIDTH-1
|
|
||||||
STORE FF_COL_COUNT
|
|
||||||
|
|
||||||
FF_COL:
|
|
||||||
LOAD FF_CELL_PTR
|
|
||||||
LOAD FF_OFFS1
|
|
||||||
ADD
|
|
||||||
LOADI
|
|
||||||
|
|
||||||
LOAD FF_CELL_PTR
|
|
||||||
LOAD FF_OFFS2
|
|
||||||
ADD
|
|
||||||
LOADI
|
|
||||||
|
|
||||||
LOAD FF_CELL_PTR
|
|
||||||
LOAD FF_OFFS3
|
|
||||||
ADD
|
|
||||||
LOADI
|
|
||||||
|
|
||||||
LOAD FF_CELL_PTR
|
|
||||||
LOAD FF_OFFS4
|
|
||||||
ADD
|
|
||||||
LOADI
|
|
||||||
|
|
||||||
ADD
|
|
||||||
ADD
|
|
||||||
ADD
|
|
||||||
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
|
|
||||||
; if new cell value > 0, subtract 1 to cool down
|
|
||||||
DUP
|
|
||||||
CBRANCH.Z FF_SKIP
|
|
||||||
DEC 1
|
|
||||||
FF_SKIP:
|
|
||||||
LOAD FF_CELL_PTR ; load cell ptr
|
|
||||||
SWAP ; swap with new value
|
|
||||||
STOREI 4 ; store with postincrement
|
|
||||||
STORE FF_CELL_PTR ; save new ptr value
|
|
||||||
|
|
||||||
LOAD FF_COL_COUNT ; decrement column count
|
|
||||||
DEC 1
|
|
||||||
DUP
|
|
||||||
STORE FF_COL_COUNT
|
|
||||||
CBRANCH.NZ FF_COL ; loop if col count <> 0
|
|
||||||
|
|
||||||
; at the end of a row, go to next row
|
|
||||||
; by adding 8 to the cell pointer,
|
|
||||||
; skipping the first cell of the next row
|
|
||||||
LOAD FF_CELL_PTR
|
|
||||||
INC 8
|
|
||||||
STORE FF_CELL_PTR
|
|
||||||
|
|
||||||
LOAD FF_ROW_COUNT ; decrement row count
|
|
||||||
DEC 1
|
|
||||||
DUP
|
|
||||||
STORE FF_ROW_COUNT
|
|
||||||
CBRANCH.NZ FF_ROW ; loop if row count <> 0
|
|
||||||
|
|
||||||
FF_EXIT:
|
|
||||||
FPADJ FF_FS
|
|
||||||
RET
|
|
||||||
|
|
||||||
; framebuffer controller registers
|
|
||||||
.EQU FB_RA $900
|
|
||||||
.EQU FB_WA $901
|
|
||||||
.EQU FB_IO $902
|
|
||||||
.EQU FB_PS $903
|
|
||||||
.EQU FB_PD $904
|
|
||||||
.EQU FB_CTL $905
|
|
||||||
.EQU WORDS_PER_LINE 80
|
|
||||||
|
|
||||||
; fire width in vmem words (strict left-to-right evaluation)
|
|
||||||
.EQU FFD_ROW_WORDS 1 + FIREWIDTH / 8
|
|
||||||
|
|
||||||
; draw all fire cells
|
|
||||||
; args: pointer to fire cell buffer, screen x, screen y
|
|
||||||
.EQU FFD_CELL_PTR 0
|
|
||||||
.EQU FFD_X 4
|
|
||||||
.EQU FFD_Y 8
|
|
||||||
.EQU FFD_ROW_COUNT 12
|
|
||||||
.EQU FFD_ROW_WORDCOUNT 16
|
|
||||||
.EQU FFD_VMEM_PTR 20
|
|
||||||
.EQU FFD_FS 24
|
|
||||||
FASTFIREDRAW:
|
|
||||||
FPADJ -FFD_FS
|
|
||||||
STORE FFD_Y
|
|
||||||
STORE FFD_X
|
|
||||||
STORE FFD_CELL_PTR
|
|
||||||
|
|
||||||
; calculate video memory addr
|
|
||||||
; addr = y * 80 + X / 8
|
|
||||||
LOAD FFD_Y
|
|
||||||
SHL 2 ; y * 16
|
|
||||||
SHL 2
|
|
||||||
DUP
|
|
||||||
SHL 2 ; + y * 64
|
|
||||||
ADD ; = y * 80
|
|
||||||
|
|
||||||
LOAD FFD_X
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
ADD ; + x / 8
|
|
||||||
|
|
||||||
DUP
|
|
||||||
STORE FFD_VMEM_PTR
|
|
||||||
LOADC FB_WA ; set vmem write address
|
|
||||||
SWAP
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
LOADC FIREHEIGHT + 1
|
|
||||||
STORE FFD_ROW_COUNT
|
|
||||||
FFD_ROW:
|
|
||||||
LOADC FFD_ROW_WORDS
|
|
||||||
STORE FFD_ROW_WORDCOUNT
|
|
||||||
|
|
||||||
LOADC FB_WA ; set vmem write address
|
|
||||||
LOAD FFD_VMEM_PTR
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
FFD_WORD:
|
|
||||||
LOAD FFD_CELL_PTR ; load cell ptr
|
|
||||||
LOADC 0 ; vmem word, start with 0
|
|
||||||
|
|
||||||
; leftmost pixel (0)
|
|
||||||
OVER ; [ cptr, vmemw, cptr ]
|
|
||||||
LOADI ; load cell value [ cptr, vmemw, cellval ]
|
|
||||||
SHR ; scale it down (from 7 bits to 4)
|
|
||||||
SHR
|
|
||||||
SHR ; [ cptr, vmemw, cellval shr 3 ]
|
|
||||||
OR ; [ cptr, vmemw ]
|
|
||||||
SWAP ; [ vmemw, cptr ]
|
|
||||||
INC 4 ; increment cell ptr on stack [ vmemw, cptr + 4 ]
|
|
||||||
SWAP ; [ cptr + 4, vmemw ]
|
|
||||||
|
|
||||||
SHL 2 ; move bits to left for next pixel
|
|
||||||
SHL 2
|
|
||||||
|
|
||||||
; pixel 1
|
|
||||||
OVER
|
|
||||||
LOADI ; load cell value
|
|
||||||
SHR ; scale it down (from 7 bits to 4)
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
OR
|
|
||||||
SWAP
|
|
||||||
INC 4 ; increment cell ptr on stack
|
|
||||||
SWAP
|
|
||||||
|
|
||||||
SHL 2 ; move bits to left for next pixel
|
|
||||||
SHL 2
|
|
||||||
|
|
||||||
; pixel 2
|
|
||||||
OVER
|
|
||||||
LOADI ; load cell value
|
|
||||||
SHR ; scale it down (from 7 bits to 4)
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
OR
|
|
||||||
SWAP
|
|
||||||
INC 4 ; increment cell ptr on stack
|
|
||||||
SWAP
|
|
||||||
|
|
||||||
SHL 2 ; move bits to left for next pixel
|
|
||||||
SHL 2
|
|
||||||
|
|
||||||
; pixel 3
|
|
||||||
OVER
|
|
||||||
LOADI ; load cell value
|
|
||||||
SHR ; scale it down (from 7 bits to 4)
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
OR
|
|
||||||
SWAP
|
|
||||||
INC 4 ; increment cell ptr on stack
|
|
||||||
SWAP
|
|
||||||
|
|
||||||
SHL 2 ; move bits to left for next pixel
|
|
||||||
SHL 2
|
|
||||||
|
|
||||||
; pixel 4
|
|
||||||
OVER
|
|
||||||
LOADI ; load cell value
|
|
||||||
SHR ; scale it down (from 7 bits to 4)
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
OR
|
|
||||||
SWAP
|
|
||||||
INC 4 ; increment cell ptr on stack
|
|
||||||
SWAP
|
|
||||||
|
|
||||||
SHL 2 ; move bits to left for next pixel
|
|
||||||
SHL 2
|
|
||||||
|
|
||||||
; pixel 5
|
|
||||||
OVER
|
|
||||||
LOADI ; load cell value
|
|
||||||
SHR ; scale it down (from 7 bits to 4)
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
OR
|
|
||||||
SWAP
|
|
||||||
INC 4 ; increment cell ptr on stack
|
|
||||||
SWAP
|
|
||||||
|
|
||||||
SHL 2 ; move bits to left for next pixel
|
|
||||||
SHL 2
|
|
||||||
|
|
||||||
; pixel 6
|
|
||||||
OVER
|
|
||||||
LOADI ; load cell value
|
|
||||||
SHR ; scale it down (from 7 bits to 4)
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
OR
|
|
||||||
SWAP
|
|
||||||
INC 4 ; increment cell ptr on stack
|
|
||||||
SWAP
|
|
||||||
|
|
||||||
SHL 2 ; move bits to left for next pixel
|
|
||||||
SHL 2
|
|
||||||
|
|
||||||
; pixel 7
|
|
||||||
OVER
|
|
||||||
LOADI ; load cell value
|
|
||||||
SHR ; scale it down (from 7 bits to 4)
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
OR
|
|
||||||
SWAP
|
|
||||||
INC 4 ; increment cell ptr on stack
|
|
||||||
SWAP
|
|
||||||
|
|
||||||
; store word to vmem
|
|
||||||
; vmem write addr will autoincrement
|
|
||||||
LOADC FB_IO
|
|
||||||
SWAP
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
STORE FFD_CELL_PTR
|
|
||||||
|
|
||||||
; prepare for next word
|
|
||||||
LOAD FFD_ROW_WORDCOUNT
|
|
||||||
DEC 1
|
|
||||||
DUP
|
|
||||||
STORE FFD_ROW_WORDCOUNT
|
|
||||||
CBRANCH.NZ FFD_WORD
|
|
||||||
|
|
||||||
; prepare for next row
|
|
||||||
LOAD FFD_VMEM_PTR
|
|
||||||
LOADC WORDS_PER_LINE
|
|
||||||
ADD
|
|
||||||
STORE FFD_VMEM_PTR
|
|
||||||
|
|
||||||
LOAD FFD_ROW_COUNT
|
|
||||||
DEC 1
|
|
||||||
DUP
|
|
||||||
STORE FFD_ROW_COUNT
|
|
||||||
CBRANCH.NZ FFD_ROW
|
|
||||||
FFD_EXIT:
|
|
||||||
FPADJ FFD_FS
|
|
||||||
RET
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
{$H1}
|
|
||||||
{$S2}
|
|
||||||
program fire;
|
|
||||||
const MAXX = 30;
|
|
||||||
MAXY = 50;
|
|
||||||
var firebuf: array [0..MAXY, 0..MAXX] of integer;
|
|
||||||
|
|
||||||
firepalette: array [0..15] of integer =
|
|
||||||
( $FFA, $FF8, $FF4, $FF0, $FE0, $FD0, $FA0, $F90,
|
|
||||||
$F00, $E00, $D00, $A00, $800, $600, $300, $000);
|
|
||||||
x,y:integer;
|
|
||||||
|
|
||||||
procedure createPalette;
|
|
||||||
var i:integer;
|
|
||||||
begin
|
|
||||||
for i := 15 downto 0 do
|
|
||||||
setpalette(15 - i, firepalette[i]);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure fireItUp;
|
|
||||||
var x,y:integer;
|
|
||||||
begin
|
|
||||||
y := MAXY - 1;
|
|
||||||
for x := 1 to MAXX - 1 do
|
|
||||||
firebuf[y, x] := random and 127;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure updateFire;
|
|
||||||
var i,x,y:integer;
|
|
||||||
begin
|
|
||||||
for y := 0 to MAXY - 2 do
|
|
||||||
for x := 1 to MAXX - 1 do
|
|
||||||
begin
|
|
||||||
i :=
|
|
||||||
((firebuf[y + 1, x - 1]
|
|
||||||
+ firebuf[y + 1, x]
|
|
||||||
+ firebuf[y + 1, x + 1]
|
|
||||||
+ firebuf[y + 2, x])
|
|
||||||
) shr 2;
|
|
||||||
if i > 0 then
|
|
||||||
i := i - 1;
|
|
||||||
firebuf[y, x] := i;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure drawFire;
|
|
||||||
var x, y, col:integer;
|
|
||||||
begin
|
|
||||||
for y := 0 to MAXY - 1 do
|
|
||||||
begin
|
|
||||||
x := 0;
|
|
||||||
for col in firebuf[y] do
|
|
||||||
begin
|
|
||||||
putpixel(300 + x, 150 + y, col shr 3);
|
|
||||||
x := x + 1;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
randomize;
|
|
||||||
initgraphics;
|
|
||||||
createPalette;
|
|
||||||
while not conavail do
|
|
||||||
begin
|
|
||||||
fireItUp;
|
|
||||||
updateFire;
|
|
||||||
drawFire;
|
|
||||||
end;
|
|
||||||
|
|
||||||
for y := 0 to MAXY do
|
|
||||||
begin
|
|
||||||
x := firebuf[y, 10];
|
|
||||||
drawline(0, y, x, y, 1);
|
|
||||||
end;
|
|
||||||
end.
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
{$H1}
|
|
||||||
{$S1}
|
|
||||||
program fire2;
|
|
||||||
uses fastfire;
|
|
||||||
|
|
||||||
const MAXX = FIREWIDTH;
|
|
||||||
MAXY = FIREHEIGHT;
|
|
||||||
|
|
||||||
var firecells: FireBuf;
|
|
||||||
|
|
||||||
firepalette: array [0..15] of integer =
|
|
||||||
{ ( $FFA, $FF8, $FF4, $FF0, $FE0, $FD0, $FA0, $F90,
|
|
||||||
$F00, $E00, $D00, $A00, $800, $600, $300, $000); }
|
|
||||||
( $FFA, $FFA, $FFA, $FFA, $FF0, $FF0, $FF0, $FF0,
|
|
||||||
$FF0, $FD0, $FA0, $C00, $A00, $700, $400, $000);
|
|
||||||
x,y:integer;
|
|
||||||
|
|
||||||
procedure createPalette;
|
|
||||||
var i:integer;
|
|
||||||
begin
|
|
||||||
for i := 15 downto 0 do
|
|
||||||
setpalette(15 - i, firepalette[i]);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure fireItUp;
|
|
||||||
var x,y:integer;
|
|
||||||
begin
|
|
||||||
y := MAXY - 1;
|
|
||||||
for x := 1 to MAXX - 1 do
|
|
||||||
firecells[y, x] := random and 127;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure updateFire;
|
|
||||||
var i,x,y:integer;
|
|
||||||
begin
|
|
||||||
for y := 0 to MAXY - 2 do
|
|
||||||
for x := 1 to MAXX - 1 do
|
|
||||||
begin
|
|
||||||
i :=
|
|
||||||
((firecells[y + 1, x - 1]
|
|
||||||
+ firecells[y + 1, x]
|
|
||||||
+ firecells[y + 1, x + 1]
|
|
||||||
+ firecells[y + 2, x])
|
|
||||||
) shr 2;
|
|
||||||
if i > 0 then
|
|
||||||
i := i - 1;
|
|
||||||
firecells[y, x] := i;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure drawFire;
|
|
||||||
var x, y, col:integer;
|
|
||||||
begin
|
|
||||||
for y := 0 to MAXY - 1 do
|
|
||||||
begin
|
|
||||||
x := 0;
|
|
||||||
for col in firecells[y] do
|
|
||||||
begin
|
|
||||||
putpixel(100 + x, 150 + y, col shr 3);
|
|
||||||
x := x + 1;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
randomize;
|
|
||||||
initgraphics;
|
|
||||||
createPalette;
|
|
||||||
while not conavail do
|
|
||||||
begin
|
|
||||||
fireItUp;
|
|
||||||
FastFireUpdate(firecells);
|
|
||||||
{ updateFire; }
|
|
||||||
FastFireDraw(firecells, 160, 100);
|
|
||||||
{ drawFire; }
|
|
||||||
end;
|
|
||||||
|
|
||||||
for y := 0 to MAXY do
|
|
||||||
begin
|
|
||||||
x := firecells[y, 10];
|
|
||||||
drawline(0, y, x, y, 1);
|
|
||||||
end;
|
|
||||||
end.
|
|
||||||
|
|
@ -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.
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
{$H2560}
|
|
||||||
program pcmtest2;
|
|
||||||
uses pcmaudio;
|
|
||||||
|
|
||||||
var filename:string;
|
|
||||||
buf:SndBufPtr;
|
|
||||||
sampleRate:integer;
|
|
||||||
err:integer;
|
|
||||||
done:boolean;
|
|
||||||
c:char;
|
|
||||||
|
|
||||||
function readAudioFile(fname:string):SndBufPtr;
|
|
||||||
var i,size:integer;
|
|
||||||
c:char;
|
|
||||||
buf:SndBufPtr;
|
|
||||||
f:file;
|
|
||||||
begin
|
|
||||||
open(f, fname, 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);
|
|
||||||
|
|
||||||
readAudioFile := buf;
|
|
||||||
end;
|
|
||||||
|
|
||||||
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 := 32000;
|
|
||||||
|
|
||||||
buf := readAudioFile(filename);
|
|
||||||
|
|
||||||
SampleQStart(buf, sampleRate);
|
|
||||||
|
|
||||||
write('Press ESC to stop> ');
|
|
||||||
done := false;
|
|
||||||
while not done do
|
|
||||||
begin
|
|
||||||
read(c);
|
|
||||||
if c = #27 then
|
|
||||||
begin
|
|
||||||
done := true; writeln(';');
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if c = '?' then
|
|
||||||
begin
|
|
||||||
writeln; writeln('Queue: ', SampleQSize);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
SampleQStop;
|
|
||||||
|
|
||||||
dispose(buf);
|
|
||||||
end.
|
|
||||||
|
|
@ -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;
|
|
||||||
247
lib/pcmaudio.s
247
lib/pcmaudio.s
|
|
@ -1,247 +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
|
|
||||||
|
|
||||||
; set amplitude out to zero (biased)
|
|
||||||
LOADC AUDIO_BASE+2
|
|
||||||
LOADCP 32768
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
SMPLQ_I_XT:
|
|
||||||
LOADC IRQC_REG ; re-enable interrupts
|
|
||||||
LOADC IRQC_EN
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
LOADREG IR ; jump via interrupt return register
|
|
||||||
JUMP
|
|
||||||
|
|
@ -1931,12 +1931,6 @@ _CLEARESTACK_XT:
|
||||||
; Terminate program: clear estack and
|
; Terminate program: clear estack and
|
||||||
; jump to coreloader
|
; jump to coreloader
|
||||||
PTERM:
|
PTERM:
|
||||||
; just to be safe, disable interrupts
|
|
||||||
LOADC $980
|
|
||||||
LOADC 0
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
LOADCP _CLEARESTACK
|
LOADCP _CLEARESTACK
|
||||||
CALL
|
CALL
|
||||||
LOADCP LOADER_START
|
LOADCP LOADER_START
|
||||||
|
|
|
||||||
|
|
@ -1844,8 +1844,6 @@ end;
|
||||||
|
|
||||||
function filesize(var fil:file):integer;
|
function filesize(var fil:file):integer;
|
||||||
begin
|
begin
|
||||||
checkerror(fil);
|
|
||||||
|
|
||||||
if fil.typ = IOChannel then
|
if fil.typ = IOChannel then
|
||||||
filesize := -1
|
filesize := -1
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -324,9 +324,7 @@ begin
|
||||||
rewindStringList(usedUnits);
|
rewindStringList(usedUnits);
|
||||||
while nextStringListItem(usedUnits, unitName) do
|
while nextStringListItem(usedUnits, unitName) do
|
||||||
emitInclude(unitName + UnitSuffix2);
|
emitInclude(unitName + UnitSuffix2);
|
||||||
(* _END label needs to be word-aligned because
|
|
||||||
it is used as the start of the heap *)
|
|
||||||
emitIns('.ALIGN');
|
|
||||||
emitLabelRaw('_END');
|
emitLabelRaw('_END');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2056,9 +2056,6 @@ begin
|
||||||
operandValue := 0;
|
operandValue := 0;
|
||||||
emitBlock(count, operandValue);
|
emitBlock(count, operandValue);
|
||||||
end
|
end
|
||||||
else
|
|
||||||
if lastToken.tokenText = '.ALIGN' then
|
|
||||||
alignOutput(wordSize)
|
|
||||||
else
|
else
|
||||||
errorExit2('Unrecognized directive', lastToken.tokenText);
|
errorExit2('Unrecognized directive', lastToken.tokenText);
|
||||||
end;
|
end;
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,6 @@ begin
|
||||||
if not invalid then
|
if not invalid then
|
||||||
begin
|
begin
|
||||||
open(xferFile, filename, ModeOverwrite);
|
open(xferFile, filename, ModeOverwrite);
|
||||||
blockNo := 0;
|
|
||||||
done := false;
|
done := false;
|
||||||
repeat
|
repeat
|
||||||
serReadBlock(ok);
|
serReadBlock(ok);
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports clk]
|
||||||
create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports clk]
|
create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports clk]
|
||||||
|
|
||||||
## Switches
|
## Switches
|
||||||
#set_property -dict {PACKAGE_PIN A8 IOSTANDARD LVCMOS33} [get_ports sw0]
|
set_property -dict {PACKAGE_PIN A8 IOSTANDARD LVCMOS33} [get_ports sw0]
|
||||||
#set_property -dict {PACKAGE_PIN C11 IOSTANDARD LVCMOS33} [get_ports sw1]
|
set_property -dict {PACKAGE_PIN C11 IOSTANDARD LVCMOS33} [get_ports sw1]
|
||||||
#set_property -dict { PACKAGE_PIN C10 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L13N_T2_MRCC_16 Sch=sw[2]
|
#set_property -dict { PACKAGE_PIN C10 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L13N_T2_MRCC_16 Sch=sw[2]
|
||||||
#set_property -dict { PACKAGE_PIN A10 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L14P_T2_SRCC_16 Sch=sw[3]
|
#set_property -dict { PACKAGE_PIN A10 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L14P_T2_SRCC_16 Sch=sw[3]
|
||||||
|
|
||||||
|
|
@ -34,7 +34,7 @@ set_property -dict {PACKAGE_PIN T9 IOSTANDARD LVCMOS33} [get_ports led2]
|
||||||
set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports led3]
|
set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports led3]
|
||||||
|
|
||||||
## Buttons
|
## Buttons
|
||||||
#set_property -dict {PACKAGE_PIN D9 IOSTANDARD LVCMOS33} [get_ports btn0]
|
set_property -dict {PACKAGE_PIN D9 IOSTANDARD LVCMOS33} [get_ports btn0]
|
||||||
#set_property -dict { PACKAGE_PIN C9 IOSTANDARD LVCMOS33 } [get_ports { btn1 }]; #IO_L11P_T1_SRCC_16 Sch=btn[1]
|
#set_property -dict { PACKAGE_PIN C9 IOSTANDARD LVCMOS33 } [get_ports { btn1 }]; #IO_L11P_T1_SRCC_16 Sch=btn[1]
|
||||||
#set_property -dict { PACKAGE_PIN B9 IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; #IO_L11N_T1_SRCC_16 Sch=btn[2]
|
#set_property -dict { PACKAGE_PIN B9 IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; #IO_L11N_T1_SRCC_16 Sch=btn[2]
|
||||||
#set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L12P_T1_MRCC_16 Sch=btn[3]
|
#set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L12P_T1_MRCC_16 Sch=btn[3]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
module irqctrl #(IRQ_LINES = 3, IRQ_DELAY_WIDTH = 4) (
|
module irqctrl #(IRQ_LINES = 2, IRQ_DELAY_WIDTH = 4) (
|
||||||
input wire clk,
|
input wire clk,
|
||||||
input wire [IRQ_LINES-1:0] irq_in,
|
input wire [IRQ_LINES-1:0] irq_in,
|
||||||
input wire cs,
|
input wire cs,
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,11 @@ module stackcpu #(parameter ADDR_WIDTH = 32, WIDTH = 32,
|
||||||
output wire write_enable,
|
output wire write_enable,
|
||||||
input wire mem_wait,
|
input wire mem_wait,
|
||||||
|
|
||||||
output wire debug1,
|
output wire led1,
|
||||||
output wire debug2,
|
output wire led2,
|
||||||
output wire debug3
|
output wire led3
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam EVAL_STACK_INDEX_WIDTH = 6;
|
localparam EVAL_STACK_INDEX_WIDTH = 6;
|
||||||
|
|
||||||
wire reset = !rst;
|
wire reset = !rst;
|
||||||
|
|
@ -90,6 +90,7 @@ module stackcpu #(parameter ADDR_WIDTH = 32, WIDTH = 32,
|
||||||
wire mem_write;
|
wire mem_write;
|
||||||
|
|
||||||
wire x_is_zero;
|
wire x_is_zero;
|
||||||
|
// wire [WIDTH-1:0] y_plus_operand = Y + operand;
|
||||||
|
|
||||||
wire x_equals_y = X == Y;
|
wire x_equals_y = X == Y;
|
||||||
wire y_lessthan_x = $signed(Y) < $signed(X);
|
wire y_lessthan_x = $signed(Y) < $signed(X);
|
||||||
|
|
@ -104,10 +105,16 @@ module stackcpu #(parameter ADDR_WIDTH = 32, WIDTH = 32,
|
||||||
assign write_enable = mem_write_enable;
|
assign write_enable = mem_write_enable;
|
||||||
|
|
||||||
// debug output ------------------------------------------------------------------------------------
|
// debug output ------------------------------------------------------------------------------------
|
||||||
assign debug1 = reset;
|
assign led1 = reset;
|
||||||
assign debug2 = ins_loadc;
|
assign led2 = ins_loadc;
|
||||||
assign debug3 = ins_branch;
|
assign led3 = ins_branch;
|
||||||
|
// assign debug_out1 = { mem_read_enable, mem_write_enable, x_is_zero,
|
||||||
|
// ins_branch, ins_aluop, y_lessthan_x, x_equals_y, {7{1'b0}}, seq_state};
|
||||||
|
// assign debug_out2 = data_in;
|
||||||
|
// assign debug_out3 = nX;
|
||||||
|
// assign debug_out4 = nPC;
|
||||||
|
// assign debug_out5 = ins;
|
||||||
|
// assign debug_out6 = IV;
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// instruction decoding
|
// instruction decoding
|
||||||
|
|
|
||||||
|
|
@ -1,93 +1,53 @@
|
||||||
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
// waveform generator module (PCM)
|
// waveform generator module (pulse wave or noise)
|
||||||
module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
|
module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
|
||||||
AMP_WIDTH=16, AMP_BIAS=32768) (
|
AMP_WIDTH=16, AMP_BIAS=32768) (
|
||||||
input wire clk,
|
input wire clk,
|
||||||
input wire reset,
|
input wire reset,
|
||||||
input wire [1:0] reg_sel,
|
input wire [1:0] reg_sel,
|
||||||
output wire [DATA_WIDTH-1:0] rd_data,
|
output wire [DATA_WIDTH-1:0] rd_data,
|
||||||
input wire [AMP_WIDTH-1:0] wr_data,
|
input wire [DATA_WIDTH-1:0] wr_data,
|
||||||
input wire rd_en,
|
input wire rd_en,
|
||||||
input wire wr_en,
|
input wire wr_en,
|
||||||
|
|
||||||
output wire [AMP_WIDTH-1:0] amp_val,
|
output wire [AMP_WIDTH-1:0] amp_val,
|
||||||
output wire running,
|
output wire running
|
||||||
output wire irq
|
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam TDRAU_REG_CTL = 0; /* control register */
|
localparam TDRAU_REG_CTL = 0; /* control register */
|
||||||
localparam TDRAU_REG_CLK = 1; /* clock divider register */
|
localparam TDRAU_REG_CLK = 1; /* clock divider register */
|
||||||
localparam TDRAU_REG_AMP = 2; /* amplitude (volume) register */
|
localparam TDRAU_REG_AMP = 2; /* amplitude (volume) register */
|
||||||
|
|
||||||
/* avoid warning about unconnected port */
|
// localparam LFSR_WIDTH = 18;
|
||||||
(* keep="soft" *) wire _unused = rd_en;
|
// localparam LFSR_TAP_IDX_1 = 17;
|
||||||
|
// localparam LFSR_TAP_IDX_2 = 10;
|
||||||
|
// localparam LFSR_INIT = 'h3CBE6;
|
||||||
|
|
||||||
|
localparam LFSR_WIDTH = 23;
|
||||||
|
localparam LFSR_INIT = 'h1;
|
||||||
|
|
||||||
reg channel_enable;
|
reg channel_enable;
|
||||||
reg [CLOCK_DIV_WIDTH-1:0] clock_div;
|
reg [CLOCK_DIV_WIDTH-1:0] clock_div;
|
||||||
reg [CLOCK_DIV_WIDTH-1:0] div_count;
|
reg [CLOCK_DIV_WIDTH-1:0] div_count;
|
||||||
reg amp_phase;
|
reg amp_phase;
|
||||||
|
reg [AMP_WIDTH-1:0] amp_start;
|
||||||
reg [AMP_WIDTH-1:0] amp_out;
|
reg [AMP_WIDTH-1:0] amp_out;
|
||||||
|
|
||||||
|
reg noise_enable;
|
||||||
|
reg [LFSR_WIDTH-1:0] lfsr;
|
||||||
|
wire [AMP_WIDTH-1:0] noise_out;
|
||||||
|
|
||||||
wire fifo_wr_en;
|
reg direct_amp_enable;
|
||||||
wire fifo_rd_en, fifo_full, fifo_empty;
|
|
||||||
wire [AMP_WIDTH-1:0] fifo_rd_data;
|
|
||||||
|
|
||||||
fifo #(.ADDR_WIDTH(4), .DATA_WIDTH(16)) sample_buf(
|
|
||||||
clk, reset,
|
|
||||||
fifo_wr_en, fifo_rd_en,
|
|
||||||
wr_data[AMP_WIDTH-1:0], fifo_rd_data,
|
|
||||||
fifo_full,
|
|
||||||
fifo_empty
|
|
||||||
);
|
|
||||||
|
|
||||||
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 [DATA_WIDTH-1:0] rd_data_buf;
|
|
||||||
assign rd_data = rd_data_buf;
|
|
||||||
|
|
||||||
|
//assign rd_data = {{DATA_WIDTH-8-CLOCK_DIV_WIDTH{1'b0}}, div_count, {7{1'b0}}, channel_enable};
|
||||||
|
assign rd_data = {8'b0, amp_start,
|
||||||
|
{6{1'b0}}, amp_phase, channel_enable};
|
||||||
assign amp_val = amp_out;
|
assign amp_val = amp_out;
|
||||||
assign running = channel_enable;
|
assign running = channel_enable;
|
||||||
|
|
||||||
wire ctl_reg_write = wr_en && (reg_sel == TDRAU_REG_CTL);
|
wire ctl_reg_write = wr_en && (reg_sel == TDRAU_REG_CTL);
|
||||||
|
|
||||||
/* 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};
|
|
||||||
end
|
|
||||||
|
|
||||||
/* irq signal to interrupt controller */
|
|
||||||
always @(posedge clk)
|
|
||||||
begin
|
|
||||||
if(reset)
|
|
||||||
irq_buf <= 0;
|
|
||||||
else
|
|
||||||
if(fifo_empty && irq_enable)
|
|
||||||
irq_buf <= 1;
|
|
||||||
else
|
|
||||||
irq_buf <= 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
/* interrupt enable flag */
|
|
||||||
always @(posedge clk)
|
|
||||||
begin
|
|
||||||
if(reset)
|
|
||||||
irq_enable <= 0;
|
|
||||||
else
|
|
||||||
if(ctl_reg_write)
|
|
||||||
irq_enable <= wr_data[4];
|
|
||||||
else
|
|
||||||
if(irq_buf)
|
|
||||||
irq_enable <= 0; // disable interrupts after an interrupt
|
|
||||||
end
|
|
||||||
|
|
||||||
/* channel enable flag */
|
/* channel enable flag */
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
begin
|
begin
|
||||||
|
|
@ -107,6 +67,16 @@ module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
|
||||||
clock_div <= wr_data;
|
clock_div <= wr_data;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
/* amplitude register */
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
if(reset)
|
||||||
|
amp_start <= 0;
|
||||||
|
else
|
||||||
|
if (wr_en && (reg_sel == TDRAU_REG_AMP))
|
||||||
|
amp_start <= wr_data;
|
||||||
|
end
|
||||||
|
|
||||||
/* divider counter */
|
/* divider counter */
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
begin
|
begin
|
||||||
|
|
@ -122,6 +92,43 @@ module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
|
||||||
div_count <= 1; // start cycle on next clock tick
|
div_count <= 1; // start cycle on next clock tick
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
/* noise enable flag */
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
if(reset)
|
||||||
|
noise_enable <= 0;
|
||||||
|
else if (ctl_reg_write)
|
||||||
|
noise_enable <= wr_data[1];
|
||||||
|
end
|
||||||
|
|
||||||
|
/* noise generator (Linear Feedback Shift Register) */
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
if (reset)
|
||||||
|
lfsr <= LFSR_INIT;
|
||||||
|
else
|
||||||
|
if (ctl_reg_write && wr_data[1])
|
||||||
|
lfsr <= LFSR_INIT;
|
||||||
|
else
|
||||||
|
if (channel_enable && noise_enable)
|
||||||
|
if (div_count == 0)
|
||||||
|
//lfsr <= { lfsr[LFSR_TAP_IDX_1] ^ lfsr[LFSR_TAP_IDX_2], lfsr[LFSR_WIDTH-1:1] };
|
||||||
|
// shift width and tap bits taken from https://github.com/jotego/jtopl
|
||||||
|
lfsr <= { lfsr[LFSR_WIDTH-2:0], lfsr[22] ^ lfsr[9] ^ lfsr[8] ^ lfsr[0]};
|
||||||
|
end
|
||||||
|
|
||||||
|
assign noise_out = lfsr[0] ? amp_start : ~amp_start;
|
||||||
|
|
||||||
|
/* direct amplitude enable flag */
|
||||||
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
|
if(reset)
|
||||||
|
direct_amp_enable <= 0;
|
||||||
|
else if (ctl_reg_write)
|
||||||
|
direct_amp_enable <= wr_data[2];
|
||||||
|
end
|
||||||
|
|
||||||
/* amplitude out */
|
/* amplitude out */
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
begin
|
begin
|
||||||
|
|
@ -135,7 +142,9 @@ module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
|
||||||
begin
|
begin
|
||||||
if (div_count == 0) // invert amplitude on clock tick
|
if (div_count == 0) // invert amplitude on clock tick
|
||||||
begin
|
begin
|
||||||
amp_out <= fifo_rd_data;
|
amp_out <= direct_amp_enable ? amp_start :
|
||||||
|
noise_enable ? noise_out :
|
||||||
|
amp_phase ? amp_start : ~amp_start;
|
||||||
amp_phase <= ~amp_phase;
|
amp_phase <= ~amp_phase;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -143,8 +152,8 @@ module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
|
||||||
amp_out <= AMP_BIAS;
|
amp_out <= AMP_BIAS;
|
||||||
|
|
||||||
// reset phase bit when enabling the channel
|
// reset phase bit when enabling the channel
|
||||||
if (ctl_reg_write && wr_data[0] && ~channel_enable)
|
if (ctl_reg_write && wr_data[0])
|
||||||
// when channel is being enabled, phase will be flipped on next tick
|
// when channel is enabled, phase will be flipped on next tick
|
||||||
// because div_count will become zero
|
// because div_count will become zero
|
||||||
amp_phase <= 1;
|
amp_phase <= 1;
|
||||||
end
|
end
|
||||||
|
|
@ -158,7 +167,7 @@ module tdraudio #(DATA_WIDTH=32) (
|
||||||
input wire [DATA_WIDTH-1:0] wr_data,
|
input wire [DATA_WIDTH-1:0] wr_data,
|
||||||
input wire rd_en,
|
input wire rd_en,
|
||||||
input wire wr_en,
|
input wire wr_en,
|
||||||
output wire irq_out,
|
|
||||||
output wire pdm_out,
|
output wire pdm_out,
|
||||||
output wire gain_sel,
|
output wire gain_sel,
|
||||||
output wire shutdown_n
|
output wire shutdown_n
|
||||||
|
|
@ -166,21 +175,14 @@ module tdraudio #(DATA_WIDTH=32) (
|
||||||
|
|
||||||
localparam CLOCK_DIV_WIDTH = 22;
|
localparam CLOCK_DIV_WIDTH = 22;
|
||||||
localparam AMP_WIDTH = 16;
|
localparam AMP_WIDTH = 16;
|
||||||
localparam AMP_BIAS = 32768;
|
|
||||||
localparam DAC_WIDTH = 18;
|
localparam DAC_WIDTH = 18;
|
||||||
|
|
||||||
/* avoid warning about unconnected port */
|
|
||||||
(* keep="soft" *) wire [DATA_WIDTH-1:AMP_WIDTH] _unused = wr_data[DATA_WIDTH-1:AMP_WIDTH];
|
|
||||||
|
|
||||||
wire [4:0] chan_sel = io_addr[6:2];
|
wire [4:0] chan_sel = io_addr[6:2];
|
||||||
wire [1:0] reg_sel = io_addr[1:0];
|
wire [1:0] reg_sel = io_addr[1:0];
|
||||||
|
|
||||||
wire [AMP_WIDTH-1:0] amp_wr_data = wr_data[AMP_WIDTH-1:0];
|
|
||||||
|
|
||||||
wire [AMP_WIDTH-1:0] chan0_amp;
|
wire [AMP_WIDTH-1:0] chan0_amp;
|
||||||
wire [DATA_WIDTH-1:0] chan0_rd_data;
|
wire [DATA_WIDTH-1:0] chan0_rd_data;
|
||||||
wire chan0_running;
|
wire chan0_running;
|
||||||
wire chan0_irq;
|
|
||||||
wire chan0_sel = chan_sel == 5'd0;
|
wire chan0_sel = chan_sel == 5'd0;
|
||||||
wire chan0_rd_en = chan0_sel && rd_en;
|
wire chan0_rd_en = chan0_sel && rd_en;
|
||||||
wire chan0_wr_en = chan0_sel && wr_en;
|
wire chan0_wr_en = chan0_sel && wr_en;
|
||||||
|
|
@ -188,7 +190,6 @@ module tdraudio #(DATA_WIDTH=32) (
|
||||||
wire [AMP_WIDTH-1:0] chan1_amp;
|
wire [AMP_WIDTH-1:0] chan1_amp;
|
||||||
wire [DATA_WIDTH-1:0] chan1_rd_data;
|
wire [DATA_WIDTH-1:0] chan1_rd_data;
|
||||||
wire chan1_running;
|
wire chan1_running;
|
||||||
wire chan1_irq;
|
|
||||||
wire chan1_sel = chan_sel == 5'd1;
|
wire chan1_sel = chan_sel == 5'd1;
|
||||||
wire chan1_rd_en = chan1_sel && rd_en;
|
wire chan1_rd_en = chan1_sel && rd_en;
|
||||||
wire chan1_wr_en = chan1_sel && wr_en;
|
wire chan1_wr_en = chan1_sel && wr_en;
|
||||||
|
|
@ -196,7 +197,6 @@ module tdraudio #(DATA_WIDTH=32) (
|
||||||
wire [AMP_WIDTH-1:0] chan2_amp;
|
wire [AMP_WIDTH-1:0] chan2_amp;
|
||||||
wire [DATA_WIDTH-1:0] chan2_rd_data;
|
wire [DATA_WIDTH-1:0] chan2_rd_data;
|
||||||
wire chan2_running;
|
wire chan2_running;
|
||||||
wire chan2_irq;
|
|
||||||
wire chan2_sel = chan_sel == 5'd2;
|
wire chan2_sel = chan_sel == 5'd2;
|
||||||
wire chan2_rd_en = chan2_sel && rd_en;
|
wire chan2_rd_en = chan2_sel && rd_en;
|
||||||
wire chan2_wr_en = chan2_sel && wr_en;
|
wire chan2_wr_en = chan2_sel && wr_en;
|
||||||
|
|
@ -204,13 +204,14 @@ module tdraudio #(DATA_WIDTH=32) (
|
||||||
wire [AMP_WIDTH-1:0] chan3_amp;
|
wire [AMP_WIDTH-1:0] chan3_amp;
|
||||||
wire [DATA_WIDTH-1:0] chan3_rd_data;
|
wire [DATA_WIDTH-1:0] chan3_rd_data;
|
||||||
wire chan3_running;
|
wire chan3_running;
|
||||||
wire chan3_irq;
|
|
||||||
wire chan3_sel = chan_sel == 5'd3;
|
wire chan3_sel = chan_sel == 5'd3;
|
||||||
wire chan3_rd_en = chan3_sel && rd_en;
|
wire chan3_rd_en = chan3_sel && rd_en;
|
||||||
wire chan3_wr_en = chan3_sel && wr_en;
|
wire chan3_wr_en = chan3_sel && wr_en;
|
||||||
|
|
||||||
wire running = chan0_running || chan1_running || chan2_running || chan3_running;
|
wire running = chan0_running || chan1_running || chan2_running || chan3_running;
|
||||||
|
|
||||||
|
reg was_running;
|
||||||
|
|
||||||
assign rd_data = chan0_sel ? chan0_rd_data :
|
assign rd_data = chan0_sel ? chan0_rd_data :
|
||||||
chan1_sel ? chan1_rd_data :
|
chan1_sel ? chan1_rd_data :
|
||||||
chan2_sel ? chan2_rd_data :
|
chan2_sel ? chan2_rd_data :
|
||||||
|
|
@ -218,40 +219,40 @@ module tdraudio #(DATA_WIDTH=32) (
|
||||||
{DATA_WIDTH{1'b1}};
|
{DATA_WIDTH{1'b1}};
|
||||||
|
|
||||||
wavegen chan0(clk, reset, reg_sel,
|
wavegen chan0(clk, reset, reg_sel,
|
||||||
chan0_rd_data, amp_wr_data,
|
chan0_rd_data, wr_data,
|
||||||
chan0_rd_en, chan0_wr_en,
|
chan0_rd_en, chan0_wr_en,
|
||||||
chan0_amp,
|
chan0_amp, chan0_running);
|
||||||
chan0_running, chan0_irq);
|
|
||||||
|
|
||||||
wavegen chan1(clk, reset, reg_sel,
|
wavegen chan1(clk, reset, reg_sel,
|
||||||
chan1_rd_data, amp_wr_data,
|
chan1_rd_data, wr_data,
|
||||||
chan1_rd_en, chan1_wr_en,
|
chan1_rd_en, chan1_wr_en,
|
||||||
chan1_amp,
|
chan1_amp, chan1_running);
|
||||||
chan1_running, chan1_irq);
|
|
||||||
|
|
||||||
wavegen chan2(clk, reset, reg_sel,
|
wavegen chan2(clk, reset, reg_sel,
|
||||||
chan2_rd_data, amp_wr_data,
|
chan2_rd_data, wr_data,
|
||||||
chan2_rd_en, chan2_wr_en,
|
chan2_rd_en, chan2_wr_en,
|
||||||
chan2_amp,
|
chan2_amp, chan2_running);
|
||||||
chan2_irq, chan2_running);
|
|
||||||
|
|
||||||
wavegen chan3(clk, reset, reg_sel,
|
wavegen chan3(clk, reset, reg_sel,
|
||||||
chan3_rd_data, amp_wr_data,
|
chan3_rd_data, wr_data,
|
||||||
chan3_rd_en, chan3_wr_en,
|
chan3_rd_en, chan3_wr_en,
|
||||||
chan3_amp,
|
chan3_amp, chan3_running);
|
||||||
chan3_running, chan3_irq);
|
|
||||||
|
|
||||||
reg [DAC_WIDTH:0] deltasigma_acc; // one extra bit
|
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
|
wire [DAC_WIDTH:0] amp_sum = chan0_amp + chan1_amp + chan2_amp + chan3_amp; // also one overflow bit here
|
||||||
|
//wire [AMP_WIDTH-1:0] amp_sum_scaled = amp_sum[DAC_WIDTH-2:2]; // shifted right to scale down
|
||||||
assign gain_sel = 1; // gain select: 0 -> 12dB, 1 -> 6dB
|
assign gain_sel = 1; // gain select: 0 -> 12dB, 1 -> 6dB
|
||||||
|
|
||||||
// assign shutdown_n = running;
|
assign shutdown_n = running;
|
||||||
assign shutdown_n = 1; /* don't enable shutdown mode, it creates a mains hum */
|
|
||||||
|
|
||||||
reg irq_out_buf;
|
/* detect shutdown */
|
||||||
assign irq_out = irq_out_buf;
|
always @(posedge clk)
|
||||||
|
begin
|
||||||
always @(posedge clk) irq_out_buf <= chan0_irq || chan1_irq || chan2_irq || chan3_irq;
|
if (reset)
|
||||||
|
was_running <= 0;
|
||||||
|
else
|
||||||
|
was_running <= running;
|
||||||
|
end
|
||||||
|
|
||||||
/* delta-sigma DAC */
|
/* delta-sigma DAC */
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
|
|
@ -259,10 +260,11 @@ module tdraudio #(DATA_WIDTH=32) (
|
||||||
if(reset)
|
if(reset)
|
||||||
deltasigma_acc <= 0;
|
deltasigma_acc <= 0;
|
||||||
else
|
else
|
||||||
// if (running)
|
if (running)
|
||||||
deltasigma_acc <= deltasigma_acc[DAC_WIDTH-1:0] + amp_sum;
|
deltasigma_acc <= deltasigma_acc[DAC_WIDTH-1:0] + amp_sum;
|
||||||
// else
|
else
|
||||||
// deltasigma_acc <= deltasigma_acc[DAC_WIDTH-1:0] + (4*AMP_BIAS);
|
if (!running && was_running) // clear accumulator on shutdown
|
||||||
|
deltasigma_acc <= 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
/* 1-bit audio output */
|
/* 1-bit audio output */
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,9 @@
|
||||||
module top(
|
module top(
|
||||||
input wire clk,
|
input wire clk,
|
||||||
input wire rst,
|
input wire rst,
|
||||||
|
input wire btn0,
|
||||||
|
input wire sw0,
|
||||||
|
input wire sw1,
|
||||||
output wire led0,
|
output wire led0,
|
||||||
output wire led1,
|
output wire led1,
|
||||||
output wire led2,
|
output wire led2,
|
||||||
|
|
@ -225,21 +228,19 @@ module top(
|
||||||
assign uart_tx_data = mem_write_data[7:0];
|
assign uart_tx_data = mem_write_data[7:0];
|
||||||
assign uart_rd_data = { {WIDTH-10{1'b1}}, uart_rx_avail, uart_tx_busy, uart_rx_data };
|
assign uart_rd_data = { {WIDTH-10{1'b1}}, uart_rx_avail, uart_tx_busy, uart_rx_data };
|
||||||
|
|
||||||
wire audio_irq;
|
// interrupt controller
|
||||||
|
reg timer_tick;
|
||||||
|
reg[23:0] tick_count;
|
||||||
|
wire [1:0] irq_in = { timer_tick, uart_rx_avail };
|
||||||
|
wire [1:0] irqc_rd_data0;
|
||||||
|
wire [WIDTH-1:0] irqc_rd_data = { tick_count, 6'b0, irqc_rd_data0 };
|
||||||
|
wire irqc_seten = mem_write_data[7];
|
||||||
|
wire irqc_cs = io_enable && (io_slot == 3);
|
||||||
|
|
||||||
buart #(.CLKFREQ(`clkfreq)) uart0(`clock, rst,
|
|
||||||
uart_baud,
|
|
||||||
uart_txd_in, uart_rxd_out,
|
|
||||||
uart_rx_clear, uart_tx_en,
|
|
||||||
uart_rx_avail, uart_tx_busy,
|
|
||||||
uart_tx_data, uart_rx_data);
|
|
||||||
|
|
||||||
// audio controller
|
|
||||||
`ifdef ENABLE_TDRAUDIO
|
`ifdef ENABLE_TDRAUDIO
|
||||||
wire [WIDTH-1:0] tdraudio_wr_data;
|
wire [WIDTH-1:0] tdraudio_wr_data;
|
||||||
wire [WIDTH-1:0] tdraudio_rd_data;
|
wire [WIDTH-1:0] tdraudio_rd_data;
|
||||||
wire tdraudio_rd_en, tdraudio_wr_en;
|
wire tdraudio_rd_en, tdraudio_wr_en;
|
||||||
wire tdraudio_irq;
|
|
||||||
|
|
||||||
wire tdraudio_cs_en = io_enable && (io_slot == 4);
|
wire tdraudio_cs_en = io_enable && (io_slot == 4);
|
||||||
assign tdraudio_rd_en = tdraudio_cs_en && mem_read_enable;
|
assign tdraudio_rd_en = tdraudio_cs_en && mem_read_enable;
|
||||||
|
|
@ -252,20 +253,9 @@ module top(
|
||||||
tdraudio_wr_data,
|
tdraudio_wr_data,
|
||||||
tdraudio_rd_en,
|
tdraudio_rd_en,
|
||||||
tdraudio_wr_en,
|
tdraudio_wr_en,
|
||||||
tdraudio_irq,
|
|
||||||
amp2_ain, amp2_gain, amp2_shutdown_n);
|
amp2_ain, amp2_gain, amp2_shutdown_n);
|
||||||
assign audio_irq = tdraudio_irq;
|
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
// interrupt controller
|
|
||||||
reg timer_tick;
|
|
||||||
reg[23:0] tick_count;
|
|
||||||
wire [2:0] irq_in = { audio_irq, timer_tick, uart_rx_avail };
|
|
||||||
wire [2:0] irqc_rd_data0;
|
|
||||||
wire [WIDTH-1:0] irqc_rd_data = { tick_count, 5'b0, irqc_rd_data0 };
|
|
||||||
wire irqc_seten = mem_write_data[7];
|
|
||||||
wire irqc_cs = io_enable && (io_slot == 3);
|
|
||||||
|
|
||||||
assign io_rd_data = (io_slot == 0) ? uart_rd_data :
|
assign io_rd_data = (io_slot == 0) ? uart_rd_data :
|
||||||
`ifdef ENABLE_MICROSD
|
`ifdef ENABLE_MICROSD
|
||||||
(io_slot == 1) ? spi_rd_data :
|
(io_slot == 1) ? spi_rd_data :
|
||||||
|
|
@ -279,6 +269,13 @@ module top(
|
||||||
`endif
|
`endif
|
||||||
-1;
|
-1;
|
||||||
|
|
||||||
|
buart #(.CLKFREQ(`clkfreq)) uart0(`clock, rst,
|
||||||
|
uart_baud,
|
||||||
|
uart_txd_in, uart_rxd_out,
|
||||||
|
uart_rx_clear, uart_tx_en,
|
||||||
|
uart_rx_avail, uart_tx_busy,
|
||||||
|
uart_tx_data, uart_rx_data);
|
||||||
|
|
||||||
// CPU -----------------------------------------------------------------
|
// CPU -----------------------------------------------------------------
|
||||||
stackcpu cpu0(.clk(`clock), .rst(rst), .irq(irq),
|
stackcpu cpu0(.clk(`clock), .rst(rst), .irq(irq),
|
||||||
.addr(mem_addr),
|
.addr(mem_addr),
|
||||||
|
|
@ -286,7 +283,7 @@ module top(
|
||||||
.read_ins(dram_read_ins),
|
.read_ins(dram_read_ins),
|
||||||
.data_out(mem_write_data), .write_enable(mem_write_enable),
|
.data_out(mem_write_data), .write_enable(mem_write_enable),
|
||||||
.mem_wait(mem_wait),
|
.mem_wait(mem_wait),
|
||||||
.debug1(led1), .debug2(led2), .debug3(led3));
|
.led1(led1), .led2(led2), .led3(led3));
|
||||||
|
|
||||||
// Interrupt Controller
|
// Interrupt Controller
|
||||||
irqctrl irqctrl0(`clock, irq_in, irqc_cs, mem_write_enable,
|
irqctrl irqctrl0(`clock, irq_in, irqc_cs, mem_write_enable,
|
||||||
|
|
|
||||||
|
|
@ -378,18 +378,26 @@
|
||||||
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
|
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
|
||||||
<RQSFiles/>
|
<RQSFiles/>
|
||||||
</Run>
|
</Run>
|
||||||
<Run Id="impl_1" Type="Ft2:EntireDesign" Part="xc7a35ticsg324-1L" ConstrsSet="constrs_1" Description="Default settings for Implementation." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/impl_1" SynthRun="synth_1" IncludeInArchive="true" IsChild="false" GenFullBitstream="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/impl_1" LaunchOptions="-jobs 6 " AutoRQSDir="$PSRCDIR/utils_1/imports/impl_1" ParallelReportGen="true">
|
<Run Id="impl_1" Type="Ft2:EntireDesign" Part="xc7a35ticsg324-1L" ConstrsSet="constrs_1" Description="Uses multiple algorithms for optimization, placement, and routing to get potentially better results." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/impl_1" SynthRun="synth_1" IncludeInArchive="true" IsChild="false" GenFullBitstream="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/impl_1" LaunchOptions="-jobs 6 " AutoRQSDir="$PSRCDIR/utils_1/imports/impl_1" ParallelReportGen="true">
|
||||||
<Strategy Version="1" Minor="2">
|
<Strategy Version="1" Minor="2">
|
||||||
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2024">
|
<StratHandle Name="Performance_Explore" Flow="Vivado Implementation 2024">
|
||||||
<Desc>Default settings for Implementation.</Desc>
|
<Desc>Uses multiple algorithms for optimization, placement, and routing to get potentially better results.</Desc>
|
||||||
</StratHandle>
|
</StratHandle>
|
||||||
<Step Id="init_design"/>
|
<Step Id="init_design"/>
|
||||||
<Step Id="opt_design"/>
|
<Step Id="opt_design">
|
||||||
|
<Option Id="Directive">0</Option>
|
||||||
|
</Step>
|
||||||
<Step Id="power_opt_design"/>
|
<Step Id="power_opt_design"/>
|
||||||
<Step Id="place_design"/>
|
<Step Id="place_design">
|
||||||
|
<Option Id="Directive">0</Option>
|
||||||
|
</Step>
|
||||||
<Step Id="post_place_power_opt_design"/>
|
<Step Id="post_place_power_opt_design"/>
|
||||||
<Step Id="phys_opt_design"/>
|
<Step Id="phys_opt_design">
|
||||||
<Step Id="route_design"/>
|
<Option Id="Directive">0</Option>
|
||||||
|
</Step>
|
||||||
|
<Step Id="route_design">
|
||||||
|
<Option Id="Directive">0</Option>
|
||||||
|
</Step>
|
||||||
<Step Id="post_route_phys_opt_design"/>
|
<Step Id="post_route_phys_opt_design"/>
|
||||||
<Step Id="write_bitstream">
|
<Step Id="write_bitstream">
|
||||||
<Option Id="BinFile">1</Option>
|
<Option Id="BinFile">1</Option>
|
||||||
|
|
|
||||||
151
utils/serload.py
151
utils/serload.py
|
|
@ -16,7 +16,6 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
|
||||||
import serial
|
import serial
|
||||||
import time
|
import time
|
||||||
import random
|
import random
|
||||||
|
|
@ -42,6 +41,30 @@ def get_default_device():
|
||||||
return '/dev/ttyUSB1'
|
return '/dev/ttyUSB1'
|
||||||
|
|
||||||
|
|
||||||
|
def serwrite_slow(databytes, ser):
|
||||||
|
total = len(data)
|
||||||
|
count = 1
|
||||||
|
for d in data:
|
||||||
|
sys.stdout.write("writing {0:02x} {1:04d}/{2:04d}\r".format(ord(d), count, total))
|
||||||
|
ser.write(bytes(d,"utf8"))
|
||||||
|
count += 1
|
||||||
|
time.sleep(0.020)
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
def serwrite(datafile, ser):
|
||||||
|
with open(datafile) as f:
|
||||||
|
data = f.read()
|
||||||
|
total = len(data)
|
||||||
|
count = 1
|
||||||
|
for d in data:
|
||||||
|
sys.stdout.write("writing {0:02x} {1:04d}/{2:04d}\r".format(ord(d), count, total))
|
||||||
|
ser.write(bytes(d,"utf8"))
|
||||||
|
count += 1
|
||||||
|
time.sleep(0.020)
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
def checksum(databytes):
|
def checksum(databytes):
|
||||||
i = 0
|
i = 0
|
||||||
cksum = 0
|
cksum = 0
|
||||||
|
|
@ -62,26 +85,10 @@ def sendchar(char, ser):
|
||||||
ser.write(char.to_bytes(1, 'big'))
|
ser.write(char.to_bytes(1, 'big'))
|
||||||
|
|
||||||
|
|
||||||
def sendcommand(ser, cmd=b'L', verbose=False):
|
def sendcommand(ser, cmd=b'L'):
|
||||||
verbose = True
|
|
||||||
ser.write(cmd)
|
ser.write(cmd)
|
||||||
resp = ser.read_until()
|
resp = ser.read_until()
|
||||||
if verbose:
|
print(cmd,"sent, response:", str(resp))
|
||||||
print(cmd,"sent, response:", str(resp))
|
|
||||||
return resp
|
|
||||||
|
|
||||||
|
|
||||||
# send command and wait for echo
|
|
||||||
def commandwait(ser, cmd):
|
|
||||||
resp = sendcommand(ser, cmd, verbose=False)
|
|
||||||
if len(resp) == 0:
|
|
||||||
print("timeout sending '{}' command".format(cmd))
|
|
||||||
return None
|
|
||||||
|
|
||||||
if resp != bytearray(cmd + b"\r\n"):
|
|
||||||
print("invalid response to '{}' command".format(cmd))
|
|
||||||
return None
|
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -146,8 +153,6 @@ def serload_bin(datafile, ser):
|
||||||
|
|
||||||
data += bytearray(pad)
|
data += bytearray(pad)
|
||||||
|
|
||||||
print("{} total blocks".format((len(data) + blocksize - 1) // blocksize))
|
|
||||||
|
|
||||||
if not send_size_header(ser, filesize):
|
if not send_size_header(ser, filesize):
|
||||||
print("Error sending size header.")
|
print("Error sending size header.")
|
||||||
return
|
return
|
||||||
|
|
@ -274,8 +279,18 @@ def serdownload(fname, ser):
|
||||||
|
|
||||||
def mput(filenames, ser):
|
def mput(filenames, ser):
|
||||||
for f in filenames:
|
for f in filenames:
|
||||||
resp = set_filename(f, ser)
|
f_encoded = f.encode('utf8')
|
||||||
if resp is None:
|
print("Setting filename", f)
|
||||||
|
resp = sendcommand(ser, b'S')
|
||||||
|
if len(resp) == 0:
|
||||||
|
print("timeout sending 'S' command")
|
||||||
|
return
|
||||||
|
if resp != b'S\r\n' and resp != b'> S\r\n':
|
||||||
|
print("unrecognized response to 'S' command, aborting")
|
||||||
|
return
|
||||||
|
resp = sendcommand(ser, f_encoded + b'\r')
|
||||||
|
if not f_encoded in resp:
|
||||||
|
print("unrecognized response to filename, aborting")
|
||||||
return
|
return
|
||||||
serload_bin(f, ser)
|
serload_bin(f, ser)
|
||||||
|
|
||||||
|
|
@ -284,92 +299,12 @@ def mput(filenames, ser):
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
||||||
|
|
||||||
def set_filename(f, ser):
|
|
||||||
f_encoded = f.encode('utf8')
|
|
||||||
print("Setting filename", f)
|
|
||||||
resp = commandwait(ser, b'S')
|
|
||||||
if resp is None:
|
|
||||||
return None
|
|
||||||
resp = sendcommand(ser, f_encoded + b'\r')
|
|
||||||
if not f_encoded in resp:
|
|
||||||
print("unrecognized response to filename, aborting")
|
|
||||||
return None
|
|
||||||
return resp
|
|
||||||
|
|
||||||
|
|
||||||
def getnamedfile(filename, ser):
|
|
||||||
resp = set_filename(filename, ser)
|
|
||||||
if resp is None:
|
|
||||||
return None
|
|
||||||
serdownload(filename, ser)
|
|
||||||
|
|
||||||
|
|
||||||
def putnamedfile(filename, ser):
|
|
||||||
resp = set_filename(filename, ser)
|
|
||||||
if resp is None:
|
|
||||||
return None
|
|
||||||
serload_bin(filename, ser)
|
|
||||||
print("Remote status:")
|
|
||||||
showdata(ser)
|
|
||||||
|
|
||||||
|
|
||||||
def showdata(ser):
|
|
||||||
|
|
||||||
promptseen = False
|
|
||||||
|
|
||||||
while not promptseen:
|
|
||||||
c = ser.read(1)
|
|
||||||
if c == b'>':
|
|
||||||
promptseen = True
|
|
||||||
else:
|
|
||||||
print(c.decode('utf8'), end='')
|
|
||||||
rest = ser.read(1)
|
|
||||||
|
|
||||||
|
|
||||||
def localdir():
|
|
||||||
result = os.walk(".")
|
|
||||||
for dirpath, dirnames, filenames in os.walk("."):
|
|
||||||
for f in filenames:
|
|
||||||
print(f)
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
def interactive(ser):
|
|
||||||
done = False
|
|
||||||
while not done:
|
|
||||||
args = input("> ").strip().split()
|
|
||||||
if len(args) > 0:
|
|
||||||
cmd = args[0]
|
|
||||||
args.pop(0)
|
|
||||||
if cmd == 'dir':
|
|
||||||
if commandwait(ser, b'Y') is None:
|
|
||||||
return
|
|
||||||
showdata(ser)
|
|
||||||
elif cmd == 'get':
|
|
||||||
if len(args) > 1:
|
|
||||||
print("exactly one argument required (filename)")
|
|
||||||
else:
|
|
||||||
getnamedfile(args[0], ser)
|
|
||||||
elif cmd == 'put':
|
|
||||||
if len(args) > 1:
|
|
||||||
print("exactly one argument required (filename)")
|
|
||||||
else:
|
|
||||||
putnamedfile(args[0], ser)
|
|
||||||
elif cmd == 'ldir':
|
|
||||||
if len(args) > 0:
|
|
||||||
print("superfluous argument")
|
|
||||||
else:
|
|
||||||
localdir()
|
|
||||||
else:
|
|
||||||
print("Unknown command. Valid commands are: dir get ldir put")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
argparser = argparse.ArgumentParser(
|
argparser = argparse.ArgumentParser(
|
||||||
description='transfer files from/to the Tridora-CPU')
|
description='transfer files from/to the Tridora-CPU')
|
||||||
argparser.add_argument('-d', '--device', help='serial device', default=get_default_device())
|
argparser.add_argument('-d', '--device', help='serial device', default=get_default_device())
|
||||||
argparser.add_argument('command', choices=['get', 'put', 'mput', 'interactive'])
|
argparser.add_argument('command', choices=['get', 'put', 'mput'])
|
||||||
argparser.add_argument('filename', nargs='*')
|
argparser.add_argument('filename', nargs='+')
|
||||||
args = argparser.parse_args()
|
args = argparser.parse_args()
|
||||||
|
|
||||||
cmd = args.command
|
cmd = args.command
|
||||||
|
|
@ -384,10 +319,8 @@ if __name__ == "__main__":
|
||||||
serload_bin(filenames[0], ser)
|
serload_bin(filenames[0], ser)
|
||||||
elif cmd == 'mput':
|
elif cmd == 'mput':
|
||||||
mput(filenames, ser)
|
mput(filenames, ser)
|
||||||
elif cmd == 'interactive':
|
|
||||||
interactive(ser)
|
|
||||||
else:
|
else:
|
||||||
print("should not get here")
|
print("should not get here")
|
||||||
|
|
||||||
#if cmd is not None:
|
if cmd is not None:
|
||||||
# ser.close()
|
ser.close()
|
||||||
|
|
|
||||||
|
|
@ -538,9 +538,6 @@ def create_image_with_stuff(imgfile):
|
||||||
slotnr = putfile("../progs/recover.prog", None , f, part, partstart, slotnr)
|
slotnr = putfile("../progs/recover.prog", None , f, part, partstart, slotnr)
|
||||||
slotnr = putfile("../progs/changemem.prog", None , f, part, partstart, slotnr)
|
slotnr = putfile("../progs/changemem.prog", None , f, part, partstart, slotnr)
|
||||||
|
|
||||||
slotnr = putfile("../lib/pcmaudio.s", None , f, part, partstart, slotnr)
|
|
||||||
slotnr = putfile("../lib/pcmaudio.inc", None , f, part, partstart, slotnr)
|
|
||||||
|
|
||||||
listdir(f, part)
|
listdir(f, part)
|
||||||
|
|
||||||
# third partition
|
# third partition
|
||||||
|
|
@ -603,8 +600,6 @@ def create_image_with_stuff(imgfile):
|
||||||
|
|
||||||
slotnr = putfile("../examples/lines.pas", None , f, part, partstart, slotnr)
|
slotnr = putfile("../examples/lines.pas", None , f, part, partstart, slotnr)
|
||||||
|
|
||||||
slotnr = putfile("../examples/pcmtest2.pas", None , f, part, partstart, slotnr)
|
|
||||||
|
|
||||||
slotnr = putfile("../examples/pictviewer.pas", None , f, part, partstart, slotnr)
|
slotnr = putfile("../examples/pictviewer.pas", None , f, part, partstart, slotnr)
|
||||||
slotnr = putfile("../examples/Toco_Toucan.pict", None , f, part, partstart, slotnr)
|
slotnr = putfile("../examples/Toco_Toucan.pict", None , f, part, partstart, slotnr)
|
||||||
slotnr = putfile("../examples/shinkansen.pict", None , f, part, partstart, slotnr)
|
slotnr = putfile("../examples/shinkansen.pict", None , f, part, partstart, slotnr)
|
||||||
|
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
import sys
|
|
||||||
import random, struct
|
|
||||||
import wave
|
|
||||||
|
|
||||||
freq = 16000
|
|
||||||
BIAS = 32768
|
|
||||||
def convert(srcpath, destpath):
|
|
||||||
outdata = bytearray()
|
|
||||||
with wave.open(srcpath, mode="rb") as f:
|
|
||||||
params = f.getparams()
|
|
||||||
print(params.nchannels, params.sampwidth, params.framerate)
|
|
||||||
|
|
||||||
frames = f.readframes(2*1024*1024)
|
|
||||||
for i in range(0, len(frames), 2):
|
|
||||||
v = int.from_bytes(frames[i:i+2], "little", signed=True)
|
|
||||||
v += BIAS
|
|
||||||
hi = (v & 0xFF00) >> 8
|
|
||||||
lo = (v & 0x00FF)
|
|
||||||
outdata.append(hi)
|
|
||||||
outdata.append(lo)
|
|
||||||
|
|
||||||
with open(destpath, mode="wb") as f:
|
|
||||||
f.write(outdata)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
sourcefilename = sys.argv[1]
|
|
||||||
destfilename = sys.argv[2]
|
|
||||||
convert(sourcefilename, destfilename)
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue