From 926f819e3b9a93a2d0649b74e0a13d25845b5171 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Tue, 14 Jun 2016 20:00:16 -0400 Subject: [PATCH 1/2] Added some documentation, made the speaker private. --- Components/6560/6560.cpp | 17 ++++++------ Components/6560/6560.hpp | 58 ++++++++++++++++++++++++++++------------ 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/Components/6560/6560.cpp b/Components/6560/6560.cpp index f22b69204..43060ec78 100644 --- a/Components/6560/6560.cpp +++ b/Components/6560/6560.cpp @@ -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++) { diff --git a/Components/6560/6560.hpp b/Components/6560/6560.hpp index 59a73d8f4..8f107462f 100644 --- a/Components/6560/6560.hpp +++ b/Components/6560/6560.hpp @@ -14,40 +14,64 @@ namespace MOS { -class MOS6560Speaker: public ::Outputs::Filter { - 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 _crt; - MOS6560Speaker _speaker; + class Speaker: public ::Outputs::Filter { + 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; From ce7488dd3014e940ce9e16bf6772a0c3d279861b Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Tue, 14 Jun 2016 21:06:29 -0400 Subject: [PATCH 2/2] Added support for _invertedCells. Treading water a little before making real changes. --- Components/6560/6560.cpp | 33 ++++++++++++++++++++++++--------- Components/6560/6560.hpp | 1 + 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/Components/6560/6560.cpp b/Components/6560/6560.cpp index 43060ec78..32c2b02d5 100644 --- a/Components/6560/6560.cpp +++ b/Components/6560/6560.cpp @@ -107,7 +107,7 @@ void MOS6560::set_register(int address, uint8_t value) output_border(_cycles_in_state * 4); _cycles_in_state = 0; } - _invertedCells = !!((value >> 3)&1); + _invertedCells = !((value >> 3)&1); _borderColour = _colours[value & 0x07]; _backgroundColour = _colours[value >> 4]; break; @@ -142,10 +142,14 @@ 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++; + // keep track of internal time relative to this scanline _horizontal_counter++; + + // check for end of scanline if(_horizontal_counter == 65) { _horizontal_counter = 0; + _vertical_counter++; _column_counter = -1; @@ -276,14 +280,25 @@ void MOS6560::set_graphics_value(uint8_t value, uint8_t colour_value) uint8_t cell_colour = _colours[_character_colour & 0x7]; if(!(_character_colour&0x8)) { - pixel_pointer[0] = ((_character_value >> 7)&1) ? cell_colour : _backgroundColour; - pixel_pointer[1] = ((_character_value >> 6)&1) ? cell_colour : _backgroundColour; - pixel_pointer[2] = ((_character_value >> 5)&1) ? cell_colour : _backgroundColour; - pixel_pointer[3] = ((_character_value >> 4)&1) ? cell_colour : _backgroundColour; - pixel_pointer[4] = ((_character_value >> 3)&1) ? cell_colour : _backgroundColour; - pixel_pointer[5] = ((_character_value >> 2)&1) ? cell_colour : _backgroundColour; - pixel_pointer[6] = ((_character_value >> 1)&1) ? cell_colour : _backgroundColour; - pixel_pointer[7] = ((_character_value >> 0)&1) ? cell_colour : _backgroundColour; + uint8_t colours[2]; + if(_invertedCells) + { + colours[0] = cell_colour; + colours[1] = _backgroundColour; + } + else + { + colours[0] = _backgroundColour; + colours[1] = cell_colour; + } + pixel_pointer[0] = colours[(_character_value >> 7)&1]; + pixel_pointer[1] = colours[(_character_value >> 6)&1]; + pixel_pointer[2] = colours[(_character_value >> 5)&1]; + pixel_pointer[3] = colours[(_character_value >> 4)&1]; + pixel_pointer[4] = colours[(_character_value >> 3)&1]; + pixel_pointer[5] = colours[(_character_value >> 2)&1]; + pixel_pointer[6] = colours[(_character_value >> 1)&1]; + pixel_pointer[7] = colours[(_character_value >> 0)&1]; } else { diff --git a/Components/6560/6560.hpp b/Components/6560/6560.hpp index 8f107462f..bad97523e 100644 --- a/Components/6560/6560.hpp +++ b/Components/6560/6560.hpp @@ -81,6 +81,7 @@ class MOS6560 { bool _invertedCells; int _horizontal_counter, _vertical_counter; + bool _did_output_graphics; int _column_counter, _row_counter; uint16_t _video_matrix_address_counter, _video_matrix_line_address_counter;