Initial commit with basic sound and speech support.
This commit is contained in:
parent
d871fb4660
commit
84ddb58602
|
@ -7,6 +7,7 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
9D16BCE21D9E070B005EE214 /* speech.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = speech.s; sourceTree = "<group>"; };
|
||||
9DB3C98C1D84A11600395532 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = "<group>"; };
|
||||
9DB3C98D1D84A11600395532 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
|
||||
9DB3C98F1D84A11600395532 /* AppleCommander.jar */ = {isa = PBXFileReference; lastKnownFileType = archive.jar; name = AppleCommander.jar; path = make/AppleCommander.jar; sourceTree = "<group>"; };
|
||||
|
@ -17,6 +18,8 @@
|
|||
9DB3C9941D84A11600395532 /* prodos_template.dsk */ = {isa = PBXFileReference; lastKnownFileType = file; name = prodos_template.dsk; path = make/prodos_template.dsk; sourceTree = "<group>"; };
|
||||
9DB3C9951D84A11600395532 /* tail.mk */ = {isa = PBXFileReference; lastKnownFileType = text; name = tail.mk; path = make/tail.mk; sourceTree = "<group>"; };
|
||||
9DB3C9961D84A11600395532 /* V2Make.scpt */ = {isa = PBXFileReference; lastKnownFileType = file; name = V2Make.scpt; path = make/V2Make.scpt; sourceTree = "<group>"; };
|
||||
9DB3C99C1D84A21E00395532 /* mockingboard.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = mockingboard.c; sourceTree = "<group>"; };
|
||||
9DB3C99D1D84A21E00395532 /* mockingboard.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mockingboard.h; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
|
@ -31,6 +34,9 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
9DB3C98C1D84A11600395532 /* main.c */,
|
||||
9DB3C99C1D84A21E00395532 /* mockingboard.c */,
|
||||
9DB3C99D1D84A21E00395532 /* mockingboard.h */,
|
||||
9D16BCE21D9E070B005EE214 /* speech.s */,
|
||||
9DB3C98D1D84A11600395532 /* Makefile */,
|
||||
9DB3C98E1D84A11600395532 /* make */,
|
||||
);
|
||||
|
@ -223,6 +229,7 @@
|
|||
9DB3C99B1D84A11600395532 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
|
|
|
@ -5,6 +5,22 @@
|
|||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "9DB3C98A1D84A11600395532"
|
||||
BuildableName = "mocktest"
|
||||
BlueprintName = "mocktest"
|
||||
ReferencedContainer = "container:mocktest.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
|
@ -26,6 +42,15 @@
|
|||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "9DB3C98A1D84A11600395532"
|
||||
BuildableName = "mocktest"
|
||||
BlueprintName = "mocktest"
|
||||
ReferencedContainer = "container:mocktest.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
|
@ -35,6 +60,15 @@
|
|||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "9DB3C98A1D84A11600395532"
|
||||
BuildableName = "mocktest"
|
||||
BlueprintName = "mocktest"
|
||||
ReferencedContainer = "container:mocktest.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
|
|
|
@ -25,7 +25,7 @@ PGM=mocktest
|
|||
# Uncomment the one you want below (the first one is the default):
|
||||
# MACHINE = apple2
|
||||
# MACHINE = apple2-dos33
|
||||
# MACHINE = apple2-system
|
||||
MACHINE = apple2-system
|
||||
# MACHINE = apple2-loader
|
||||
# MACHINE = apple2-reboot
|
||||
# MACHINE = apple2enh
|
||||
|
|
|
@ -8,13 +8,105 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <conio.h>
|
||||
|
||||
#include "mockingboard.h"
|
||||
|
||||
|
||||
extern void setupSpeech(void);
|
||||
uint8_t **tabPtr = (uint8_t **)0x00f9;
|
||||
|
||||
|
||||
tMockingSoundRegisters soundData1 = {
|
||||
{ TONE_PERIOD_A(4), 0, 0 }, // Tone period for the three channels
|
||||
MIN_NOISE_PERIOD, // Noise period
|
||||
ENABLE_CHANNEL(TONE_CHANNEL_A), // Enable
|
||||
{ MAX_AMPLITUDE, MIN_AMPLITUDE, MIN_AMPLITUDE }, // Amplitude for the three channels
|
||||
MIN_ENVELOPE_PERIOD, // Envelope period
|
||||
ENVELOPE_SHAPE_ONE_SHOT_DECAY, // Envelope shape
|
||||
0, // Dummy1
|
||||
0 // Dummy2
|
||||
};
|
||||
|
||||
|
||||
tMockingSoundRegisters soundData2 = {
|
||||
{ TONE_PERIOD_F_SHARP(3), 0, 0 }, // Tone period for the three channels
|
||||
MIN_NOISE_PERIOD, // Noise period
|
||||
ENABLE_CHANNEL(TONE_CHANNEL_A), // Enable
|
||||
{ MAX_AMPLITUDE, MIN_AMPLITUDE, MIN_AMPLITUDE }, // Amplitude for the three channels
|
||||
MIN_ENVELOPE_PERIOD, // Envelope period
|
||||
ENVELOPE_SHAPE_ONE_SHOT_DECAY, // Envelope shape
|
||||
0, // Dummy1
|
||||
0 // Dummy2
|
||||
};
|
||||
|
||||
|
||||
uint8_t speechData[] = {
|
||||
0xCF, 0x00, 0xE8, 0x70, 0xA8, 0x5F, 0x00, 0xE8,
|
||||
0x70, 0xA8, 0x5F, 0x00, 0xE8, 0x70, 0xA8, 0x5F,
|
||||
0x00, 0xE8, 0x7B, 0xA8, 0x5F, 0x63, 0xE7, 0x6B,
|
||||
0xA8, 0x59, 0x47, 0xE8, 0x6A, 0xA8, 0x61, 0x36,
|
||||
0xE8, 0x79, 0xA8, 0x65, 0x37, 0xE7, 0x79, 0xA8,
|
||||
0x69, 0x0E, 0xE7, 0x6A, 0xA8, 0x61, 0x29, 0xE8,
|
||||
0x6B, 0xA8, 0x59, 0xAD, 0xE8, 0x6B, 0xA8, 0x51,
|
||||
0xC0, 0xE8, 0x6A, 0xA8, 0x51, 0x07, 0xE8, 0x6A,
|
||||
0xA8, 0x4B, 0x39, 0xE8, 0x6A, 0xA8, 0x49, 0x64,
|
||||
0xE7, 0x6A, 0x88, 0x49, 0x11, 0xE7, 0x5A, 0xB8,
|
||||
0x51, 0x63, 0xE7, 0x5A, 0xB8, 0x59, 0x1D, 0xE8,
|
||||
0x7A, 0xA8, 0x61, 0x65, 0xE8, 0x79, 0xA8, 0x61,
|
||||
0xC0, 0xE8, 0x70, 0x78, 0x51, 0x00, 0xE8, 0x70,
|
||||
0x78, 0x51, 0x00, 0xE8, 0x70, 0x78, 0x59, 0x00,
|
||||
0xE7, 0x79, 0xA8, 0x65, 0x04, 0xE7, 0x6A, 0x98,
|
||||
0x61, 0x16, 0xE8, 0x6B, 0xA8, 0x61, 0x60, 0xE8,
|
||||
0x7C, 0xA8, 0x59, 0x78, 0xE7, 0x7C, 0xA8, 0x55,
|
||||
0x0A, 0xE8, 0x6B, 0xA8, 0x62, 0x33, 0xE8, 0x6A,
|
||||
0xA8, 0x59, 0x1C, 0xE8, 0x7A, 0xA8, 0x51, 0x64,
|
||||
0xE7, 0x7B, 0x88, 0x51, 0x01, 0xE8, 0x7C, 0xA8,
|
||||
0x59, 0x30, 0xE8, 0x7D, 0xA8, 0x59, 0x27, 0xE7,
|
||||
0x7D, 0x78, 0x61, 0x01, 0xE8, 0x6C, 0xA8, 0x61,
|
||||
0x28, 0xE8, 0x6B, 0xA8, 0x59, 0x32, 0xE8, 0x6A,
|
||||
0xA8, 0x4D, 0x60, 0xE7, 0x29, 0xA8, 0x41, 0x0A,
|
||||
0xE8, 0x78, 0xA8, 0x41, 0x30, 0xE8, 0x70, 0xA8,
|
||||
0x39, 0xFF, 0xE8, 0x70, 0xA8, 0x39, 0x00, 0xE8,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
|
||||
void delay(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 1000; i++) ;
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
mockingBoardInit(4);
|
||||
|
||||
printf("HELLO, WORLD!\n");
|
||||
|
||||
while (!kbhit()) {
|
||||
mockingBoardTableAccess(SOUND_CHIP_1, &soundData1);
|
||||
delay();
|
||||
mockingBoardReset(SOUND_CHIP_1);
|
||||
|
||||
mockingBoardTableAccess(SOUND_CHIP_2, &soundData2);
|
||||
delay();
|
||||
mockingBoardReset(SOUND_CHIP_2);
|
||||
}
|
||||
|
||||
cgetc();
|
||||
printf("RUN SPEECH TEST (Y/N) ");
|
||||
if (cgetc() != 'Y')
|
||||
return 0;
|
||||
|
||||
*tabPtr = speechData;
|
||||
setupSpeech();
|
||||
|
||||
cgetc();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,114 @@
|
|||
//
|
||||
// mockingboard.c
|
||||
// mocktest
|
||||
//
|
||||
// Created by Jeremy Rand on 2016-09-10.
|
||||
// Copyright © 2016 Jeremy Rand. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "mockingboard.h"
|
||||
|
||||
|
||||
// Defines
|
||||
|
||||
#define LATCH_COMMAND 0x7
|
||||
#define WRITE_COMMAND 0x6
|
||||
#define RESET_COMMAND 0x0
|
||||
#define THROUGH_PORT_B 0x4
|
||||
|
||||
|
||||
// Globals
|
||||
|
||||
// Addresses for the two 6522's (assuming slot 4 for now)
|
||||
static uint8_t *gMockPortB[NUM_SOUND_CHIPS] = { (uint8_t *)0xc400, (uint8_t *)0xc480 };
|
||||
static uint8_t *gMockPortA[NUM_SOUND_CHIPS] = { (uint8_t *)0xc401, (uint8_t *)0xc481 };
|
||||
static uint8_t *gMockDataDirB[NUM_SOUND_CHIPS] = { (uint8_t *)0xc402, (uint8_t *)0xc482 };
|
||||
static uint8_t *gMockDataDirA[NUM_SOUND_CHIPS] = { (uint8_t *)0xc403, (uint8_t *)0xc483 };
|
||||
|
||||
static uint8_t gMockingBoardInitialized = false;
|
||||
|
||||
|
||||
static uint8_t *mapIOPointer(uint8_t slot, uint8_t *ptr)
|
||||
{
|
||||
uint16_t temp1 = (uint16_t)ptr;
|
||||
uint16_t temp2 = slot;
|
||||
|
||||
temp2 << 8;
|
||||
temp1 &= 0xf0ff;
|
||||
|
||||
temp1 |= temp2;
|
||||
ptr = (uint8_t *)temp1;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void mockingBoardInit(tSlot slot)
|
||||
{
|
||||
tSoundChip soundChip;
|
||||
|
||||
if (sizeof(tMockingSoundRegisters) != 16) {
|
||||
printf("The sound registers must be 16 bytes long!\n");
|
||||
}
|
||||
|
||||
for (soundChip = SOUND_CHIP_1; soundChip < NUM_SOUND_CHIPS; soundChip++) {
|
||||
#if 0
|
||||
gMockPortB[soundChip] = mapIOPointer(slot, gMockPortB[soundChip]);
|
||||
gMockPortA[soundChip] = mapIOPointer(slot, gMockPortA[soundChip]);
|
||||
gMockDataDirB[soundChip] = mapIOPointer(slot, gMockDataDirB[soundChip]);
|
||||
gMockDataDirA[soundChip] = mapIOPointer(slot, gMockDataDirA[soundChip]);
|
||||
#endif
|
||||
|
||||
*(gMockDataDirA[soundChip]) = 0xff; // Set port A for output
|
||||
*(gMockDataDirB[soundChip]) = 0x7; // Set port B for output
|
||||
}
|
||||
|
||||
gMockingBoardInitialized = true;
|
||||
}
|
||||
|
||||
|
||||
static void writeCommand(tSoundChip soundChip, uint8_t command)
|
||||
{
|
||||
volatile uint8_t *ptr = gMockPortB[soundChip];
|
||||
|
||||
*ptr = command;
|
||||
*ptr = THROUGH_PORT_B;
|
||||
}
|
||||
|
||||
|
||||
void mockingBoardLatch(tSoundChip soundChip)
|
||||
{
|
||||
writeCommand(soundChip, LATCH_COMMAND);
|
||||
}
|
||||
|
||||
|
||||
void mockingBoardWrite(tSoundChip soundChip)
|
||||
{
|
||||
writeCommand(soundChip, WRITE_COMMAND);
|
||||
}
|
||||
|
||||
|
||||
void mockingBoardReset(tSoundChip soundChip)
|
||||
{
|
||||
writeCommand(soundChip, RESET_COMMAND);
|
||||
}
|
||||
|
||||
|
||||
void mockingBoardTableAccess(tSoundChip soundChip, tMockingSoundRegisters *registers)
|
||||
{
|
||||
uint8_t *data = (uint8_t *)registers;
|
||||
volatile uint8_t *ptr = gMockPortA[soundChip];
|
||||
uint8_t index;
|
||||
|
||||
mockingBoardReset(soundChip);
|
||||
for (index = 0; index < 16; index++) {
|
||||
*ptr = index;
|
||||
mockingBoardLatch(soundChip);
|
||||
*ptr = *data;
|
||||
mockingBoardWrite(soundChip);
|
||||
data++;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
//
|
||||
// mockingboard.h
|
||||
// mocktest
|
||||
//
|
||||
// Created by Jeremy Rand on 2016-09-10.
|
||||
// Copyright © 2016 Jeremy Rand. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __mocktest__mockingboard__
|
||||
#define __mocktest__mockingboard__
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
// Defines
|
||||
|
||||
#define MOCK_NUM_CHANNELS 3
|
||||
|
||||
|
||||
#define TONE_PERIOD_C(octave) (0x7a3 >> (octave - 1))
|
||||
#define TONE_PERIOD_C_SHARP(octave) (0x735 >> (octave - 1))
|
||||
#define TONE_PERIOD_D(octave) (0x6cd >> (octave - 1))
|
||||
#define TONE_PERIOD_D_SHARP(octave) (0x66c >> (octave - 1))
|
||||
#define TONE_PERIOD_E(octave) (0x60f >> (octave - 1))
|
||||
#define TONE_PERIOD_F(octave) (0x5b8 >> (octave - 1))
|
||||
#define TONE_PERIOD_F_SHARP(octave) (0x566 >> (octave - 1))
|
||||
#define TONE_PERIOD_G(octave) (0x518 >> (octave - 1))
|
||||
#define TONE_PERIOD_G_SHARP(octave) (0x4cf >> (octave - 1))
|
||||
#define TONE_PERIOD_A(octave) (0x48a >> (octave - 1))
|
||||
#define TONE_PERIOD_A_SHARP(octave) (0x449 >> (octave - 1))
|
||||
#define TONE_PERIOD_B(octave) (0x40b >> (octave - 1))
|
||||
|
||||
#define MIN_NOISE_PERIOD 0
|
||||
#define MAX_NOISE_PERIOD 31
|
||||
|
||||
#define TONE_CHANNEL_A 1
|
||||
#define TONE_CHANNEL_B 2
|
||||
#define TONE_CHANNEL_C 4
|
||||
#define NOISE_CHANNEL_A 8
|
||||
#define NOISE_CHANNLE_B 16
|
||||
#define NOISE_CHANNEL_C 32
|
||||
|
||||
#define ENABLE_CHANNEL(channels) (0x3f ^ (channels))
|
||||
|
||||
#define MIN_AMPLITUDE 0
|
||||
#define MAX_AMPLITUDE 15
|
||||
#define VARIABLE_AMPLITUDE 16
|
||||
|
||||
#define MIN_ENVELOPE_PERIOD 0
|
||||
#define MAX_ENVELOPE_PERIOD 65535u
|
||||
#define MILLISEC_TO_ENVELOP_PERIOD(ms) ((ms) * 4)
|
||||
|
||||
|
||||
// Here is a table of the envelope shapes and how they look:
|
||||
//
|
||||
// ENVELOPE_SHAPE_ONE_SHOT_DECAY \__________...
|
||||
//
|
||||
// ENVELOPE_SHAPE_ONE_SHOT_ATTACK /__________...
|
||||
//
|
||||
// ENVELOPE_SHAPE_CONT_DECAY \|\|\|\|\|\...
|
||||
//
|
||||
// ENVELOPE_SHAPE_CONT_DECAY_HOLD \__________...
|
||||
//
|
||||
// ENVELOPE_SHAPE_CONT_DECAY_ALT \/\/\/\/\/\...
|
||||
// _________
|
||||
// ENVELOPE_SHAPE_CONT_DECAY_ALT_HOLD \| ...
|
||||
//
|
||||
// ENVELOPE_SHAPE_CONT_ATTACK /|/|/|/|/|/...
|
||||
// __________
|
||||
// ENVELOPE_SHAPE_CONT_ATTACK_HOLD / ...
|
||||
// ENVELOPE_SHAPE_CONT_ATTACK_ALT /\/\/\/\/\/...
|
||||
//
|
||||
// ENVELOPE_SHAPE_CONT_ATTACK_ALT_HOLD /|_________...
|
||||
|
||||
#define ENVELOPE_SHAPE_ONE_SHOT_DECAY 0
|
||||
#define ENVELOPE_SHAPE_ONE_SHOT_ATTACK 4
|
||||
#define ENVELOPE_SHAPE_CONT_DECAY 8
|
||||
#define ENVELOPE_SHAPE_CONT_DECAY_HOLD 9
|
||||
#define ENVELOPE_SHAPE_CONT_DECAY_ALT 10
|
||||
#define ENVELOPE_SHAPE_CONT_DECAY_ALT_HOLD 11
|
||||
#define ENVELOPE_SHAPE_CONT_ATTACK 12
|
||||
#define ENVELOPE_SHAPE_CONT_ATTACK_HOLD 13
|
||||
#define ENVELOPE_SHAPE_CONT_ATTACK_ALT 14
|
||||
#define ENVELOPE_SHAPE_CONT_ATTACK_ALT_HOLD 15
|
||||
|
||||
|
||||
|
||||
// Typedefs
|
||||
|
||||
typedef uint8_t tSlot;
|
||||
|
||||
typedef enum {
|
||||
SOUND_CHIP_1 = 0,
|
||||
SOUND_CHIP_2 = 1,
|
||||
NUM_SOUND_CHIPS = 2
|
||||
} tSoundChip;
|
||||
|
||||
|
||||
typedef struct tMockingSoundRegisters {
|
||||
uint16_t tonePeriod[MOCK_NUM_CHANNELS];
|
||||
uint8_t noisePeriod;
|
||||
uint8_t enable;
|
||||
uint8_t amplitude[MOCK_NUM_CHANNELS];
|
||||
uint16_t envelopePeriod;
|
||||
uint8_t envelopeShape;
|
||||
uint8_t dummy1;
|
||||
uint8_t dummy2;
|
||||
} tMockingSoundRegisters;
|
||||
|
||||
|
||||
// API
|
||||
|
||||
void mockingBoardInit(tSlot slot);
|
||||
|
||||
void mockingBoardLatch(tSoundChip soundChip);
|
||||
void mockingBoardWrite(tSoundChip soundChip);
|
||||
void mockingBoardReset(tSoundChip soundChip);
|
||||
|
||||
void mockingBoardTableAccess(tSoundChip soundChip, tMockingSoundRegisters *registers);
|
||||
|
||||
|
||||
#endif /* defined(__mocktest__mockingboard__) */
|
|
@ -0,0 +1,135 @@
|
|||
;
|
||||
; speech.s
|
||||
; mocktest
|
||||
;
|
||||
; Created by Jeremy Rand on 2016-09-29.
|
||||
; Copyright © 2016 Jeremy Rand. All rights reserved.
|
||||
;
|
||||
|
||||
|
||||
.export _setupSpeech
|
||||
|
||||
|
||||
TABPTR := $F9 ;DATA POINTER
|
||||
OUTPTR := $FB ;START OF DATA POINTER
|
||||
ENDPTR := $FD ;END OF DATA POINTER
|
||||
BUSY := $FF ;BUSY FLAG
|
||||
IRQL := $03FE ;INTERRUPT VECTOR, LOW BYTE
|
||||
IRQH := $03FF ;INTERRUPT VECTOR, HIGH BYTE
|
||||
BASE := $C440 ;FIRST SPEECH CHIP
|
||||
DURPHON := BASE ;REGISTER 0 OF SPEECH CHIP
|
||||
INFLECT := BASE+$01 ;REGISTER 1 OF SPEECH CHIP
|
||||
RATEINF := BASE+$02 ;REGISTER 2 OF SPEECH CHIP
|
||||
CTTRAMP := BASE+$03 ;REGISTER 3 OF SPEECH CHIP
|
||||
FILFREQ := BASE+$04 ;REGISTER 4 OF SPEECH CHIP
|
||||
DDRB := $C402
|
||||
DDRA := $C403
|
||||
PCR := $C48C ;PERIPHERAL CONTROL REG-6522
|
||||
IFR := $C48D ;INTERRUPT FLAG REG-6522
|
||||
IER := $C48E
|
||||
|
||||
|
||||
.CODE
|
||||
|
||||
.proc _setupSpeech
|
||||
SEI ;DISABLE INTERRUPTS
|
||||
LDA #<_interr ;SET INTERRUPT VECTOR
|
||||
STA IRQL ;TO POINT TO INTERRUPT
|
||||
LDA #>_interr ;SERVICE ROUTINE
|
||||
STA IRQH
|
||||
LDA #$00
|
||||
STA DDRA
|
||||
STA DDRB
|
||||
|
||||
LDA TABPTR+1 ;GET HIGH ADDRESS OF DATA
|
||||
STA OUTPTR+1 ;STORE IN WORK POINTER
|
||||
LDX TABPTR ;GET LOW ADDRESS OF DATA
|
||||
INX ;INCREMENT TWICE
|
||||
INX ;TO SKIP OVER LENGTH BYTES
|
||||
BNE @L1 ;CHECK FOR PAGE BOUNDARY
|
||||
INC OUTPTR+1
|
||||
@L1:
|
||||
STX OUTPTR ;STORE LOW BYTE
|
||||
|
||||
LDY #$01
|
||||
LDA (TABPTR),Y ;GET HIGH LENGTH BYTE
|
||||
CLC
|
||||
ADC TABPTR+1 ;AND ADD TO BASE ADDRESS
|
||||
STA ENDPTR+1 ;STORE END ADDRESS
|
||||
DEY
|
||||
LDA (TABPTR),Y ;GET LOW LENGTH BYTE
|
||||
CLC
|
||||
ADC TABPTR ;AND ADD TO BASE ADDRESS
|
||||
BCC @L2 ;CHECK FOR PAGE BOUNDARY
|
||||
INC ENDPTR+1
|
||||
@L2:
|
||||
STA ENDPTR ;STORE END ADDRESS
|
||||
|
||||
LDA #$FF ;SET BUSY FLAG
|
||||
STA BUSY ;AND SET PERIPHERAL CONTROL
|
||||
LDA #$0C ;REGISTER TO RECOGNIZE
|
||||
STA PCR ;SIGNAL FROM SPEECH CHIP
|
||||
LDA #$80 ;RAISE CTRL BIT IN REGISTER 3
|
||||
STA CTTRAMP
|
||||
LDA #$C0 ;SET TRANSITIONED INFLECTION
|
||||
STA DURPHON ;MODE IN REGISTER 0
|
||||
LDA #$70 ;LOWER CTRL BIT
|
||||
STA CTTRAMP
|
||||
LDA #$82 ;ENABLE 6522 INTERRUPTS
|
||||
STA IER
|
||||
CLI ;CLEAR INTERRUPT MASK
|
||||
RTS ;RETURN TO CALLER
|
||||
.endproc
|
||||
|
||||
|
||||
.proc _interr
|
||||
TXA ;SAVE REGISTERS
|
||||
PHA
|
||||
TYA
|
||||
PHA
|
||||
LDA IFR
|
||||
BPL @L2
|
||||
LDA #$02 ;CLEAR INTERRUPT FLAG
|
||||
STA IFR
|
||||
LDY #$00 ;INIT REGISTERS
|
||||
LDX #$04
|
||||
LDA OUTPTR ;CHECK FOR END OF DATA FILE
|
||||
CMP ENDPTR
|
||||
BCC @L1 ;IF NOT THEN CONTINUE
|
||||
LDA OUTPTR+1 ;CHECK HIGH ADDRESS ALSO
|
||||
CMP ENDPTR+1
|
||||
BCC @L1 ;IF NOT THEN CONTINUE
|
||||
LDA #$00 ;IF END, TURN EVERYTHING OFF
|
||||
STA DURPHON ;STORE PAUSE PHONEME
|
||||
LDA #$70 ;ZERO AMPLITUDE
|
||||
STA CTTRAMP
|
||||
LDA #$00 ;CLEAR BUSY FLAG
|
||||
STA BUSY
|
||||
LDA #$02 ;CLEAR INTERRUPT ENABLE
|
||||
STA IER ;IN 6522
|
||||
LDA #$FF
|
||||
STA DDRA
|
||||
LDA #$07
|
||||
STA DDRB
|
||||
@L2:
|
||||
PLA ;RESTORE REGISTERS
|
||||
TAY
|
||||
PLA
|
||||
TAX
|
||||
LDA $45
|
||||
RTI ;RETURN FROM INTERRUPT
|
||||
|
||||
@L1:
|
||||
LDA (OUTPTR),Y ;GET DATA
|
||||
STA BASE,X ;STORE IN SPEECH CHIP
|
||||
INC OUTPTR ;NEXT DATA
|
||||
BNE @L3
|
||||
INC OUTPTR+1
|
||||
|
||||
@L3:
|
||||
DEX ;NEXT REGISTER
|
||||
CPX #$FF ;LAST REGISTER?
|
||||
BNE @L1 ;NO, CONTINUE
|
||||
BEQ @L2 ;YES, RETURN
|
||||
.endproc
|
||||
|
Loading…
Reference in New Issue