Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is SoundCortex readable? #9

Open
Kyuchumimo opened this issue Jul 26, 2024 · 5 comments
Open

Is SoundCortex readable? #9

Kyuchumimo opened this issue Jul 26, 2024 · 5 comments

Comments

@Kyuchumimo
Copy link

Kyuchumimo commented Jul 26, 2024

I am using SoundCortexLPC and I can write data perfectly well to it via I2C, but I can't seem to read data.

With PSG registers I always get 0xA1 as answer.
With SCC addresses I almost always get 0xA3 as answer.
This seems to match the addresses of the IOEXT protocol.

If you build it with IOEXT support enabled, IO ports are assigned as

* 0xA0: PSG address latch
* 0xA1: PSG data read/write
* 0xA2: SCC address latch
* 0xA3: SCC data read/write

I use MicroPython, and the code I use for testing is as follows:

  • For PSG
for reg in range(16):
    _i2c0.readfrom_mem(0x50, reg, 2)

Which returns the following:

1 ... b'\xa1\xa1'
2 ... b'\xa1\xa1'
3 ... b'\xa1\xa1'
...
14 ... b'\xa1\xa1'
15 ... b'\xa1\xa1'
16 ... b'\xa1\xa1'
  • For SCC
for reg in range(256):
    _i2c0.readfrom_mem(0x51, reg, 2)

Which returns the following:

1 ... b'\xa3\xa3'
2 ... b'\xa3\xa3'
3 ... b'\xa3\xa3'
...
254 ... b'\xa3\xa3'
255 ... b'\x01\x01'
256 ... b'\x01\x01'
@toyoshim
Copy link
Owner

Registers here don't mean the emulated chip's register, but a specially assigned register to realize a library specific function, i.e. reading the library version.

https://github.com/toyoshim/SoundCortex/blob/master/src/SCC.c#L108
https://github.com/toyoshim/SoundCortex/blob/master/src/SCC.c#L108

Implementation is here.

@Kyuchumimo
Copy link
Author

Kyuchumimo commented Jul 28, 2024

I want to implement that the mixers of both sound chips are readable as they are registers / memory adresses that need to be bit modified. Is this the right way to do it?

PSG.c

bool PSGRead(uint8_t reg, uint8_t* value) {
  switch (reg) {
  case 0x07:  // mixer
    for (int i = 0; i < 3; ++i) {
      *value |= PSGWork.synth[i].tone << i;
      *value |= PSGWork.synth[i].noise << i + 3;
    }
    break;
  case 0xfe:  // minor version
    *value = 1;
    break;
  case 0xff:  // major version
    *value = 1;
    break;
  default:
    return false;
  }
  return true;
}

SCC.c

bool SCCRead(uint8_t reg, uint8_t* value) {
  switch (reg) {
  case 0xaf:  // mixer
    for (int i = 0; i < 5; ++i) {
      *value |= SCCWork.synth[i].tone << i;
    }
    break;
  case 0xfe:  // minor version
    *value = 1;
    break;
  case 0xff:  // major version
    *value = 1;
    break;
  default:
    return false;
  }
  return true;
}

@toyoshim
Copy link
Owner

Do you really need to implement this in the SoundCortex side?
I think your code should know what was written last time as your code was the single writer in your system?
Adding a local cache in your code would work effectively as a query via i2c costs. Also I would like to keep the code for the SoundCortex as small as possible.

@Kyuchumimo
Copy link
Author

Kyuchumimo commented Jul 30, 2024

Not really.

I had already thought about the other way you mention, but since the original sound chips can be read, it seemed like a good idea to have it implemented.

@Kyuchumimo
Copy link
Author

Kyuchumimo commented Aug 6, 2024

I took the trouble to fill in all the remaining registers and memory addresses. I could make a pull request, but since you say that you are not interested in making the microcontroller readable due to memory space issues, it doesn't make much sense, but I'll leave it anyway in case someone else is interested in the future.

PSG.c

// PSG.c

bool PSGRead(uint8_t reg, uint8_t* value) {
  switch (reg) {
  case 0x00:  // TP[7:0] for Ch.A
    *value = PSGWork.channel[0].tp & 0xff;
    break;
  case 0x01:  // TP[11:8] for Ch.A
    *value = PSGWork.channel[0].tp >> 8;
    break;
  case 0x02:  // TP[7:0] for Ch.B
    *value = PSGWork.channel[1].tp & 0xff;
    break;
  case 0x03:  // TP[11:8] for Ch.B
    *value = PSGWork.channel[1].tp >> 8;
    break;
  case 0x04:  // TP[7:0] for Ch.C
    *value = PSGWork.channel[2].tp & 0xff;
    break;
  case 0x05:  // TP[11:8] for Ch.C
    *value = PSGWork.channel[2].tp >> 8;
    break;
  case 0x06:  // NP[4:0]
    *value = PSGWork.noise.np;
    break;
  case 0x07:  // mixer
    for (int i = 0; i < 3; ++i) {
      *value |= PSGWork.synth[i].tone << i;
      *value |= PSGWork.synth[i].noise << i + 3;
    }
    break;
  case 0x08:  // M/L[3:0] for Ch.A
    *value = PSGWork.channel[0].ml;
    break;
  case 0x09:  // M/L[3:0] for Ch.B
    *value = PSGWork.channel[1].ml;
    break;
  case 0x0a:  // M/L[3:0] for Ch.C
    *value = PSGWork.channel[2].ml;
    break;
  case 0x0b:  // EP[7:0]
  case 0x0c:  // EP[15:8]
  case 0x0d:  // CONT/ATT/ALT/HOLD
    // TODO: support envelope.
    break;
  case 0x0e:
  case 0x0f:
    break;
  case 0xfe:  // minor version
    *value = 1;
    break;
  case 0xff:  // major version
    *value = 1;
    break;
  default:
    return false;
  }
  return true;
}

SCC.c

// SCC.c

bool SCCRead(uint8_t reg, uint8_t* value) {
  // Register map is compatible with SCC+.
  if (reg <= 0x9f) {
    int ch = reg >> 5;
    int offset = reg & 0x1f;
    *value = SCCWork.synth[ch].wt[offset];
  } else if (reg <= 0xa9) {
    int ch = (reg - 0xa0) >> 1;
    if (reg & 1)
      *value = SCCWork.channel[ch].tp >> 8;
    else
      *value = SCCWork.channel[ch].tp & 0xff;
  } else if (reg <= 0xae) {
    int ch = reg - 0xaa;
    *value = SCCWork.channel[ch].ml;
  } else if (reg == 0xaf) {
    for (int i = 0; i < 5; ++i) {
      *value |= SCCWork.synth[i].tone << i;
    }
  } else if (reg == 0xfe) {
    // minor version
    *value = 1;
  } else if (reg == 0xff) {
    // major version
    *value = 1;
  } else {
    return false;
  }
  return true;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants