1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-07 23:29:06 +00:00

Added some documentation, made the speaker private.

This commit is contained in:
Thomas Harte 2016-06-14 20:00:16 -04:00
parent 3e1e5b163a
commit 926f819e3b
2 changed files with 49 additions and 26 deletions

View File

@ -25,7 +25,6 @@ MOS6560::MOS6560() :
"uint yC = c & 15u;"
"float phaseOffset = 6.283185308 * float(yC) / 16.0;"
// "float chroma = step(mod(phase + phaseOffset + 0.785398163397448, 6.283185308), 3.141592654);"
"float chroma = cos(phase + phaseOffset);"
"return mix(y, step(yC, 14) * chroma, amplitude);"
"}");
@ -140,6 +139,7 @@ void MOS6560::output_border(unsigned int number_of_cycles)
uint16_t MOS6560::get_address()
{
// keep track of the amount of time since the speaker was updated; lazy updates are applied
_cycles_since_speaker_update++;
_horizontal_counter++;
@ -316,20 +316,19 @@ void MOS6560::update_audio()
#pragma mark - Audio
MOS6560Speaker::MOS6560Speaker() :
MOS6560::Speaker::Speaker() :
_volume(0),
_control_registers{0, 0, 0, 0},
_shift_registers{0, 0, 0, 0},
_counters{2, 1, 0, 0} // create a slight phase offset for the three channels
{
}
{}
void MOS6560Speaker::set_volume(uint8_t volume)
void MOS6560::Speaker::set_volume(uint8_t volume)
{
_volume = volume;
}
void MOS6560Speaker::set_control(int channel, uint8_t value)
void MOS6560::Speaker::set_control(int channel, uint8_t value)
{
_control_registers[channel] = value;
}
@ -402,11 +401,11 @@ static uint8_t noise_pattern[] = {
0xf0, 0xe1, 0xe0, 0x78, 0x70, 0x38, 0x3c, 0x3e, 0x1e, 0x3c, 0x1e, 0x1c, 0x70, 0x3c, 0x38, 0x3f,
};
#define shift(r) _shift_registers[r] = (uint8_t)((_shift_registers[r] << 1) | (((_shift_registers[r]^0x80)&_control_registers[r]) >> 7));
#define shift(r) _shift_registers[r] = (_shift_registers[r] << 1) | (((_shift_registers[r]^0x80)&_control_registers[r]) >> 7);
#define increment(r) _shift_registers[r] = (_shift_registers[r]+1)%8191;
#define update(r, m, up) _counters[r]++; if((_counters[r] >> m) == 0x7f) { up(r); _counters[r] = _control_registers[r]&0x7f; }
void MOS6560Speaker::get_samples(unsigned int number_of_samples, int16_t *target)
void MOS6560::Speaker::get_samples(unsigned int number_of_samples, int16_t *target)
{
for(unsigned int c = 0; c < number_of_samples; c++)
{
@ -424,7 +423,7 @@ void MOS6560Speaker::get_samples(unsigned int number_of_samples, int16_t *target
}
}
void MOS6560Speaker::skip_samples(unsigned int number_of_samples)
void MOS6560::Speaker::skip_samples(unsigned int number_of_samples)
{
for(unsigned int c = 0; c < number_of_samples; c++)
{

View File

@ -14,40 +14,64 @@
namespace MOS {
class MOS6560Speaker: public ::Outputs::Filter<MOS6560Speaker> {
public:
MOS6560Speaker();
/*!
The 6560 is a video and audio output chip; it therefore vends both a @c CRT and a @c Speaker.
void set_volume(uint8_t volume);
void set_control(int channel, uint8_t value);
void get_samples(unsigned int number_of_samples, int16_t *target);
void skip_samples(unsigned int number_of_samples);
private:
unsigned int _counters[4];
uint8_t _shift_registers[4];
uint8_t _control_registers[4];
uint8_t _volume;
};
To run the 6560 for a cycle, the caller should call @c get_address, make the requested bus access
and call @c set_graphics_value with the result.
@c set_register and @c get_register provide register access.
*/
class MOS6560 {
public:
MOS6560();
Outputs::CRT::CRT *get_crt() { return _crt.get(); }
Outputs::Speaker *get_speaker() { return &_speaker; }
/*!
Impliedly runs the 6560 for a single cycle, returning the next address that it puts on the bus.
*/
uint16_t get_address();
/*!
An owning machine should determine the state of the data bus as a result of the access implied
by @c get_address and supply it to set_graphics_value.
*/
void set_graphics_value(uint8_t value, uint8_t colour_value);
void synchronise() { update_audio(); }
/*!
Causes the 6560 to flush as much pending CRT and speaker communications as possible.
*/
inline void synchronise() { update_audio(); }
/*!
Writes to a 6560 register.
*/
void set_register(int address, uint8_t value);
/*
Reads from a 6560 register.
*/
uint8_t get_register(int address);
private:
std::unique_ptr<Outputs::CRT::CRT> _crt;
MOS6560Speaker _speaker;
class Speaker: public ::Outputs::Filter<Speaker> {
public:
Speaker();
void set_volume(uint8_t volume);
void set_control(int channel, uint8_t value);
void get_samples(unsigned int number_of_samples, int16_t *target);
void skip_samples(unsigned int number_of_samples);
private:
unsigned int _counters[4];
unsigned int _shift_registers[4];
uint8_t _control_registers[4];
uint8_t _volume;
} _speaker;
bool _interlaced, _tall_characters;
uint8_t _first_column_location, _first_row_location;