From 4bf81d3b90a03ac9e7dd815dfe842fc7fa7a60fb Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 12 Oct 2019 18:19:55 -0400 Subject: [PATCH] Decodes the 6850 control register, and starts working on standardised serial ports. --- Components/6850/6850.cpp | 28 ++++++++ Components/6850/6850.hpp | 8 +++ Components/SerialPort/SerialPort.cpp | 9 +++ Components/SerialPort/SerialPort.hpp | 71 +++++++++++++++++++ .../Clock Signal.xcodeproj/project.pbxproj | 16 +++++ 5 files changed, 132 insertions(+) create mode 100644 Components/SerialPort/SerialPort.cpp create mode 100644 Components/SerialPort/SerialPort.hpp diff --git a/Components/6850/6850.cpp b/Components/6850/6850.cpp index 3809dd97e..5e2571a5c 100644 --- a/Components/6850/6850.cpp +++ b/Components/6850/6850.cpp @@ -30,6 +30,30 @@ void ACIA::write(int address, uint8_t value) { if((value&3) == 3) { LOG("Reset"); } else { + switch(value & 3) { + default: + case 0: divider_ = 1; break; + case 1: divider_ = 16; break; + case 2: divider_ = 64; break; + } + switch((value >> 2) & 7) { + default: + case 0: word_size_ = 7; stop_bits_ = 2; parity_ = Parity::Even; break; + case 1: word_size_ = 7; stop_bits_ = 2; parity_ = Parity::Odd; break; + case 2: word_size_ = 7; stop_bits_ = 1; parity_ = Parity::Even; break; + case 3: word_size_ = 7; stop_bits_ = 1; parity_ = Parity::Odd; break; + case 4: word_size_ = 8; stop_bits_ = 2; parity_ = Parity::None; break; + case 5: word_size_ = 8; stop_bits_ = 1; parity_ = Parity::None; break; + case 6: word_size_ = 8; stop_bits_ = 1; parity_ = Parity::Even; break; + case 7: word_size_ = 8; stop_bits_ = 1; parity_ = Parity::Odd; break; + } + switch((value >> 5) & 3) { + case 0: set_ready_to_transmit(false); transmit_interrupt_enabled_ = false; break; + case 1: set_ready_to_transmit(false); transmit_interrupt_enabled_ = true; break; + case 2: set_ready_to_transmit(true); transmit_interrupt_enabled_ = false; break; + case 3: set_ready_to_transmit(false); transmit_interrupt_enabled_ = false; break; /* TODO: transmit a break level on the transmit output. */ + } + receive_interrupt_enabled_ = value & 0x80; LOG("Write to control register"); } } @@ -37,3 +61,7 @@ void ACIA::write(int address, uint8_t value) { void ACIA::run_for(HalfCycles) { } + +void ACIA::set_ready_to_transmit(bool) { + +} diff --git a/Components/6850/6850.hpp b/Components/6850/6850.hpp index b210ca1b8..df8eafa0e 100644 --- a/Components/6850/6850.hpp +++ b/Components/6850/6850.hpp @@ -40,6 +40,14 @@ class ACIA { private: int divider_ = 1; uint8_t status_ = 0x00; + enum class Parity { + Even, Odd, None + } parity_ = Parity::None; + int word_size_ = 7, stop_bits_ = 2; + bool receive_interrupt_enabled_ = false; + bool transmit_interrupt_enabled_ = false; + + void set_ready_to_transmit(bool); }; } diff --git a/Components/SerialPort/SerialPort.cpp b/Components/SerialPort/SerialPort.cpp new file mode 100644 index 000000000..4927e60ce --- /dev/null +++ b/Components/SerialPort/SerialPort.cpp @@ -0,0 +1,9 @@ +// +// SerialPort.cpp +// Clock Signal +// +// Created by Thomas Harte on 12/10/2019. +// Copyright © 2019 Thomas Harte. All rights reserved. +// + +#include "SerialPort.hpp" diff --git a/Components/SerialPort/SerialPort.hpp b/Components/SerialPort/SerialPort.hpp new file mode 100644 index 000000000..e78061c25 --- /dev/null +++ b/Components/SerialPort/SerialPort.hpp @@ -0,0 +1,71 @@ +// +// SerialPort.hpp +// Clock Signal +// +// Created by Thomas Harte on 12/10/2019. +// Copyright © 2019 Thomas Harte. All rights reserved. +// + +#ifndef SerialPort_hpp +#define SerialPort_hpp + +namespace Serial { + +/// Signal is an amalgamation of the RS-232-esque signals and those available on the Macintosh +/// and therefore often associated with RS-422. +enum class Signal { + Receive, + Transmit, + ClearToSend, + RequestToSend, + DataCarrierDetect, + OutputHandshake, + InputHandshake +}; + +/*! + @c Line connects a single reader and a single writer, allowing timestamped events to be + published and consumed, potentially with a clock conversion in between. It allows line + levels to be written and read in larger collections. + + It is assumed that the owner of the reader and writer will ensure that the reader will never + get ahead of the writer. If the writer posts events behind the reader they will simply be + given instanteous effect. +*/ +class Line { + public: + void connect_reader(int clock_rate); + void disconnect_reader(); + + void connect_writer(int clock_rate); + void disconnect_writer(); + + /// Sets the line to @c level after @c cycles relative to the writer's + /// clock rate have elapsed from the final event currently posted. + void write(int cycles, bool level); + + /// Enqueues @c count level changes, the first occurring @c cycles + /// after the final event currently posted and each subsequent event + /// occurring @c cycles after the previous. The levels to output are + /// taken from @c levels which is read from lsb to msb. @c cycles is + /// relative to the writer's clock rate. + void write(int cycles, int count, int levels); + + /// Advances the read position by @c cycles relative to the reader's + /// clock rate. + void advance_reader(int cycles); + + /// @returns The instantaneous level of this line at the current read position. + bool read(); +}; + +/*! + Defines an RS-232-esque srial port. +*/ +class Port { + public: +}; + +} + +#endif /* SerialPort_hpp */ diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 5aca36465..fe95f0d47 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -308,6 +308,8 @@ 4B89453D201967B4007DE474 /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B894516201967B4007DE474 /* StaticAnalyser.cpp */; }; 4B89453E201967B4007DE474 /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B894517201967B4007DE474 /* StaticAnalyser.cpp */; }; 4B89453F201967B4007DE474 /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B894517201967B4007DE474 /* StaticAnalyser.cpp */; }; + 4B8F5D962352125200C775ED /* SerialPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8F5D942352125200C775ED /* SerialPort.cpp */; }; + 4B8F5D972352125200C775ED /* SerialPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8F5D942352125200C775ED /* SerialPort.cpp */; }; 4B8FE21B1DA19D5F0090D3CE /* Atari2600Options.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B8FE2131DA19D5F0090D3CE /* Atari2600Options.xib */; }; 4B8FE21C1DA19D5F0090D3CE /* MachineDocument.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B8FE2151DA19D5F0090D3CE /* MachineDocument.xib */; }; 4B8FE21D1DA19D5F0090D3CE /* QuickLoadCompositeOptions.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B8FE2171DA19D5F0090D3CE /* QuickLoadCompositeOptions.xib */; }; @@ -1096,6 +1098,8 @@ 4B8D287E1F77207100645199 /* TrackSerialiser.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TrackSerialiser.hpp; sourceTree = ""; }; 4B8E4ECD1DCE483D003716C3 /* KeyboardMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = KeyboardMachine.hpp; sourceTree = ""; }; 4B8EF6071FE5AF830076CCDD /* LowpassSpeaker.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = LowpassSpeaker.hpp; sourceTree = ""; }; + 4B8F5D942352125200C775ED /* SerialPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SerialPort.cpp; sourceTree = ""; }; + 4B8F5D952352125200C775ED /* SerialPort.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SerialPort.hpp; sourceTree = ""; }; 4B8FE2141DA19D5F0090D3CE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/Atari2600Options.xib"; sourceTree = SOURCE_ROOT; }; 4B8FE2161DA19D5F0090D3CE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/MachineDocument.xib"; sourceTree = SOURCE_ROOT; }; 4B8FE2181DA19D5F0090D3CE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/QuickLoadCompositeOptions.xib"; sourceTree = SOURCE_ROOT; }; @@ -2629,6 +2633,15 @@ path = Implementation; sourceTree = ""; }; + 4B8F5D932352125200C775ED /* SerialPort */ = { + isa = PBXGroup; + children = ( + 4B8F5D942352125200C775ED /* SerialPort.cpp */, + 4B8F5D952352125200C775ED /* SerialPort.hpp */, + ); + path = SerialPort; + sourceTree = ""; + }; 4B92294922B064FD00A1458F /* QuadratureMouse */ = { isa = PBXGroup; children = ( @@ -3266,6 +3279,7 @@ 4B4A762D1DB1A35C007AAE2E /* AY38910 */, 4B302181208A550100773308 /* DiskII */, 4B4B1A39200198C900A0F866 /* KonamiSCC */, + 4B8F5D932352125200C775ED /* SerialPort */, 4BB0A6582044FD3000FB3688 /* SN76489 */, ); name = Components; @@ -4142,6 +4156,7 @@ 4B8318B022D3E531006DB630 /* AppleII.cpp in Sources */, 4B055AB11FAE86070060FFFF /* Tape.cpp in Sources */, 4BC1317B2346DF2B00E4FF3D /* MSA.cpp in Sources */, + 4B8F5D972352125200C775ED /* SerialPort.cpp in Sources */, 4BFE7B881FC39D8900160B38 /* StandardOptions.cpp in Sources */, 4B894533201967B4007DE474 /* 6502.cpp in Sources */, 4B055AA91FAE85EF0060FFFF /* CommodoreGCR.cpp in Sources */, @@ -4253,6 +4268,7 @@ 4BEA525E1DF33323007E74F2 /* Tape.cpp in Sources */, 4B07835A1FC11D10001D12BB /* Configurable.cpp in Sources */, 4B8334951F5E25B60097E338 /* C1540.cpp in Sources */, + 4B8F5D962352125200C775ED /* SerialPort.cpp in Sources */, 4B89453C201967B4007DE474 /* StaticAnalyser.cpp in Sources */, 4B595FAD2086DFBA0083CAA8 /* AudioToggle.cpp in Sources */, 4B1497921EE4B5A800CE2596 /* ZX8081.cpp in Sources */,