mirror of
https://github.com/pevans/erc-c.git
synced 2024-11-23 23:32:45 +00:00
Use state machine for stepper motor changes
This commit is contained in:
parent
cbf693b186
commit
998a139c00
@ -14,6 +14,30 @@
|
|||||||
#include "apple2.enc.h"
|
#include "apple2.enc.h"
|
||||||
#include "apple2.h"
|
#include "apple2.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
|
||||||
* drive right away, as the size of said data can be variable based on
|
* drive right away, as the size of said data can be variable based on
|
||||||
@ -235,62 +259,15 @@ apple2_dd_phaser(apple2dd *drive)
|
|||||||
{
|
{
|
||||||
int phase = drive->phase_state;
|
int phase = drive->phase_state;
|
||||||
int last = drive->last_phase;
|
int last = drive->last_phase;
|
||||||
int step = 0;
|
|
||||||
|
|
||||||
if (phase == (last << 1)) {
|
if (!drive->online) {
|
||||||
step++;
|
|
||||||
} else if (phase == 0x1 && last == 0x8) {
|
|
||||||
step++;
|
|
||||||
} else if (phase == (last >> 1)) {
|
|
||||||
step--;
|
|
||||||
} else if (phase == 0x8 && last == 0x1) {
|
|
||||||
step--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (phase == 0 && last == 0) {
|
|
||||||
step = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (phase == 1 && last == 0) {
|
|
||||||
step = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// This is a bit of trickery; there is no phase state for 0x10 or
|
|
||||||
// 0x0, but we want to pretend like the phase is "next" to the bit
|
|
||||||
// we're operating with for the purpose of establishing a direction.
|
|
||||||
if (phase == 0x1 && last == 0x8) {
|
|
||||||
phase = 0x10;
|
|
||||||
} else if (phase == 0x8 && last == 0x1) {
|
|
||||||
phase = 0x0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We only want to respond to adjacent phases, so if the last phase
|
|
||||||
// shifted in _any_ direction is not equal to the phase state, then
|
|
||||||
// we should do nothing.
|
|
||||||
if (phase != 0 && (phase << 1) != last && (phase >> 1) != last) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The above check works for non-zero phases, but for zero phases,
|
// Look up the number of steps to move according to the current
|
||||||
// the logic is a bit different.
|
// phase and the current track position.
|
||||||
if (phase == 0 && last != 0x1 && last != 0x8) {
|
apple2_dd_step(drive,
|
||||||
return;
|
stepper_fsm[phase][drive->track_pos & 0x7]);
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
apple2_dd_step(drive, step);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// If phase > last, then we must move the head forward by a half
|
|
||||||
// track. If it's < last, then we move the head backward, again by a
|
|
||||||
// half track.
|
|
||||||
if (phase > last) {
|
|
||||||
apple2_dd_step(drive, 1);
|
|
||||||
} else if (phase < last) {
|
|
||||||
apple2_dd_step(drive, -1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// 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
|
||||||
@ -421,6 +398,12 @@ apple2_dd_step(apple2dd *drive, int steps)
|
|||||||
} else if (drive->track_pos < 0) {
|
} else if (drive->track_pos < 0) {
|
||||||
drive->track_pos = 0;
|
drive->track_pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The sector position is rehomed to zero whenever we step a
|
||||||
|
// non-zero length.
|
||||||
|
if (steps) {
|
||||||
|
drive->sector_pos = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -203,24 +203,25 @@ Test(apple2_dd, decode)
|
|||||||
|
|
||||||
Test(apple2_dd, phaser)
|
Test(apple2_dd, phaser)
|
||||||
{
|
{
|
||||||
|
// Test going backwards
|
||||||
|
drive->track_pos = 3;
|
||||||
drive->phase_state = 1;
|
drive->phase_state = 1;
|
||||||
drive->last_phase = 0;
|
drive->last_phase = 0;
|
||||||
|
drive->online = true;
|
||||||
|
|
||||||
apple2_dd_phaser(drive);
|
apple2_dd_phaser(drive);
|
||||||
|
|
||||||
cr_assert_eq(drive->track_pos, 1);
|
cr_assert_eq(drive->track_pos, 0);
|
||||||
cr_assert_eq(drive->last_phase, 1);
|
cr_assert_eq(drive->last_phase, 1);
|
||||||
|
|
||||||
// This shouldn't work--we should stay at the track_pos we begin
|
// Forwards
|
||||||
// with
|
drive->phase_state = 9;
|
||||||
drive->phase_state = 0x4;
|
drive->track_pos = 5;
|
||||||
|
drive->last_phase = 8;
|
||||||
apple2_dd_phaser(drive);
|
apple2_dd_phaser(drive);
|
||||||
cr_assert_eq(drive->track_pos, 1);
|
|
||||||
|
|
||||||
// And test that we can go backward
|
cr_assert_eq(drive->track_pos, 7);
|
||||||
drive->phase_state = 0x2;
|
cr_assert_eq(drive->last_phase, 9);
|
||||||
apple2_dd_phaser(drive);
|
|
||||||
cr_assert_eq(drive->track_pos, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Test(apple2_dd, switch_phase)
|
Test(apple2_dd, switch_phase)
|
||||||
|
Loading…
Reference in New Issue
Block a user