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

Started iterating towards having an AY and a fully-working keyboard.

This commit is contained in:
Thomas Harte 2016-10-14 21:18:03 -04:00
parent 8867ad647c
commit d8e4c488c2
6 changed files with 217 additions and 19 deletions

View File

@ -0,0 +1,23 @@
//
// AY-3-8910.cpp
// Clock Signal
//
// Created by Thomas Harte on 14/10/2016.
// Copyright © 2016 Thomas Harte. All rights reserved.
//
#include "AY38910.hpp"
using namespace GI;
AY38910::AY38910()
{
}
void AY38910::get_samples(unsigned int number_of_samples, int16_t *target)
{
}
void AY38910::skip_samples(unsigned int number_of_samples)
{
}

View File

@ -0,0 +1,35 @@
//
// AY-3-8910.hpp
// Clock Signal
//
// Created by Thomas Harte on 14/10/2016.
// Copyright © 2016 Thomas Harte. All rights reserved.
//
#ifndef AY_3_8910_hpp
#define AY_3_8910_hpp
#include "../../Outputs/Speaker.hpp"
namespace GI {
class AY38910: public ::Outputs::Filter<AY38910> {
public:
AY38910();
void get_samples(unsigned int number_of_samples, int16_t *target);
void skip_samples(unsigned int number_of_samples);
void select_register(uint8_t r);
void set_register_value(uint8_t value);
uint8_t get_register_value();
private:
int _selected_register;
uint8_t _registers[16];
};
};
#endif /* AY_3_8910_hpp */

View File

@ -14,6 +14,8 @@ Machine::Machine() : _cycles_since_video_update(0)
{
set_clock_rate(1000000);
_via.set_interrupt_delegate(this);
_keyboard.reset(new Keyboard);
clear_all_keys();
}
void Machine::configure_as_target(const StaticAnalyser::Target &target)
@ -69,6 +71,7 @@ void Machine::update_video()
void Machine::setup_output(float aspect_ratio)
{
_videoOutput.reset(new VideoOutput(_ram));
_via.ay8910.reset(new GI::AY38910());
}
void Machine::close_output()
@ -80,3 +83,23 @@ void Machine::mos6522_did_change_interrupt_status(void *mos6522)
{
set_irq_line(_via.get_interrupt_line());
}
void Machine::set_key_state(Key key, bool isPressed)
{
if(key == KeyNMI)
{
set_nmi_line(isPressed);
}
else
{
if(isPressed)
_keyboard->rows[key >> 8] |= (key & 0xff);
else
_keyboard->rows[key >> 8] &= ~(key & 0xff);
}
}
void Machine::clear_all_keys()
{
memset(_keyboard->rows, 0, sizeof(_keyboard->rows));
}

View File

