sound chips added to pld file and added sn76489 test

This commit is contained in:
Joppe Blondel
2026-10-17 13:30:54 +02:00
parent 55012d8b7b
commit ebf409745d
20 changed files with 2972 additions and 264 deletions
+9 -3
View File
@@ -23,19 +23,25 @@ $(BUILDDIR)/bios.bin: bios.asm tape.asm $(BUILDDIR)/memory.inc
basic:
$(MAKE) -C apps/basic $(or $(MAKECMDGOALS),all) --no-print-directory
sn76489:
$(MAKE) -C apps/sn76489 $(or $(MAKECMDGOALS),all) --no-print-directory
$(BUILDDIR)/memory.inc: memory.mk
@mkdir -p $(@D)
@awk 'BEGIN { print "; Generated from rom_layout.mk; do not edit." } \
/^[A-Z][A-Z0-9_]*[[:space:]]*:=[[:space:]]*/ { print $$1 " .equ " $$3 }' $< > $@
$(BUILDDIR)/rom.bin: $(BUILDDIR)/bios.bin basic
$(BUILDDIR)/rom.bin: $(BUILDDIR)/bios.bin basic sn76489
echo "bios: $(shell wc -c < $(BUILDDIR)/bios.bin) / $$(($(BIOS_ROM_SIZE)+0))"
echo "basic: $(shell wc -c < $(BUILDDIR)/basic.bin) / $$(($(BASIC_ROM_SIZE)+0))"
echo "sn76489: $(shell wc -c < $(BUILDDIR)/sn76489.bin) / $$(($(SN76489_ROM_SIZE)+0))"
objcopy --pad-to=$$(($(BIOS_ROM_START)+$(BIOS_ROM_SIZE))) \
-I binary $(BUILDDIR)/bios.bin -O binary $(BUILDDIR)/bios_padded.bin
objcopy --pad-to=$(BASIC_ROM_SIZE) \
-I binary $(BUILDDIR)/basic.bin -O binary $(BUILDDIR)/basic_padded.bin
cat $(BUILDDIR)/bios_padded.bin $(BUILDDIR)/basic_padded.bin > $(BUILDDIR)/rom.bin
objcopy --pad-to=$(SN76489_ROM_SIZE) \
-I binary $(BUILDDIR)/sn76489.bin -O binary $(BUILDDIR)/sn76489_padded.bin
cat $(BUILDDIR)/bios_padded.bin $(BUILDDIR)/basic_padded.bin $(BUILDDIR)/sn76489_padded.bin > $(BUILDDIR)/rom.bin
.PHONY: $(TOPTARGETS) $(SUBDIRS) basic
.PHONY: $(TOPTARGETS) $(SUBDIRS) basic sn76489
+22
View File
@@ -0,0 +1,22 @@
.SILENT:
ASM := zasm
ASMFLAGS := -w -b
BUILDDIR := ../../build
TOPTARGETS := all clean
$(TOPTARGETS): $(SUBDIRS)
all: $(BUILDDIR) $(BUILDDIR)/sn76489.bin
clean:
rm -rf $(BUILDDIR)
$(BUILDDIR):
mkdir -p $(BUILDDIR)
$(BUILDDIR)/sn76489.bin: main.asm psglib_zasm.asm $(BUILDDIR)/memory.inc
echo '>$<'
$(ASM) $(ASMFLAGS) $< $@
.PHONY: $(TOPTARGETS) $(SUBDIRS)
+89
View File
@@ -0,0 +1,89 @@
#include "../../build/memory.inc"
#include "../../bios.inc"
#include "../../hardware.inc"
CTC_BASE .equ 020h
CTC_CHANNEL_0 .equ CTC_BASE+000h
CTC_CHANNEL_1 .equ CTC_BASE+001h
CTC_CHANNEL_2 .equ CTC_BASE+002h
CTC_CHANNEL_3 .equ CTC_BASE+003h
RAM_TOP .equ 0xbfff
; workspace variables here vv
; ------------------------ ^^
SAVED_SP .equ RAM_TOP-0x02 ; word
STACK_TOP .equ RAM_TOP-0x100
; -------------------------------------------------------
; Entry
; -------------------------------------------------------
.org SN76489_ROM_START
push bc
push de
push hl
ld hl, 0
add hl, sp ; get sp
ld (SAVED_SP), hl ; save sp for later
ld hl, STACK_TOP
ld sp, hl ; use own stack
ld hl,str_header
call BIOS_PUTS
ld hl,SHARED_MEM_START+042h
ld bc, ctc_interrupt ; install own ctc isr
ld (hl), bc
di
call PSGInit ; Initialize psglib
ld a,10100111b ; interrupts enabled
; timer mode
; prescaler 256
; automatic trigger
; time constant follows
; reset
; control word
out (CTC_CHANNEL_1), a
ld a,78 ; 50Hz
out (CTC_CHANNEL_1), a
; music must be loaded from 8000
ld hl, 0x8000
call PSGPlayNoRepeat
ei
exit:
ld hl, (SAVED_SP)
ld sp, hl ; restore original stack
pop hl
pop de
pop bc
ret
; -------------------------------------------------------
; CTC CHAN 1 interrupt handler
; -------------------------------------------------------
ctc_interrupt:
push af
push bc
push de
push hl
call PSGFrame
pop hl
pop de
pop bc
pop af
reti
; -------------------------------------------------------
; Strings
; -------------------------------------------------------
str_header: .db "SN76489 test",00dh,00ah,000h
#include "psglib_zasm.asm"
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+22
View File
@@ -145,6 +145,7 @@ init:
ei
call tape_init
call psg_silence
; Print header message
ld hl,msg_header
@@ -272,6 +273,13 @@ release_daisy_chain:
ctc_uart_init:
; Reset CTC channels
ld a,003h
; A channel may still be waiting for a time constant after a warm boot.
; In that state the first byte is consumed as the constant, so send the
; reset control word again to guarantee the unused channel is disabled.
out (CTC_CHANNEL_0),a
out (CTC_CHANNEL_1),a
out (CTC_CHANNEL_2),a
out (CTC_CHANNEL_3),a
out (CTC_CHANNEL_0),a
out (CTC_CHANNEL_1),a
out (CTC_CHANNEL_2),a
@@ -557,6 +565,20 @@ delay_ms:
jp nz,1$ ; 10T
ret
; -------------------------------------------------------
; Silence all audio generators
; -------------------------------------------------------
psg_silence:
ld a,0x9f ; mute tone 0
out (SN_PORT),a
ld a,0xbf ; mute tone 1
out (SN_PORT),a
ld a,0xdf ; mute tone 2
out (SN_PORT),a
ld a,0xff ; mute noise
out (SN_PORT),a
ret
; -------------------------------------------------------
; Strings
; -------------------------------------------------------
+1
View File
@@ -6,3 +6,4 @@ BANK_ENABLE_BIT .equ 004h
BANK_MODE_CLEAR_MASK .equ 0f9h
TAPE_PORT .equ 018h
SN_PORT .equ 019h
-199
View File
@@ -1,199 +0,0 @@
Name casette;
PartNo 00;
Date 2026-10-03;
Revision 01;
Designer joppe;
Company unknown;
Assembly None;
Location unknown;
Device g22v10;
/* ------------------------------------------------------------
Constants
------------------------------------------------------------ */
ar = 'b'0;
sp = 'b'0;
/* ------------------------------------------------------------
Pin assignments
Physical signals IOSEL, RD and WR are active-low.
Their polarity is expressed in the equations with !.
------------------------------------------------------------ */
/* inputs */
PIN 1 = CLK;
PIN 2 = A1;
PIN 3 = A2;
PIN 4 = IOSEL;
PIN 5 = RD;
PIN 6 = A0;
PIN 7 = COMP;
PIN 8 = WR;
/* data bus */
PIN 14 = D0;
PIN 15 = D1;
PIN 16 = D2;
PIN 17 = D3;
PIN 18 = D4;
PIN 19 = D5;
PIN 20 = D6;
PIN 21 = D7;
/* registered output */
PIN 22 = LED;
/* ------------------------------------------------------------
Read register at offset 0
Conditions:
/IOSEL = 0
/RD = 0
/WR = 1
A2:A0 = 000
Result:
D0 = COMP
D7..D1 = 0
------------------------------------------------------------ */
D0 = COMP;
D1 = 'b'0;
D2 = 'b'0;
D3 = 'b'0;
D4 = 'b'0;
D5 = 'b'0;
D6 = 'b'0;
D7 = 'b'0;
D0.OE =
!IOSEL
& !RD
& WR
& !A2
& !A1
& !A0;
D1.OE =
!IOSEL
& !RD
& WR
& !A2
& !A1
& !A0;
D2.OE =
!IOSEL
& !RD
& WR
& !A2
& !A1
& !A0;
D3.OE =
!IOSEL
& !RD
& WR
& !A2
& !A1
& !A0;
D4.OE =
!IOSEL
& !RD
& WR
& !A2
& !A1
& !A0;
D5.OE =
!IOSEL
& !RD
& WR
& !A2
& !A1
& !A0;
D6.OE =
!IOSEL
& !RD
& WR
& !A2
& !A1
& !A0;
D7.OE =
!IOSEL
& !RD
& WR
& !A2
& !A1
& !A0;
/* ------------------------------------------------------------
Writable LED register
Write conditions:
/IOSEL = 0
/RD = 1
/WR = 0
A2:A0 = 000
During such a write:
LED.D = D0
Otherwise:
LED.D = LED
Pin 1 (CLK) clocks the registered macrocell.
------------------------------------------------------------ */
LED.D =
(
!IOSEL
& RD
& !WR
& !A2
& !A1
& !A0
& D0
)
#
(
(
IOSEL
# !RD
# WR
# A2
# A1
# A0
)
& LED
);
LED.ar = ar;
LED.sp = sp;
+49
View File
@@ -0,0 +1,49 @@

