Getting PSG and SID code working
Code is mainly there to let us silence those parts on boot.
This commit is contained in:
parent
bdd2cb4929
commit
2e966e481d
|
@ -2,8 +2,8 @@
|
||||||
* Sound device register definitions for the F256K
|
* Sound device register definitions for the F256K
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __SOUND_C256_H
|
#ifndef __SOUND_F256_H
|
||||||
#define __SOUND_C256_H
|
#define __SOUND_F256_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
@ -20,8 +20,33 @@
|
||||||
* Internal SID
|
* Internal SID
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct s_sid_voice {
|
||||||
|
uint16_t frequency;
|
||||||
|
uint16_t pulse_width;
|
||||||
|
uint8_t control;
|
||||||
|
uint8_t attack_decay;
|
||||||
|
uint8_t sustain_release;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct s_sid {
|
||||||
|
struct s_sid_voice v1;
|
||||||
|
struct s_sid_voice v2;
|
||||||
|
struct s_sid_voice v3;
|
||||||
|
|
||||||
|
uint16_t filter_frequency;
|
||||||
|
uint8_t resonance_filter;
|
||||||
|
uint8_t mode_volume;
|
||||||
|
|
||||||
|
uint8_t pot_x;
|
||||||
|
uint8_t pot_y;
|
||||||
|
uint8_t osc3;
|
||||||
|
uint8_t env3;
|
||||||
|
};
|
||||||
|
|
||||||
#define SID_INT_N_V1_FREQ_LO ((volatile __attribute__((far)) uint8_t *)0xf01480)
|
#define SID_INT_N_V1_FREQ_LO ((volatile __attribute__((far)) uint8_t *)0xf01480)
|
||||||
#define SID_INT_L_V1_FREQ_LO ((volatile __attribute__((far)) uint8_t *)0xf01400)
|
#define SID_INT_L_V1_FREQ_LO ((volatile __attribute__((far)) uint8_t *)0xf01400)
|
||||||
#define SID_INT_R_V1_FREQ_LO ((volatile __attribute__((far)) uint8_t *)0xf01500)
|
#define SID_INT_R_V1_FREQ_LO ((volatile __attribute__((far)) uint8_t *)0xf01500)
|
||||||
|
|
||||||
|
#define SID_INT_N ((volatile __attribute__((far)) struct s_sid *)0xf01480)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -37,7 +37,7 @@ else ifeq ($(UNIT),F256)
|
||||||
AS=as65816
|
AS=as65816
|
||||||
AR=nlib
|
AR=nlib
|
||||||
|
|
||||||
SRCS_FOR_UNIT=psg.c codec_c256.c # sid.c
|
SRCS_FOR_UNIT=psg.c codec_c256.c sid.c
|
||||||
CFLAGS_FOR_UNIT=-DMODEL=2 -DCPU=255 --code-model large --data-model large
|
CFLAGS_FOR_UNIT=-DMODEL=2 -DCPU=255 --code-model large --data-model large
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
106
src/snd/psg.c
106
src/snd/psg.c
|
@ -2,10 +2,61 @@
|
||||||
* Definitions for the SN76489 PSG
|
* Definitions for the SN76489 PSG
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "psg.h"
|
#include "psg.h"
|
||||||
#include "sound_reg.h"
|
#include "sound_reg.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return the I/O base address of the PSG chip
|
||||||
|
*
|
||||||
|
* @param chip the number of the chip
|
||||||
|
* @return uint8_t* pointer to the first register
|
||||||
|
*/
|
||||||
|
static volatile uint8_t * psg_port(short chip) {
|
||||||
|
volatile uint8_t * port = 0;
|
||||||
|
|
||||||
|
#if MODEL == MODEL_FOENIX_A2560K || MODEL == MODEL_FOENIX_GENX || MODEL == MODEL_FOENIX_A2560X
|
||||||
|
switch (chip) {
|
||||||
|
case 1:
|
||||||
|
port = (uint8_t *)PSG_INT_L_PORT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
port = (uint8_t *)PSG_INT_R_PORT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
port = (uint8_t *)PSG_INT_S_PORT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
port = (uint8_t *)PSG_PORT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#elif MODEL == MODEL_FOENIX_F256 || MODEL == MODEL_FOENIX_F256K || MODEL == MODEL_FOENIX_F256K2
|
||||||
|
switch (chip) {
|
||||||
|
case 1:
|
||||||
|
port = PSG_PORT_L;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
port = PSG_PORT_R;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
port = PSG_PORT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mute all voices on the PSG
|
* Mute all voices on the PSG
|
||||||
*/
|
*/
|
||||||
|
@ -30,34 +81,15 @@ void psg_mute_all() {
|
||||||
* frequency = the frequency
|
* frequency = the frequency
|
||||||
*/
|
*/
|
||||||
void psg_tone(short chip, unsigned short voice, int frequency) {
|
void psg_tone(short chip, unsigned short voice, int frequency) {
|
||||||
volatile unsigned char * port = PSG_PORT; /* By default: external */
|
volatile uint8_t * port = psg_port(chip);
|
||||||
|
if (port) {
|
||||||
if (voice < 3) {
|
|
||||||
#if MODEL == MODEL_FOENIX_A2560K || MODEL == MODEL_FOENIX_GENX || MODEL == MODEL_FOENIX_A2560X
|
|
||||||
switch (chip) {
|
|
||||||
case 1:
|
|
||||||
port = PSG_INT_L_PORT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
port = PSG_INT_R_PORT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
port = PSG_INT_S_PORT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
if (frequency != 0) {
|
if (frequency != 0) {
|
||||||
n = 357954500 / (32 * frequency);
|
n = 11320 / frequency;
|
||||||
|
// n = 3579545 / (32 * frequency);
|
||||||
}
|
}
|
||||||
*port = (unsigned char)(0x80 | ((voice & 0x03) << 5) | (n & 0x0f));
|
*port = (uint8_t)(0x80 | ((voice & 0x03) << 5) | (n & 0x0f));
|
||||||
*port = (unsigned char)((n & 0x3f0) >> 4);
|
*port = (uint8_t)((n & 0x3f0) >> 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,26 +102,8 @@ void psg_tone(short chip, unsigned short voice, int frequency) {
|
||||||
* attenuation = volume level 0 = loudest, 15 = silent
|
* attenuation = volume level 0 = loudest, 15 = silent
|
||||||
*/
|
*/
|
||||||
void psg_attenuation(short chip, unsigned short voice, short attenuation) {
|
void psg_attenuation(short chip, unsigned short voice, short attenuation) {
|
||||||
volatile unsigned char * port = PSG_PORT; /* By default: external */
|
volatile uint8_t * port = psg_port(chip);
|
||||||
|
if (port) {
|
||||||
#if ( MODEL == MODEL_FOENIX_A2560K || MODEL == MODEL_FOENIX_GENX || MODEL == MODEL_FOENIX_A2560X )
|
*port = (uint8_t)(0x90 | ((voice & 0x03) << 5) | (attenuation & 0x0f));
|
||||||
switch (chip) {
|
|
||||||
case 1:
|
|
||||||
port = PSG_INT_L_PORT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
port = PSG_INT_R_PORT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
port = PSG_INT_S_PORT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
*port = (unsigned char)(0x90 | ((voice & 0x03) << 5) | (attenuation & 0x0f));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ void sid_init_all() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MODEL == MODEL_FOENIX_FMX || MODEL == MODEL_FOENIX_C256U || MODEL == MODEL_FOENIX_C256U_PLUS
|
#if MODEL == MODEL_FOENIX_FMX || MODEL == MODEL_FOENIX_C256U || MODEL == MODEL_FOENIX_C256U_PLUS || MODEL == MODEL_FOENIX_F256 || MODEL == MODEL_FOENIX_F256K || MODEL == MODEL_FOENIX_F256K2
|
||||||
/*
|
/*
|
||||||
* Test the internal SID implementation
|
* Test the internal SID implementation
|
||||||
*/
|
*/
|
||||||
|
@ -82,6 +82,8 @@ void sid_test_internal() {
|
||||||
|
|
||||||
sid = (struct s_sid *)sid_get_base(0);
|
sid = (struct s_sid *)sid_get_base(0);
|
||||||
if (sid) {
|
if (sid) {
|
||||||
|
long jiffies = 0;
|
||||||
|
|
||||||
sid->v1.attack_decay = 0x29;
|
sid->v1.attack_decay = 0x29;
|
||||||
sid->v2.attack_decay = 0x29;
|
sid->v2.attack_decay = 0x29;
|
||||||
sid->v2.attack_decay = 0x29;
|
sid->v2.attack_decay = 0x29;
|
||||||
|
@ -95,32 +97,32 @@ void sid_test_internal() {
|
||||||
sid->v1.frequency = 0x1660;
|
sid->v1.frequency = 0x1660;
|
||||||
sid->v1.control = 0x11;
|
sid->v1.control = 0x11;
|
||||||
|
|
||||||
// jiffies = rtc_get_jiffies() + 3;
|
jiffies = rtc_get_jiffies() + 3;
|
||||||
// while (jiffies > rtc_get_jiffies());
|
while (jiffies > rtc_get_jiffies());
|
||||||
|
|
||||||
// sid->v2.frequency = 0x0831;
|
sid->v2.frequency = 0x0831;
|
||||||
// sid->v2.control = 0x11;
|
sid->v2.control = 0x11;
|
||||||
|
|
||||||
// jiffies = rtc_get_jiffies() + 3;
|
jiffies = rtc_get_jiffies() + 3;
|
||||||
// while (jiffies > rtc_get_jiffies());
|
while (jiffies > rtc_get_jiffies());
|
||||||
|
|
||||||
// sid->v3.frequency = 0x2187;
|
sid->v3.frequency = 0x2187;
|
||||||
// sid->v3.control = 0x11;
|
sid->v3.control = 0x11;
|
||||||
|
|
||||||
// jiffies = rtc_get_jiffies() + 25;
|
jiffies = rtc_get_jiffies() + 25;
|
||||||
// while (jiffies > rtc_get_jiffies());
|
while (jiffies > rtc_get_jiffies());
|
||||||
|
|
||||||
// sid->v1.control = 0x10;
|
sid->v1.control = 0x10;
|
||||||
// jiffies = rtc_get_jiffies() + 3;
|
jiffies = rtc_get_jiffies() + 3;
|
||||||
// while (jiffies > rtc_get_jiffies());
|
while (jiffies > rtc_get_jiffies());
|
||||||
|
|
||||||
// sid->v2.control = 0x10;
|
sid->v2.control = 0x10;
|
||||||
// jiffies = rtc_get_jiffies() + 3;
|
jiffies = rtc_get_jiffies() + 3;
|
||||||
// while (jiffies > rtc_get_jiffies());
|
while (jiffies > rtc_get_jiffies());
|
||||||
|
|
||||||
// sid->v3.control = 0x10;
|
sid->v3.control = 0x10;
|
||||||
|
|
||||||
// sid->mode_volume = 0;
|
sid->mode_volume = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,8 +154,8 @@ void initialize() {
|
||||||
psg_mute_all();
|
psg_mute_all();
|
||||||
INFO("PSG Muted.");
|
INFO("PSG Muted.");
|
||||||
|
|
||||||
// /* Initialize and mute the SID chips */
|
/* Initialize and mute the SID chips */
|
||||||
// sid_init_all();
|
sid_init_all();
|
||||||
|
|
||||||
// // /* Initialize the Yamaha sound chips (well, turn their volume down at least) */
|
// // /* Initialize the Yamaha sound chips (well, turn their volume down at least) */
|
||||||
// // ym_init();
|
// // ym_init();
|
||||||
|
@ -184,15 +184,12 @@ void initialize() {
|
||||||
rtc_init();
|
rtc_init();
|
||||||
INFO("Real time clock initialized");
|
INFO("Real time clock initialized");
|
||||||
|
|
||||||
// target_jiffies = timers_jiffies() + 300; /* 5 seconds minimum */
|
|
||||||
// DEBUG1("target_jiffies assigned: %d", target_jiffies);
|
|
||||||
|
|
||||||
/* Enable all interrupts */
|
/* Enable all interrupts */
|
||||||
int_enable_all();
|
int_enable_all();
|
||||||
TRACE("Interrupts enabled");
|
INFO("Interrupts enabled");
|
||||||
|
|
||||||
// // /* Play the SID test bong on the Gideon SID implementation */
|
// /* Play the SID test bong on the Gideon SID implementation */
|
||||||
// // sid_test_internal();
|
// sid_test_internal();
|
||||||
|
|
||||||
#if HAS_PATA
|
#if HAS_PATA
|
||||||
if ((res = pata_install())) {
|
if ((res = pata_install())) {
|
||||||
|
@ -427,6 +424,26 @@ void test_kbd() {
|
||||||
printf("\n\n");
|
printf("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_psg() {
|
||||||
|
long target_time = rtc_get_jiffies() + (long)(60 * 2);
|
||||||
|
|
||||||
|
psg_tone(3, 0, 262);
|
||||||
|
psg_tone(3, 1, 262 * 2);
|
||||||
|
psg_tone(3, 2, 262 * 4);
|
||||||
|
|
||||||
|
psg_attenuation(3, 0, 0);
|
||||||
|
psg_attenuation(3, 1, 15);
|
||||||
|
psg_attenuation(3, 2, 15);
|
||||||
|
|
||||||
|
while (target_time > rtc_get_jiffies()) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
psg_attenuation(3, 0, 15);
|
||||||
|
psg_attenuation(3, 1, 15);
|
||||||
|
psg_attenuation(3, 2, 15);
|
||||||
|
}
|
||||||
|
|
||||||
void test_sysinfo() {
|
void test_sysinfo() {
|
||||||
// 8 x 22 region
|
// 8 x 22 region
|
||||||
t_rect region;
|
t_rect region;
|
||||||
|
@ -464,6 +481,7 @@ int main(int argc, char * argv[]) {
|
||||||
kbd_init();
|
kbd_init();
|
||||||
|
|
||||||
test_sysinfo();
|
test_sysinfo();
|
||||||
|
// test_psg();
|
||||||
test_kbd();
|
test_kbd();
|
||||||
long jiffies = timers_jiffies();
|
long jiffies = timers_jiffies();
|
||||||
printf("Jiffies: %ld\n", jiffies);
|
printf("Jiffies: %ld\n", jiffies);
|
||||||
|
|
Loading…
Reference in a new issue