@ -11,6 +11,7 @@
#include "../../Processors/6502/CPU6502.hpp"
#include "../../Components/6522/6522.hpp"
#include "../../Components/AY38910/AY38910.hpp"
#include "../../Storage/Tape/Tape.hpp"
#include "../ConfigurationTarget.hpp"
@ -24,24 +25,25 @@
namespace Oric {
class VIA: public MOS::MOS6522<VIA>, public MOS::MOS6522IRQDelegate {
public:
using MOS6522IRQDelegate::set_interrupt_status;
enum Key: uint16_t {
Key3 = 0x0000 | 0x80, KeyX = 0x0000 | 0x40, Key1 = 0x0000 | 0x20,
KeyV = 0x0000 | 0x08, Key5 = 0x0000 | 0x04, KeyN = 0x0000 | 0x02, Key7 = 0x0000 | 0x01,
KeyD = 0x0100 | 0x80, KeyQ = 0x0100 | 0x40, KeyEscape = 0x0100 | 0x20,
KeyF = 0x0100 | 0x08, KeyR = 0x0100 | 0x04, KeyT = 0x0100 | 0x02, KeyJ = 0x0100 | 0x01,
KeyC = 0x0200 | 0x80, Key2 = 0x0200 | 0x40, KeyZ = 0x0200 | 0x20, KeyControl = 0x0200 | 0x10,
Key4 = 0x0200 | 0x08, KeyB = 0x0200 | 0x04, Key6 = 0x0200 | 0x02, KeyM = 0x0200 | 0x01,
KeyQuote = 0x0300 | 0x80, KeyBackSlash = 0x0300 | 0x40,
KeyMinus = 0x0300 | 0x08, KeySemiColon = 0x0300 | 0x04, Key9 = 0x0300 | 0x02, KeyK = 0x0300 | 0x01,
KeyRight = 0x0400 | 0x80, KeyDown = 0x0400 | 0x40, KeyLeft = 0x0400 | 0x20, KeyLeftShift = 0x0400 | 0x10,
KeyUp = 0x0400 | 0x08, KeyFullStop = 0x0400 | 0x04, KeyComma = 0x0400 | 0x02, KeySpace = 0x0400 | 0x01,
KeyOpenSquare = 0x0500 | 0x80, KeyCloseSquare = 0x0500 | 0x40, KeyDelete = 0x0500 | 0x20, KeyFunction = 0x0500 | 0x10,
KeyP = 0x0500 | 0x08, KeyO = 0x0500 | 0x04, KeyI = 0x0500 | 0x02, KeyU = 0x0500 | 0x01,
KeyW = 0x0600 | 0x80, KeyS = 0x0600 | 0x40, KeyA = 0x0600 | 0x20,
KeyE = 0x0600 | 0x08, KeyG = 0x0600 | 0x04, KeyH = 0x0600 | 0x02, KeyY = 0x0600 | 0x01,
KeyEquals = 0x0700 | 0x80, KeyReturn = 0x0700 | 0x20, KeyRightShift = 0x0700 | 0x10,
KeyForwardSlash = 0x0700 | 0x08, Key0 = 0x0700 | 0x04, KeyL = 0x0700 | 0x02, Key8 = 0x0700 | 0x01,
void set_port_output(Port port, uint8_t value, uint8_t direction_mask) {
port_outputs[port] = value;
if(port)
set_control_line_input(port, Line::One, (value << 1)&value&128);
}
uint8_t get_port_input(Port port) {
if(port)
{
return port_outputs[0];
}
else
return (uint8_t)((port_outputs[port] >> 4) | (port_outputs[port] << 4));
}
uint8_t port_outputs[2];
KeyNMI = 0xffff,
};
class Machine:
@ -54,6 +56,8 @@ class Machine:
Machine();
void set_rom(std::vector<uint8_t> data);
void set_key_state(Key key, bool isPressed);
void clear_all_keys();
// to satisfy ConfigurationTarget::Machine
void configure_as_target(const StaticAnalyser::Target &target);
@ -82,7 +86,35 @@ class Machine:
std::unique_ptr<VideoOutput> _videoOutput;
//
class Keyboard {
public:
uint8_t row, column;
uint8_t rows[8];
};
class VIA: public MOS::MOS6522<VIA>, public MOS::MOS6522IRQDelegate {
public:
using MOS6522IRQDelegate::set_interrupt_status;
void set_port_output(Port port, uint8_t value, uint8_t direction_mask) {
port_outputs[port] = value;
if(port)
set_control_line_input(port, Line::One, (value << 1)&value&128);
}
uint8_t get_port_input(Port port) {
if(port)
{
return port_outputs[0];
}
else
return (uint8_t)((port_outputs[port] >> 4) | (port_outputs[port] << 4));
}
uint8_t port_outputs[2];
std::unique_ptr<GI::AY38910> ay8910;
std::shared_ptr<Keyboard> keyboard;
};
VIA _via;
std::shared_ptr<Keyboard> _keyboard;
};
}

View File