CUPL(WM) 5.0a Serial# MW-10400000
Device g22v10 Library DLIB-h-40-1
Created Sat Oct 17 12:42:37 2026
Name acc
Partno 00
Revision 01
Date 2026-10-11
Designer Joppe Blondel
Company unknown
Assembly unknown
Location unknown
*QP24
*QF5892
*G0
*F0
*L00416 00000000000000000000000011111111
*L00448 11111111111111111111111111111111
*L00480 11111111101110111011011110111111
*L00512 10111111110111111111111011110111
*L00544 11111111111111111111111111111111
*L00576 11101111111110111111111111111111
*L00608 11111111111111101111111111111111
*L00640 11110111111111111111111111101111
*L00672 11111111011111111111111111111111
*L00704 11110110111111111111111111111111
*L00736 11111111111111111110011111111111
*L00768 11111111111111111111111100000000
*L03648 00001111111111111111111111111111
*L03680 11111111111111111111011110111011
*L03712 10111011111101111111111111111111
*L03744 01111011101101110111111110111111
*L03776 11111111000000000000000000000000
*L04288 00000000000000000000000011111111
*L04320 11111111111111111111111111111111
*L04352 11111111011110111011011111111111
*L04384 10111111111111110000000000000000
*L04864 00000000000000000000111111111111
*L04896 11111111111111111111111111111111
*L04928 11111011101110110111011111111011
*L04960 11111111111100000000000000000000
*L05344 00000000000000000000000011111011
*L05376 10111011101110111111011111111111
*L05408 11111111111111111111111111110111
*L05440 11111111111111110000000000000000
*L05792 00000000000000000010000000001111
*L05824 01110011000000110000000000000000
*C5C1A
*46C6
Binary file not shown.
+297
View File
@@ -0,0 +1,297 @@
*******************************************************************************
acc
*******************************************************************************
CUPL(WM) 5.0a Serial# MW-10400000
Device g22v10 Library DLIB-h-40-1
Created Sat Oct 17 12:42:37 2026
Name acc
Partno 00
Revision 01
Date 2026-10-11
Designer Joppe Blondel
Company unknown
Assembly unknown
Location unknown
===============================================================================
Expanded Product Terms
===============================================================================
AYADDRWRITE =>
A0 & A1 & !A2 & !IOSELN & RDN & !WRN
AYBC1 =>
!A0 & A1 & !A2 & !IOSELN & !RDN & WRN
# A0 & A1 & !A2 & !IOSELN & RDN & !WRN
AYBDIR =>
A1 & !A2 & !IOSELN & RDN & !WRN
AYDATAREAD =>
!A0 & A1 & !A2 & !IOSELN & !RDN & WRN
AYDATAWRITE =>
!A0 & A1 & !A2 & !IOSELN & RDN & !WRN
COUT.d =>
!A0 & !A1 & !A2 & D0 & !IOSELN & RDN & !WRN
# COUT & IOSELN
# COUT & !RDN
# COUT & WRN
# A0 & COUT
# A1 & COUT
# A2 & COUT
COUT.ar =>
0
COUT.sp =>
0
D0 =>
COMP
D0.oe =>
!A0 & !A1 & !A2 & !IOSELN & !RDN & WRN
SNWEN =>
A0 & !A1 & !A2 & !IOSELN & RDN & !WRN
ar =>
0
sp =>
0
AYBC1.oe =>
1
AYBDIR.oe =>
1
COUT.oe =>
1
SNWEN.oe =>
1
===============================================================================
Symbol Table
===============================================================================
Pin Variable Pterms Max Min
Pol Name Ext Pin Type Used Pterms Level
--- -------- --- --- ---- ------ ------ -----
A0 6 V - - -
A1 2 V - - -
A2 3 V - - -
AYADDRWRITE 0 I 1 - -
AYBC1 17 V 2 14 1
AYBDIR 16 V 1 12 1
AYDATAREAD 0 I 1 - -
AYDATAWRITE 0 I 1 - -
CLK 1 V - - -
COMP 7 V - - -
COUT 22 V - - -
COUT d 22 X 7 10 1
COUT ar 22 X 1 1 1
COUT sp 22 X 1 1 1
D0 14 V 1 8 1
D0 oe 14 X 1 1 1
IOSELN 4 V - - -
RDN 5 V - - -
SNWEN 15 V 1 10 1
WRN 8 V - - -
ar 0 I 1 - -
sp 0 I 1 - -
AYBC1 oe 17 D 1 1 0
AYBDIR oe 16 D 1 1 0
COUT oe 22 D 1 1 0
SNWEN oe 15 D 1 1 0
LEGEND D : default variable F : field G : group
I : intermediate variable N : node M : extended node
U : undefined V : variable X : extended variable
T : function
===============================================================================
Fuse Plot
===============================================================================
SP
05764 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
AR
00000 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Pin #23 05808 Mode xx
00044 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
00088 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
00132 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
00176 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
00220 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
00264 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
00308 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
00352 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
00396 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Pin #22 05810 Mode -x
00440 --------------------------------------------
00484 -----x---x---x--x----x-------x--------x-----
00528 -------x----x-------------------------------
00572 -------x---------x--------------------------
00616 -------x--------------------x---------------
00660 -------x------------x-----------------------
00704 ----x--x------------------------------------
00748 -------xx-----------------------------------
00792 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
00836 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
00880 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Pin #21 05812 Mode xx
00924 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
00968 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01012 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01056 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01100 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01144 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01188 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01232 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01276 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01320 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01364 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01408 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01452 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Pin #20 05814 Mode xx
01496 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01540 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01584 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01628 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01672 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01716 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01760 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01804 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01848 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01892 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01936 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
01980 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02024 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02068 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02112 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Pin #19 05816 Mode xx
02156 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02200 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02244 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02288 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02332 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02376 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02420 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02464 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02508 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02552 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02596 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02640 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02684 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02728 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02772 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02816 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02860 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Pin #18 05818 Mode xx
02904 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02948 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
02992 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03036 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03080 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03124 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03168 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03212 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03256 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03300 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03344 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03388 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03432 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03476 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03520 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03564 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03608 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Pin #17 05820 Mode --
03652 --------------------------------------------
03696 ----x----x---x---x---x------x---------------
03740 ----x----x---x--x---x--------x--------------
03784 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03828 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03872 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03916 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
03960 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
04004 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
04048 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
04092 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
04136 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
04180 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
04224 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
04268 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Pin #16 05822 Mode --
04312 --------------------------------------------
04356 ----x----x---x--x------------x--------------
04400 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
04444 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
04488 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
04532 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
04576 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
04620 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
04664 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
04708 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
04752 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
04796 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
04840 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Pin #15 05824 Mode x-
04884 --------------------------------------------
04928 -----x---x---x--x---x--------x--------------
04972 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
05016 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
05060 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
05104 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
05148 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
05192 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
05236 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
05280 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
05324 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Pin #14 05826 Mode --
05368 -----x---x---x---x---x------x---------------
05412 ------------------------x-------------------
05456 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
05500 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
05544 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
05588 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
05632 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
05676 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
05720 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
LEGEND X : fuse not blown
- : fuse blown
===============================================================================
Chip Diagram
===============================================================================
______________
| acc |
CLK x---|1 24|---x Vcc
A1 x---|2 23|---x
A2 x---|3 22|---x COUT
IOSELN x---|4 21|---x
RDN x---|5 20|---x
A0 x---|6 19|---x
COMP x---|7 18|---x
WRN x---|8 17|---x AYBC1
x---|9 16|---x AYBDIR
x---|10 15|---x SNWEN
x---|11 14|---x D0
GND x---|12 13|---x
|______________|
+74
View File
@@ -0,0 +1,74 @@
LISTING FOR LOGIC DESCRIPTION FILE: audio_casette_card.pld Page 1
CUPL(WM): Universal Compiler for Programmable Logic
Version 5.0a Serial# MW-10400000
Copyright (c) 1983, 1998 Logical Devices, Inc.
Created Sat Oct 17 12:42:37 2026
1:Name acc;
2:PartNo 00;
3:Date 2026-10-11;
4:Revision 01;
5:Designer Joppe Blondel;
6:Company unknown;
7:Assembly unknown;
8:Location unknown;
9:Device g22v10;
10:
11:/* Constants */
12:ar = 'b'0;
13:sp = 'b'0;
14:
15:/* Pin assignments */
16:/* inputs */
17:PIN 1 = CLK;
18:PIN 2 = A1;
19:PIN 3 = A2;
20:PIN 4 = IOSELN;
21:PIN 5 = RDN;
22:PIN 6 = A0;
23:PIN 7 = COMP;
24:PIN 8 = WRN;
25:/* outputs */
26:PIN 14 = D0;
27:PIN 15 = SNWEN;
28:PIN 16 = AYBDIR;
29:PIN 17 = AYBC1;
30:PIN 22 = COUT;
31:
32:/* Read reg0 */
33:/* places comparator output on D0 when reading addr0 */
34:D0 = COMP;
35:D0.OE = !IOSELN & !RDN & WRN & !A0 & !A1 & !A2;
36:
37:/* Write reg0 */
38:/* writes D0 to casette output port */
39:/* during a write COUT.D=D0 otherwise COUT.D = COUT */
40:COUT.D = (!IOSELN & RDN & !WRN & !A0 & !A1 & !A2 & D0) #
41: ((IOSELN # !RDN # WRN # A0 # A1 # A2) & COUT);
42:COUT.ar = ar;
43:COUT.sp = sp;
44:
45:/* Write to SN76489 at addr 1 */
46:SNWEN = !(!IOSELN & RDN & !WRN & A0 & !A1 & !A2);
47:
48:/* AY-3-8910 access at addr 2 (data) addr 3 (adress) */
49:AYDATAREAD = !IOSELN & !RDN & WRN & !A0 & A1 & !A2;
50:AYDATAWRITE = !IOSELN & RDN & !WRN & !A0 & A1 & !A2;
51:AYADDRWRITE = !IOSELN & RDN & !WRN & A0 & A1 & !A2;
52:AYBDIR = AYDATAWRITE # AYADDRWRITE;
53:AYBC1 = AYDATAREAD # AYADDRWRITE;
LISTING FOR LOGIC DESCRIPTION FILE: audio_casette_card.pld Page 2
CUPL(WM): Universal Compiler for Programmable Logic
Version 5.0a Serial# MW-10400000
Copyright (c) 1983, 1998 Logical Devices, Inc.
Created Sat Oct 17 12:42:37 2026
54:
Jedec Fuse Checksum (5c1a)
Jedec Transmit Checksum (46c6)
+53
View File
@@ -0,0 +1,53 @@
Name acc;
PartNo 00;
Date 2026-10-11;
Revision 01;
Designer Joppe Blondel;
Company unknown;
Assembly unknown;
Location unknown;
Device g22v10;
/* Constants */
ar = 'b'0;
sp = 'b'0;
/* Pin assignments */
/* inputs */
PIN 1 = CLK;
PIN 2 = A1;
PIN 3 = A2;
PIN 4 = IOSELN;
PIN 5 = RDN;
PIN 6 = A0;
PIN 7 = COMP;
PIN 8 = WRN;
/* outputs */
PIN 14 = D0;
PIN 15 = SNWEN;
PIN 16 = AYBDIR;
PIN 17 = AYBC1;
PIN 22 = COUT;
/* Read reg0 */
/* places comparator output on D0 when reading addr0 */
D0 = COMP;
D0.OE = !IOSELN & !RDN & WRN & !A0 & !A1 & !A2;
/* Write reg0 */
/* writes D0 to casette output port */
/* during a write COUT.D=D0 otherwise COUT.D = COUT */
COUT.D = (!IOSELN & RDN & !WRN & !A0 & !A1 & !A2 & D0) #
((IOSELN # !RDN # WRN # A0 # A1 # A2) & COUT);
COUT.ar = ar;
COUT.sp = sp;
/* Write to SN76489 at addr 1 */
SNWEN = !(!IOSELN & RDN & !WRN & A0 & !A1 & !A2);
/* AY-3-8910 access at addr 2 (data) addr 3 (adress) */
AYDATAREAD = !IOSELN & !RDN & WRN & !A0 & A1 & !A2;
AYDATAWRITE = !IOSELN & RDN & !WRN & !A0 & A1 & !A2;
AYADDRWRITE = !IOSELN & RDN & !WRN & A0 & A1 & !A2;
AYBDIR = AYDATAWRITE # AYADDRWRITE;
AYBC1 = AYDATAREAD # AYADDRWRITE;
+79
View File
@@ -0,0 +1,79 @@
%SIGNAL
PIN 6 = A0
PIN 2 = A1
PIN 3 = A2
PIN 17 = AYBC1
PIN 16 = AYBDIR
PIN 1 = CLK
PIN 7 = COMP
PIN 22 = COUT
PIN 14 = D0
PIN 4 = IOSELN
PIN 5 = RDN
PIN 15 = SNWEN
PIN 8 = WRN
%END
%FIELD
%END
%EQUATION
AYADDRWRITE =>
A0 & A1 & !A2 & !IOSELN & RDN & !WRN
AYBC1 =>
!A0 & A1 & !A2 & !IOSELN & !RDN & WRN
# A0 & A1 & !A2 & !IOSELN & RDN & !WRN
AYBDIR =>
A1 & !A2 & !IOSELN & RDN & !WRN
AYDATAREAD =>
!A0 & A1 & !A2 & !IOSELN & !RDN & WRN
AYDATAWRITE =>
!A0 & A1 & !A2 & !IOSELN & RDN & !WRN
COUT.d =>
!A0 & !A1 & !A2 & D0 & !IOSELN & RDN & !WRN
# !COUT & IOSELN
# !COUT & !RDN
# !COUT & WRN
# A0 & !COUT
# A1 & !COUT
# A2 & !COUT
COUT.ar =>
0
COUT.sp =>
0
D0 =>
COMP
D0.oe =>
!A0 & !A1 & !A2 & !IOSELN & !RDN & WRN
SNWEN =>
A0 & !A1 & !A2 & !IOSELN & RDN & !WRN
ar =>
0
sp =>
0
AYBC1.oe =>
1
AYBDIR.oe =>
1
COUT.oe =>
1
SNWEN.oe =>
1
%END
-54
View File
@@ -1,54 +0,0 @@

CUPL(WM) 5.0a Serial# MW-10400000
Device g22v10 Library DLIB-h-40-1
Created Sat Oct 03 16:22:02 2026
Name casette
Partno 00
Revision 01
Date 2026-10-03
Designer joppe
Company unknown
Assembly None
Location unknown
*QP24
*QF5892
*G1
*F0
*L00416 00000000000000000000000011111111
*L00448 11111111111111111111111111111111
*L00480 11111111101110111011011110111111
*L00512 10111111110111111111111011110111
*L00544 11111111111111111111111111111111
*L00576 11101111111110111111111111111111
*L00608 11111111111111101111111111111111
*L00640 11110111111111111111111111100111
*L00672 11111111111111111111111111111111
*L00704 11110110111111111111111111111111
*L00736 11111111111111111110111111111111
*L00768 01111111111111111111111100000000
*L00896 00000000000000000000000000001111
*L00928 10111011101110111011111101111111
*L00960 11111111000000000000000000000000
*L01472 00000000000000000000000011111011
*L01504 10111011101110111111011111111111
*L01536 11110000000000000000000000000000
*L02144 00000000000011111011101110111011
*L02176 10111111011111111111111100000000
*L02880 00000000000000000000000011111011
*L02912 10111011101110111111011111111111
*L02944 11110000000000000000000000000000
*L03648 00001111101110111011101110111111
*L03680 01111111111111110000000000000000
*L04288 00000000000000000000000011111011
*L04320 10111011101110111111011111111111
*L04352 11110000000000000000000000000000
*L04864 00000000000000000000111110111011
*L04896 10111011101111110111111111111111
*L05344 00000000000000000000000011111011
*L05376 10111011101110111111011111111111
*L05408 11111111111111111111111111110111
*L05440 11111111111111110000000000000000
*L05792 00000000000000000010111111111111
*L05824 11110011000000110000000000000000
*C5BE4
*6A87
+2
View File
@@ -0,0 +1,2 @@
#!/bin/bash
/opt/packages/wincupl/cupl -jaxfl g22v10 audio_casette_card.pld
+3
View File
@@ -16,6 +16,9 @@ BIOS_ROM_SIZE := 0x0780
BASIC_ROM_START := 0x0800
BASIC_ROM_SIZE := 0x2200
SN76489_ROM_START := 0x2a00
SN76489_ROM_SIZE := 0x1000
BIOS_RAM_START := 0xc000
BIOS_WP_RAM_START := 0xc800
BASIC_RAM_START := 0xce00
+20 -8
View File
@@ -106,11 +106,10 @@ class PulseWriter:
self.bytes(struct.pack("<H", crc16(block_data)))
self.byte(0x00) # Make sure the last byte has its last edge
def header(pulses: PulseWriter, path:Path) -> None:
def header(pulses: PulseWriter, path:Path, file_size: int) -> None:
fname = path.name
fsize = os.path.getsize(path)
data = (
struct.pack("<HH", math.ceil(fsize/BLOCK_SIZE), fsize)
struct.pack("<HH", math.ceil(file_size/BLOCK_SIZE), file_size)
+ fname.encode()[:32].ljust(32, b' ')
)
pulses.block(TYPE_BINARY, data)
@@ -126,6 +125,12 @@ def main() -> None:
)
parser.add_argument("input", type=Path, help="input file to encode")
parser.add_argument("output", type=Path, help="output WAV file")
parser.add_argument(
"--max-size",
type=int,
metavar="BYTES",
help="encode at most this many bytes from the input file",
)
parser.add_argument("--sample-rate", type=int, default=48_000)
parser.add_argument(
"--t-short",
@@ -152,6 +157,13 @@ def main() -> None:
parser.error("--t-short must be less than --t-long")
if not 0.0 <= args.amplitude <= 1.0:
parser.error("--amplitude must be between 0 and 1")
if args.max_size is not None and args.max_size < 0:
parser.error("--max-size must not be negative")
input_size = os.path.getsize(args.input)
encoded_size = (
input_size if args.max_size is None else min(input_size, args.max_size)
)
try:
pulses = PulseWriter(
@@ -165,14 +177,14 @@ def main() -> None:
# create header block
pulses.space(5.0)
header(pulses, args.input)
header(pulses, args.input, encoded_size)
pulses.space(1.0)
with open(args.input, "rb") as f:
while True:
data = f.read(BLOCK_SIZE)
if not len(data):
break
remaining = encoded_size
while remaining:
data = f.read(min(BLOCK_SIZE, remaining))
raw(pulses, data)
remaining -= len(data)
pulses.space(1.0)
with wave.open(str(args.output), "wb") as wav:
Binary file not shown.
BIN
View File
Binary file not shown.