From 69512a4c05af214fb84dbdc4042fe6b7f61bead2 Mon Sep 17 00:00:00 2001 From: "Christopher A. Mosher" Date: Wed, 19 Dec 2018 19:39:27 -0500 Subject: [PATCH] implement drive motor-off one-second delay --- src/Makefile.am | 4 +-- src/diskcontroller.cpp | 14 +++++----- src/diskcontroller.h | 14 +++++++--- src/drivemotor.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++ src/drivemotor.h | 39 ++++++++++++++++++++++++++ src/wozfile.cpp | 2 +- 6 files changed, 121 insertions(+), 14 deletions(-) create mode 100644 src/drivemotor.cpp create mode 100644 src/drivemotor.h diff --git a/src/Makefile.am b/src/Makefile.am index f8a883c..2c308e5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,7 +12,7 @@ epple2_CPPFLAGS = $(AM_CPPFLAGS) -DETCDIR=\"$(sysconfdir)\" epple2_SOURCES = a2colorsobserved.cpp addressbus.cpp analogtv.cpp apple2.cpp \ applentsc.cpp card.cpp cassette.cpp clipboardhandler.cpp clockcard.cpp \ -configep2.cpp cpu.cpp diskbytes.cpp diskcontroller.cpp drive.cpp \ +configep2.cpp cpu.cpp diskbytes.cpp diskcontroller.cpp drive.cpp drivemotor.cpp \ emptyslot.cpp emulator.cpp firmwarecard.cpp gui.cpp hypermode.cpp \ keyboard.cpp keyboardbuffermode.cpp languagecard.cpp lowpass_1_5_mhz.cpp \ lowpass_3_58_mhz.cpp lss.cpp main.cpp memory.cpp paddlebuttonstates.cpp \ @@ -26,7 +26,7 @@ StateCalculator.cpp Trace.cpp TransCache.cpp TransNetwork.cpp noinst_HEADERS = a2colorsobserved.h addressbus.h analogtv.h apple2.h applentsc.h \ card.h cassette.h clipboardhandler.h clockcard.h configep2.h cpu.h diskbytes.h \ -diskcontroller.h drive.h e2const.h emptyslot.h emulator.h firmwarecard.h font3x5.h gui.h \ +diskcontroller.h drive.h drivemotor.h e2const.h emptyslot.h emulator.h firmwarecard.h font3x5.h gui.h \ hypermode.h keyboardbuffermode.h keyboard.h languagecard.h lowpass_1_5_mhz.h \ lowpass_3_58_mhz.h lss.h memory.h paddlebuttonstates.h paddles.h picturegenerator.h \ powerupreset.h raminitializer.h screenimage.h slots.h speakerclicker.h \ diff --git a/src/diskcontroller.cpp b/src/diskcontroller.cpp index e2642f4..5ddd081 100644 --- a/src/diskcontroller.cpp +++ b/src/diskcontroller.cpp @@ -45,21 +45,19 @@ unsigned char DiskController::io(const unsigned short addr, const unsigned char case 2: case 3: this->currentDrive->setMagnet(q,on); - this->gui.setTrack(this->slot,getCurrentDriveNumber(),getTrack()); + this->gui.setTrack(this->slot, getCurrentDriveNumber(), getTrack()); break; case 4: - this->motorOn = on; - this->gui.setIO(this->slot,getCurrentDriveNumber(),on); + this->motor.power(on); break; case 5: - this->gui.clearCurrentDrive(this->slot,getCurrentDriveNumber()); + this->gui.clearCurrentDrive(this->slot, getCurrentDriveNumber()); this->currentDrive = (on ? &this->drive2 : &this->drive1); - this->gui.setCurrentDrive(this->slot,getCurrentDriveNumber(),getTrack(),this->motorOn); + this->gui.setCurrentDrive(this->slot, getCurrentDriveNumber(),getTrack(), this->motor.isOn()); break; case 6: this->load = on; // TODO when to do these GUI updates? -// this->gui.setIO(this->slot,getCurrentDriveNumber(),this->motorOn); // this->gui.setDirty(this->slot,getCurrentDriveNumber(),true); break; case 7: @@ -83,9 +81,11 @@ unsigned char DiskController::io(const unsigned short addr, const unsigned char * (When the motor is on, that is.) */ void DiskController::tick() { - if (!this->motorOn) { + this->gui.setIO(this->slot, getCurrentDriveNumber(), this->motor.isOn()); + if (!this->motor.isOn()) { return; } + this->motor.tick(); // only need to send tick when motor is powered on rotateCurrentDisk(); diff --git a/src/diskcontroller.h b/src/diskcontroller.h index ae3b991..ef3fa1f 100644 --- a/src/diskcontroller.h +++ b/src/diskcontroller.h @@ -17,6 +17,7 @@ */ #include "card.h" #include "drive.h" +#include "drivemotor.h" #include "wozfile.h" #include "lss.h" #include "screenimage.h" @@ -41,7 +42,12 @@ private: bool load; // Q6 bool write; // Q7 - bool motorOn; // TODO WOZ make it delay power-off by about 1 second. + + /* + * Only one drive's motor can be on at a time, + * so we only need one instance. + */ + DriveMotor motor; // Maintain a copy of the last thing on the data bus, so it can // be read by the LSS algorithm when needed. @@ -57,7 +63,7 @@ private: // TODO for a rev. 0 motherboard, the disk controller will auto reset the CPU (see UA2, 9-13) void writeBit(bool on) { - if (!this->motorOn) { + if (!this->motor.isOn()) { return; } this->currentDrive->writeBit(on); @@ -89,7 +95,7 @@ public: this->gui.clearCurrentDrive(this->slot,getCurrentDriveNumber()); this->currentDrive = &this->drive1; - this->motorOn = false; + this->motor.reset(); this->gui.setCurrentDrive(this->slot,getCurrentDriveNumber(),getTrack(),false); } @@ -119,7 +125,7 @@ public: bool isMotorOn() { - return this->motorOn; + return this->motor.isOn(); } // const WozFile& getDiskBytes(unsigned char disk) diff --git a/src/drivemotor.cpp b/src/drivemotor.cpp new file mode 100644 index 0000000..559a544 --- /dev/null +++ b/src/drivemotor.cpp @@ -0,0 +1,62 @@ +/* + epple2 + Copyright (C) 2018 by Christopher A. Mosher + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY, without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "drivemotor.h" +#include "e2const.h" +//#include + +DriveMotor::DriveMotor(): + on(false), + pendingTicks(0) { +} + +DriveMotor::~DriveMotor() { +} + +bool DriveMotor::isOn() const { + return this->on; +} + +void DriveMotor::power(bool on) { + if (on) { + this->on = true; +// printf("MOTOR: power on\n"); + } else { + // delay power-off by about one second (a little longer, for momentum) + // U.A.II, p. 9-13 (NE556 timer) + this->pendingTicks = (int)(E2Const::AVG_CPU_HZ*1.2); +// printf("MOTOR: power off pending...\n"); + } +} + +void DriveMotor::reset() { + // immediate power off + // U.A.II, p. 9-13 + this->on = false; +// printf("MOTOR: power off (immediate)\n"); +} + +void DriveMotor::tick() { + if (this->pendingTicks > 0) { + --this->pendingTicks; + if (this->pendingTicks == 0){ + this->on = false; +// printf("MOTOR: power off\n"); + } + } +} diff --git a/src/drivemotor.h b/src/drivemotor.h new file mode 100644 index 0000000..c80e0ce --- /dev/null +++ b/src/drivemotor.h @@ -0,0 +1,39 @@ +/* + epple2 + Copyright (C) 2018 by Christopher A. Mosher + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY, without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef DRIVEMOTOR_H +#define DRIVEMOTOR_H + +#include + +class DriveMotor { +private: + bool on; + std::uint32_t pendingTicks; + +public: + DriveMotor(); + ~DriveMotor(); + + bool isOn() const; + void power(bool on); + void reset(); + void tick(); +}; + +#endif // DRIVEMOTOR_H diff --git a/src/wozfile.cpp b/src/wozfile.cpp index 0fef560..3541dbe 100644 --- a/src/wozfile.cpp +++ b/src/wozfile.cpp @@ -312,7 +312,7 @@ void WozFile::rotateOneBit(std::uint8_t currentQuarterTrack) { bool WozFile::getBit(std::uint8_t currentQuarterTrack) { if (!isLoaded()) { - printf("No disk to read from; will generate random data.\n"); +// printf("No disk to read from; will generate random data.\n"); return false; // there's no disk, so no pulse }