@ -37,6 +37,7 @@
4B3BA0CF1D318B44005DD7A7 /* MOS6522Bridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B3BA0C91D318B44005DD7A7 /* MOS6522Bridge.mm */; };
4B3BA0D01D318B44005DD7A7 /* MOS6532Bridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B3BA0CB1D318B44005DD7A7 /* MOS6532Bridge.mm */; };
4B3BA0D11D318B44005DD7A7 /* TestMachine.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B3BA0CD1D318B44005DD7A7 /* TestMachine.mm */; };
4B4A76301DB1A3FA007AAE2E /* AY38910.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4A762E1DB1A3FA007AAE2E /* AY38910.cpp */; };
4B4C83701D4F623200CD541F /* D64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4C836E1D4F623200CD541F /* D64.cpp */; };
4B4DC8211D2C2425003C5BF8 /* Vic20.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC81F1D2C2425003C5BF8 /* Vic20.cpp */; };
4B4DC8281D2C2470003C5BF8 /* C1540.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4DC8261D2C2470003C5BF8 /* C1540.cpp */; };
@ -458,6 +459,8 @@
4B3BA0CB1D318B44005DD7A7 /* MOS6532Bridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MOS6532Bridge.mm; sourceTree = "<group>"; };
4B3BA0CC1D318B44005DD7A7 /* TestMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestMachine.h; sourceTree = "<group>"; };
4B3BA0CD1D318B44005DD7A7 /* TestMachine.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TestMachine.mm; sourceTree = "<group>"; };
4B4A762E1DB1A3FA007AAE2E /* AY38910.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AY38910.cpp; path = AY38910/AY38910.cpp; sourceTree = "<group>"; };
4B4A762F1DB1A3FA007AAE2E /* AY38910.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = AY38910.hpp; path = AY38910/AY38910.hpp; sourceTree = "<group>"; };
4B4C836E1D4F623200CD541F /* D64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = D64.cpp; sourceTree = "<group>"; };
4B4C836F1D4F623200CD541F /* D64.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = D64.hpp; sourceTree = "<group>"; };
4B4DC81F1D2C2425003C5BF8 /* Vic20.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Vic20.cpp; sourceTree = "<group>"; };
@ -1050,6 +1053,15 @@
path = Bridges;
sourceTree = "<group>";
};
4B4A762D1DB1A35C007AAE2E /* AY38910 */ = {
isa = PBXGroup;
children = (
4B4A762E1DB1A3FA007AAE2E /* AY38910.cpp */,
4B4A762F1DB1A3FA007AAE2E /* AY38910.hpp */,
);
name = AY38910;
sourceTree = "<group>";
};
4B4DC81D1D2C2425003C5BF8 /* Commodore */ = {
isa = PBXGroup;
children = (
@ -1654,10 +1666,11 @@
4BC9DF4A1D04691600F44158 /* Components */ = {
isa = PBXGroup;
children = (
4BD468F81D8DF4290084958B /* 1770 */,
4BC9DF4B1D04691600F44158 /* 6522 */,
4B1E85791D174DEC001EF87D /* 6532 */,
4BC9DF4C1D04691600F44158 /* 6560 */,
4BD468F81D8DF4290084958B /* 1770 */,
4B4A762D1DB1A35C007AAE2E /* AY38910 */,
);
name = Components;
path = ../../Components;
@ -2250,6 +2263,7 @@
4B55CE5D1C3B7D6F0093A61B /* CSOpenGLView.m in Sources */,
4BB697CB1D4B6D3E00248BDF /* TimedEventLoop.cpp in Sources */,
4BF1354C1D6D2C300054B2EA /* StaticAnalyser.cpp in Sources */,
4B4A76301DB1A3FA007AAE2E /* AY38910.cpp in Sources */,
4B2A53A31D117D36003C6002 /* CSVic20.mm in Sources */,
4B2A53A21D117D36003C6002 /* CSElectron.mm in Sources */,
4B8FE2201DA19D7C0090D3CE /* Atari2600OptionsPanel.swift in Sources */,

View File

@ -45,7 +45,78 @@
- (void)setKey:(uint16_t)key isPressed:(BOOL)isPressed
{
_oric.set_nmi_line(isPressed);
@synchronized(self) {
switch(key)
{
/* case VK_ANSI_0: _oric.set_key_state(Oric::Key::Key0, isPressed); break;
case VK_ANSI_1: _oric.set_key_state(Oric::Key::Key1, isPressed); break;
case VK_ANSI_2: _oric.set_key_state(Oric::Key::Key2, isPressed); break;
case VK_ANSI_3: _oric.set_key_state(Oric::Key::Key3, isPressed); break;
case VK_ANSI_4: _oric.set_key_state(Oric::Key::Key4, isPressed); break;
case VK_ANSI_5: _oric.set_key_state(Oric::Key::Key5, isPressed); break;
case VK_ANSI_6: _oric.set_key_state(Oric::Key::Key6, isPressed); break;
case VK_ANSI_7: _oric.set_key_state(Oric::Key::Key7, isPressed); break;
case VK_ANSI_8: _oric.set_key_state(Oric::Key::Key8, isPressed); break;
case VK_ANSI_9: _oric.set_key_state(Oric::Key::Key9, isPressed); break;
case VK_ANSI_Q: _oric.set_key_state(Oric::Key::KeyQ, isPressed); break;
case VK_ANSI_W: _oric.set_key_state(Oric::Key::KeyW, isPressed); break;
case VK_ANSI_E: _oric.set_key_state(Oric::Key::KeyE, isPressed); break;
case VK_ANSI_R: _oric.set_key_state(Oric::Key::KeyR, isPressed); break;
case VK_ANSI_T: _oric.set_key_state(Oric::Key::KeyT, isPressed); break;
case VK_ANSI_Y: _oric.set_key_state(Oric::Key::KeyY, isPressed); break;
case VK_ANSI_U: _oric.set_key_state(Oric::Key::KeyU, isPressed); break;
case VK_ANSI_I: _oric.set_key_state(Oric::Key::KeyI, isPressed); break;
case VK_ANSI_O: _oric.set_key_state(Oric::Key::KeyO, isPressed); break;
case VK_ANSI_P: _oric.set_key_state(Oric::Key::KeyP, isPressed); break;
case VK_ANSI_A: _oric.set_key_state(Oric::Key::KeyA, isPressed); break;
case VK_ANSI_S: _oric.set_key_state(Oric::Key::KeyS, isPressed); break;
case VK_ANSI_D: _oric.set_key_state(Oric::Key::KeyD, isPressed); break;
case VK_ANSI_F: _oric.set_key_state(Oric::Key::KeyF, isPressed); break;
case VK_ANSI_G: _oric.set_key_state(Oric::Key::KeyG, isPressed); break;
case VK_ANSI_H: _oric.set_key_state(Oric::Key::KeyH, isPressed); break;
case VK_ANSI_J: _oric.set_key_state(Oric::Key::KeyJ, isPressed); break;
case VK_ANSI_K: _oric.set_key_state(Oric::Key::KeyK, isPressed); break;
case VK_ANSI_L: _oric.set_key_state(Oric::Key::KeyL, isPressed); break;
case VK_ANSI_Z: _oric.set_key_state(Oric::Key::KeyZ, isPressed); break;
case VK_ANSI_X: _oric.set_key_state(Oric::Key::KeyX, isPressed); break;
case VK_ANSI_C: _oric.set_key_state(Oric::Key::KeyC, isPressed); break;
case VK_ANSI_V: _oric.set_key_state(Oric::Key::KeyV, isPressed); break;
case VK_ANSI_B: _oric.set_key_state(Oric::Key::KeyB, isPressed); break;
case VK_ANSI_N: _oric.set_key_state(Oric::Key::KeyN, isPressed); break;
case VK_ANSI_M: _oric.set_key_state(Oric::Key::KeyM, isPressed); break;
case VK_Space: _oric.set_key_state(Oric::Key::KeySpace, isPressed); break;
case VK_Return: _oric.set_key_state(Oric::Key::KeyReturn, isPressed); break;
case VK_ANSI_Minus: _oric.set_key_state(Oric::Key::KeyMinus, isPressed); break;
case VK_RightArrow: _oric.set_key_state(Oric::Key::KeyRight, isPressed); break;
case VK_LeftArrow: _oric.set_key_state(Oric::Key::KeyLeft, isPressed); break;
case VK_DownArrow: _oric.set_key_state(Oric::Key::KeyDown, isPressed); break;
case VK_UpArrow: _oric.set_key_state(Oric::Key::KeyUp, isPressed); break;
case VK_Delete: _oric.set_key_state(Oric::Key::KeyDelete, isPressed); break;
case VK_Escape: _oric.set_key_state(Oric::Key::KeyEscape, isPressed); break;
case VK_ANSI_Comma: _oric.set_key_state(Oric::Key::KeyComma, isPressed); break;
case VK_ANSI_Period: _oric.set_key_state(Oric::Key::KeyFullStop, isPressed); break;
case VK_ANSI_Semicolon:
_oric.set_key_state(Oric::Key::KeySemiColon, isPressed); break;
case VK_Shift: _oric.set_key_state(Oric::Key::KeyLeftShift, isPressed); break;
case VK_RightShift: _oric.set_key_state(Oric::Key::KeyRightShift, isPressed); break;
case VK_Control: _oric.set_key_state(Oric::Key::KeyControl, isPressed); break;
case VK_Command:*/
case VK_ANSI_Grave:
case VK_F12: _oric.set_key_state(Oric::Key::KeyNMI, isPressed); break;
default:
printf("%02x\n", key);
break;
}
}
}
- (void)clearAllKeys