From 75c3e2dacda201d7afa5031c7fcb0680bab889dd Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 20 Oct 2019 23:07:19 -0400 Subject: [PATCH] Adds basic, incomplete dispatcher for the intelligent keyboard. --- Machines/AtariST/AtariST.cpp | 144 ++++++++++++++++++++++++++++++++++- 1 file changed, 141 insertions(+), 3 deletions(-) diff --git a/Machines/AtariST/AtariST.cpp b/Machines/AtariST/AtariST.cpp index efc455bc1..c9596dbb7 100644 --- a/Machines/AtariST/AtariST.cpp +++ b/Machines/AtariST/AtariST.cpp @@ -40,13 +40,14 @@ class IntelligentKeyboard: public: IntelligentKeyboard(Serial::Line &input, Serial::Line &output) : output_line_(output) { input.set_read_delegate(this, Storage::Time(2, 15625)); + output_line_.set_writer_clock_rate(15625); } bool serial_line_did_produce_bit(Serial::Line *, int bit) final { command_ = (command_ >> 1) | (bit << 9); bit_count_ = (bit_count_ + 1) % 10; if(!bit_count_) { - LOG("[IKBD] Should perform " << PADHEX(2) << ((command_ >> 1) & 0xff)); + dispatch_command(uint8_t(command_ >> 1)); command_ = 0; return false; } @@ -54,10 +55,148 @@ class IntelligentKeyboard: } private: + // MARK: - Serial line state. int bit_count_ = 0; int command_ = 0; Serial::Line &output_line_; - float bit_offset_ = 0.0f; + + void output_byte(uint8_t value) { + // Wrap the value in a start and stop bit, and send it on its way. + output_line_.write(2, 10, 0x200 | (value << 1)); + } + + // MARK: - Command dispatch. + std::vector command_sequence_; + void dispatch_command(uint8_t command) { + // Enqueue for parsing. + command_sequence_.push_back(command); + + // For each possible command, check that the proper number of bytes are present. + // If not, exit. If so, perform and drop out of the switch. + switch(command_sequence_.front()) { + default: + printf("Unrecognised IKBD command %02x\n", command); + break; + + case 0x80: + /* + Reset: 0x80 0x01. + "Any byte following an 0x80 command byte other than 0x01 is ignored (and causes the 0x80 to be ignored)." + */ + if(command_sequence_.size() != 2) return; + if(command_sequence_[1] == 0x01) { + reset(); + } + break; + + case 0x07: + if(command_sequence_.size() != 2) return; + set_mouse_button_actions(command_sequence_[1]); + break; + + case 0x08: + set_relative_mouse_position_reporting(); + break; + + case 0x09: + if(command_sequence_.size() != 5) return; + set_absolute_mouse_position_reporting( + uint16_t((command_sequence_[1] << 8) | command_sequence_[2]), + uint16_t((command_sequence_[3] << 8) | command_sequence_[4]) + ); + break; + + case 0x0a: + if(command_sequence_.size() != 3) return; + set_mouse_keycode_reporting(command_sequence_[1], command_sequence_[2]); + break; + + case 0x0b: + if(command_sequence_.size() != 3) return; + set_mouse_threshold(command_sequence_[1], command_sequence_[2]); + break; + + case 0x0c: + if(command_sequence_.size() != 3) return; + set_mouse_scale(command_sequence_[1], command_sequence_[2]); + break; + + case 0x0d: + interrogate_mouse_position(); + break; + + case 0x0e: + if(command_sequence_.size() != 6) return; + /* command_sequence_[1] has no defined meaning. */ + set_mouse_position( + uint16_t((command_sequence_[2] << 8) | command_sequence_[3]), + uint16_t((command_sequence_[4] << 8) | command_sequence_[5]) + ); + break; + + case 0x0f: set_mouse_y_upward(); break; + case 0x10: set_mouse_y_downward(); break; + case 0x11: resume(); break; + case 0x12: disable_mouse(); break; + case 0x13: pause(); break; + case 0x1a: disable_joysticks(); break; + } + + // There was no premature exit, so a complete command sequence must have been satisfied. + command_sequence_.clear(); + } + + // MARK: - Flow control. + void reset() { + // Reset should perform a self test, lasting at most 200ms, then post 0xf0. + // Following that it should look for any keys that currently seem to be pressed. + // Those are considered stuck and a break code is generated for them. + output_byte(0xf0); + } + + void resume() { + } + + void pause() { + } + + // MARK: - Mouse commands. + void disable_mouse() { + } + + void set_relative_mouse_position_reporting() { + } + + void set_absolute_mouse_position_reporting(uint16_t max_x, uint16_t max_y) { + } + + void set_mouse_position(uint16_t x, uint16_t y) { + } + + void set_mouse_keycode_reporting(uint8_t delta_x, uint8_t delta_y) { + } + + void set_mouse_threshold(uint8_t x, uint8_t y) { + } + + void set_mouse_scale(uint8_t x, uint8_t y) { + } + + void set_mouse_y_downward() { + } + + void set_mouse_y_upward() { + } + + void set_mouse_button_actions(uint8_t actions) { + } + + void interrogate_mouse_position() { + } + + // MARK: - Joystick commands. + void disable_joysticks() { + } }; using Target = Analyser::Static::Target; @@ -396,7 +535,6 @@ class ConcreteMachine: // TODO: push v/hsync/display_enable elsewhere. mfp_->set_timer_event_input(1, video_->display_enabled()); -// printf("%c%c%c\n", video_->display_enabled() ? 'e' : '-', video_->hsync() ? 'h' : '-', video_->vsync() ? 'v' : '-'); } cycles_until_video_event_ -= length; video_ += length;