mirror of
https://github.com/pevans/erc-c.git
synced 2024-11-18 22:06:01 +00:00
Rewrite dd to use phases and half-track steps
Phases will yet be the death of me. THE DEATH OF ME.
This commit is contained in:
parent
f59f5e2d55
commit
9562dd19ce
@ -61,6 +61,16 @@ enum apple2_dd_mode {
|
|||||||
*/
|
*/
|
||||||
#define MAX_SECTOR_POS 4095
|
#define MAX_SECTOR_POS 4095
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These are the possible phases that can energize the cogs in a disk
|
||||||
|
* drive motor. We represent them as bits, as more than one phase can be
|
||||||
|
* on at the same time.
|
||||||
|
*/
|
||||||
|
#define DD_PHASE1 0x1
|
||||||
|
#define DD_PHASE2 0x2
|
||||||
|
#define DD_PHASE3 0x4
|
||||||
|
#define DD_PHASE4 0x8
|
||||||
|
|
||||||
struct apple2dd {
|
struct apple2dd {
|
||||||
/*
|
/*
|
||||||
* Inside the disk drive there is a stepper motor, and it's
|
* Inside the disk drive there is a stepper motor, and it's
|
||||||
|
@ -13,30 +13,7 @@
|
|||||||
#include "apple2.dec.h"
|
#include "apple2.dec.h"
|
||||||
#include "apple2.enc.h"
|
#include "apple2.enc.h"
|
||||||
#include "apple2.h"
|
#include "apple2.h"
|
||||||
|
#include "vm_di.h"
|
||||||
// This is a small sort of state machine, which I adapted from AppleInPC
|
|
||||||
// (https://github.com/sosaria7/appleinpc) because I could not honestly
|
|
||||||
// think of a cleaner way of representing the step transitions that are
|
|
||||||
// possible. All credit to that project.
|
|
||||||
static int stepper_fsm[][8] =
|
|
||||||
{
|
|
||||||
{ 0, 0, 0, 0, 0, 0, 0, 0 }, // 0000
|
|
||||||
{ 0, -1, -2, -3, 0, 3, 2, 1 }, // 1000
|
|
||||||
{ 2, 1, 0, -1, -2, -3, 0, 3 }, // 0100
|
|
||||||
{ 1, 0, -1, -2, -3, 0, 3, 2 }, // 1100
|
|
||||||
{ 0, 3, 2, 1, 0, -1, -2, -3 }, // 0010
|
|
||||||
{ 0, -1, 0, 1, 0, -1, 0, 1 }, // 1010
|
|
||||||
{ 3, 2, 1, 0, -1, -2, -3, 0 }, // 0110
|
|
||||||
{ 2, 1, 0, -1, -2, -3, 0, 3 }, // 1110
|
|
||||||
{ -2, -3, 0, 3, 2, 1, 0, -1 }, // 0001
|
|
||||||
{ -1, -2, -3, 0, 3, 2, 1, 0 }, // 1001
|
|
||||||
{ 0, 1, 0, -1, 0, 1, 0, -1 }, // 0101
|
|
||||||
{ 0, -1, -2, -3, 0, 3, 2, 1 }, // 1101
|
|
||||||
{ -3, 0, 3, 2, 1, 0, -1, -2 }, // 0011
|
|
||||||
{ -2, -3, 0, 3, 2, 1, 0, -1 }, // 1011
|
|
||||||
{ 0, 3, 2, 1, 0, -1, -2, -3 }, // 0111
|
|
||||||
{ 0, 0, 0, 0, 0, 0, 0, 0 } // 1111
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a new disk drive. We do not create a memory segment for the
|
* Create a new disk drive. We do not create a memory segment for the
|
||||||
@ -257,17 +234,44 @@ apple2_dd_decode(apple2dd *drive)
|
|||||||
void
|
void
|
||||||
apple2_dd_phaser(apple2dd *drive)
|
apple2_dd_phaser(apple2dd *drive)
|
||||||
{
|
{
|
||||||
int phase = drive->phase_state;
|
int next = drive->phase_state;
|
||||||
int last = drive->last_phase;
|
int prev = drive->last_phase;
|
||||||
|
int step = 0;
|
||||||
|
|
||||||
if (!drive->online) {
|
if (!drive->online) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look up the number of steps to move according to the current
|
// If PHASE1 is on and PHASE4 was previously on, then we want to
|
||||||
// phase and the current track position.
|
// mimic an inward step
|
||||||
apple2_dd_step(drive,
|
if ((next & DD_PHASE1) && (prev & DD_PHASE4)) {
|
||||||
stepper_fsm[phase][drive->track_pos & 0x7]);
|
next = DD_PHASE4 << 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If, however, PHASE4 is on and previously PHASE1 was on, then we
|
||||||
|
// want to mimic an outward step
|
||||||
|
if ((next & DD_PHASE4) && (prev & DD_PHASE1)) {
|
||||||
|
next = DD_PHASE1 >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If an adjacent phase is on, add an inward or outward step. If
|
||||||
|
// _both_ adjacent phases are on, the step will count as zero (or no
|
||||||
|
// step).
|
||||||
|
if (next & (prev << 1)) {
|
||||||
|
step++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next & (prev >> 1)) {
|
||||||
|
step--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the opposite cog is also on, then our accounting is for
|
||||||
|
// naught; nullify the step movement.
|
||||||
|
if ((next & (prev << 2)) || (next & (prev >> 2))) {
|
||||||
|
step = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
apple2_dd_step(drive, step);
|
||||||
|
|
||||||
// Recall our trickery above with the phase variable? Because of it,
|
// Recall our trickery above with the phase variable? Because of it,
|
||||||
// we have to save the phase_state field into last_phase, and not
|
// we have to save the phase_state field into last_phase, and not
|
||||||
@ -288,7 +292,7 @@ apple2_dd_position(apple2dd *drive)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int track_offset = (drive->track_pos / 2) * ENC_ETRACK;
|
int track_offset = (drive->track_pos / 4) * ENC_ETRACK;
|
||||||
return track_offset + drive->sector_pos;
|
return track_offset + drive->sector_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,25 +203,30 @@ Test(apple2_dd, decode)
|
|||||||
|
|
||||||
Test(apple2_dd, phaser)
|
Test(apple2_dd, phaser)
|
||||||
{
|
{
|
||||||
|
// The drive must be online for any change to matter
|
||||||
|
drive->online = true;
|
||||||
|
|
||||||
// Test going backwards
|
// Test going backwards
|
||||||
drive->track_pos = 3;
|
drive->track_pos = 3;
|
||||||
drive->phase_state = 1;
|
drive->phase_state = 1;
|
||||||
drive->last_phase = 0;
|
drive->last_phase = 2;
|
||||||
drive->online = true;
|
|
||||||
|
|
||||||
apple2_dd_phaser(drive);
|
apple2_dd_phaser(drive);
|
||||||
|
|
||||||
cr_assert_eq(drive->track_pos, 0);
|
cr_assert_eq(drive->track_pos, 2);
|
||||||
cr_assert_eq(drive->last_phase, 1);
|
cr_assert_eq(drive->last_phase, 1);
|
||||||
|
|
||||||
// Forwards
|
// Forwards
|
||||||
drive->phase_state = 9;
|
drive->phase_state = 2;
|
||||||
drive->track_pos = 5;
|
drive->track_pos = 5;
|
||||||
drive->last_phase = 8;
|
drive->last_phase = 1;
|
||||||
|
apple2_dd_phaser(drive);
|
||||||
|
cr_assert_eq(drive->track_pos, 6);
|
||||||
|
cr_assert_eq(drive->last_phase, 2);
|
||||||
|
drive->phase_state = 4;
|
||||||
apple2_dd_phaser(drive);
|
apple2_dd_phaser(drive);
|
||||||
|
|
||||||
cr_assert_eq(drive->track_pos, 7);
|
cr_assert_eq(drive->track_pos, 7);
|
||||||
cr_assert_eq(drive->last_phase, 9);
|
cr_assert_eq(drive->last_phase, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
Test(apple2_dd, switch_phase)
|
Test(apple2_dd, switch_phase)
|
||||||
|
Loading…
Reference in New Issue
Block a user