1//============================================================================
2//
3// SSSS tt lll lll
4// SS SS tt ll ll
5// SS tttttt eeee ll ll aaaa
6// SSSS tt ee ee ll ll aa
7// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
8// SS SS tt ee ll ll aa aa
9// SSSS ttt eeeee llll llll aaaaa
10//
11// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
12// and the Stella Team
13//
14// See the file "License.txt" for information on usage and redistribution of
15// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16//============================================================================
17
18#ifndef ATARIVOX_HXX
19#define ATARIVOX_HXX
20
21class OSystem;
22
23#include "Control.hxx"
24#include "SaveKey.hxx"
25#include "SerialPort.hxx"
26
27/**
28 Richard Hutchinson's AtariVox "controller": A speech synthesizer and
29 storage device.
30
31 This code owes a great debt to Alex Herbert's AtariVox documentation and
32 driver code.
33
34 @author B. Watson
35*/
36class AtariVox : public SaveKey
37{
38 public:
39 /**
40 Create a new AtariVox controller plugged into the specified jack
41
42 @param jack The jack the controller is plugged into
43 @param event The event object to use for events
44 @param system The system using this controller
45 @param portname Name of the serial port used for reading and writing
46 @param eepromfile The file containing the EEPROM data
47 @param callback Called to pass messages back to the parent controller
48 */
49 AtariVox(Jack jack, const Event& event, const System& system,
50 const string& portname, const string& eepromfile,
51 onMessageCallback callback);
52 virtual ~AtariVox() = default;
53
54 public:
55 using Controller::read;
56
57 /**
58 Read the value of the specified digital pin for this controller.
59
60 @param pin The pin of the controller jack to read
61 @return The state of the pin
62 */
63 bool read(DigitalPin pin) override;
64
65 /**
66 Write the given value to the specified digital pin for this
67 controller. Writing is only allowed to the pins associated
68 with the PIA. Therefore you cannot write to pin six.
69
70 @param pin The pin of the controller jack to write to
71 @param value The value to write to the pin
72 */
73 void write(DigitalPin pin, bool value) override;
74
75 /**
76 Update the entire digital and analog pin state according to the
77 events currently set.
78 */
79 void update() override { }
80
81 /**
82 Notification method invoked by the system after its reset method has
83 been called. It may be necessary to override this method for
84 controllers that need to know a reset has occurred.
85 */
86 void reset() override;
87
88 string about(bool swappedPorts) const override { return Controller::about(swappedPorts) + myAboutString; }
89
90 private:
91 void clockDataIn(bool value);
92
93 private:
94 // Instance of an real serial port on the system
95 // Assuming there's a real AtariVox attached, we can send SpeakJet
96 // bytes directly to it
97 unique_ptr<SerialPort> mySerialPort;
98
99 // How many bits have been shifted into the shift register?
100 uInt8 myShiftCount;
101
102 // Shift register. Data comes in serially:
103 // 1 start bit, always 0
104 // 8 data bits, LSB first
105 // 1 stop bit, always 1
106 uInt16 myShiftRegister;
107
108 // When did the last data write start, in CPU cycles?
109 // The real SpeakJet chip reads data at 19200 bits/sec. Alex's
110 // driver code sends data at 62 CPU cycles per bit, which is
111 // "close enough".
112 uInt64 myLastDataWriteCycle;
113
114 // Holds information concerning serial port usage
115 string myAboutString;
116
117 private:
118 // Following constructors and assignment operators not supported
119 AtariVox() = delete;
120 AtariVox(const AtariVox&) = delete;
121 AtariVox(AtariVox&&) = delete;
122 AtariVox& operator=(const AtariVox&) = delete;
123 AtariVox& operator=(AtariVox&&) = delete;
124};
125
126#endif
127