mirror of
https://github.com/TomHarte/CLK.git
synced 2024-07-17 13:29:02 +00:00
Merge pull request #680 from TomHarte/EventCountReload
Implements MFP timer reload when in event counting mode.
This commit is contained in:
commit
288cabbad1
@ -239,6 +239,15 @@ void MFP68901::set_timer_event_input(int channel, bool value) {
|
|||||||
// If the edge bit associated with the TAI or TBI input is a one, it will be active high.
|
// If the edge bit associated with the TAI or TBI input is a one, it will be active high.
|
||||||
decrement_timer(channel, 1);
|
decrement_timer(channel, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
//
|
||||||
|
// Altering the edge bit while the timer is in the event count mode can produce a count pulse.
|
||||||
|
// The interrupt channel associated with the input (I3 for I4 for TAI) is allowed to function normally.
|
||||||
|
// To count transitions reliably, the input must remain in each state (1/O) for a length of time equal
|
||||||
|
// to four periods of the timer clock.
|
||||||
|
//
|
||||||
|
// (the final bit probably explains 13 cycles of the DE to interrupt latency; not sure about the other ~15)
|
||||||
}
|
}
|
||||||
|
|
||||||
void MFP68901::decrement_timer(int timer, int amount) {
|
void MFP68901::decrement_timer(int timer, int amount) {
|
||||||
@ -251,7 +260,10 @@ void MFP68901::decrement_timer(int timer, int amount) {
|
|||||||
case 2: begin_interrupts(Interrupt::TimerC); break;
|
case 2: begin_interrupts(Interrupt::TimerC); break;
|
||||||
case 3: begin_interrupts(Interrupt::TimerD); break;
|
case 3: begin_interrupts(Interrupt::TimerD); break;
|
||||||
}
|
}
|
||||||
if(timers_[timer].mode == TimerMode::Delay) {
|
|
||||||
|
// Re: reloading when in event counting mode; I found the data sheet thoroughly unclear on
|
||||||
|
// this, but it appears empirically to be correct. See e.g. Pompey Pirates menu 27.
|
||||||
|
if(timers_[timer].mode == TimerMode::Delay || timers_[timer].mode == TimerMode::EventCount) {
|
||||||
timers_[timer].value += timers_[timer].reload_value; // TODO: properly.
|
timers_[timer].value += timers_[timer].reload_value; // TODO: properly.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -265,7 +277,7 @@ void MFP68901::set_port_input(uint8_t input) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t MFP68901::get_port_output() {
|
uint8_t MFP68901::get_port_output() {
|
||||||
return 0xff;
|
return 0xff; // TODO.
|
||||||
}
|
}
|
||||||
|
|
||||||
void MFP68901::reevaluate_gpip_interrupts() {
|
void MFP68901::reevaluate_gpip_interrupts() {
|
||||||
|
@ -21,28 +21,58 @@ class PortHandler {
|
|||||||
// TODO: announce changes in output.
|
// TODO: announce changes in output.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Models the Motorola 68901 Multi-Function Peripheral ('MFP').
|
||||||
|
*/
|
||||||
class MFP68901: public ClockingHint::Source {
|
class MFP68901: public ClockingHint::Source {
|
||||||
public:
|
public:
|
||||||
|
/// @returns the result of a read from @c address.
|
||||||
uint8_t read(int address);
|
uint8_t read(int address);
|
||||||
|
|
||||||
|
/// Performs a write of @c value to @c address.
|
||||||
void write(int address, uint8_t value);
|
void write(int address, uint8_t value);
|
||||||
|
|
||||||
|
/// Advances the MFP by the supplied number of HalfCycles.
|
||||||
void run_for(HalfCycles);
|
void run_for(HalfCycles);
|
||||||
|
|
||||||
|
/// @returns the number of cycles until the next possible sequence point — the next time
|
||||||
|
/// at which the interrupt line _might_ change. This object conforms to ClockingHint::Source
|
||||||
|
/// so that mechanism can also be used to reduce the quantity of calls into this class.
|
||||||
|
///
|
||||||
|
/// @discussion TODO, alas.
|
||||||
HalfCycles get_next_sequence_point();
|
HalfCycles get_next_sequence_point();
|
||||||
|
|
||||||
|
/// Sets the current level of either of the timer event inputs — TAI and TBI in datasheet terms.
|
||||||
void set_timer_event_input(int channel, bool value);
|
void set_timer_event_input(int channel, bool value);
|
||||||
|
|
||||||
|
/// Sets a port handler, a receiver that will be notified upon any change in GPIP output.
|
||||||
|
///
|
||||||
|
/// @discussion TODO.
|
||||||
void set_port_handler(PortHandler *);
|
void set_port_handler(PortHandler *);
|
||||||
|
|
||||||
|
/// Sets the current input GPIP values.
|
||||||
void set_port_input(uint8_t);
|
void set_port_input(uint8_t);
|
||||||
|
|
||||||
|
/// @returns the current GPIP output values.
|
||||||
|
///
|
||||||
|
/// @discussion TODO.
|
||||||
uint8_t get_port_output();
|
uint8_t get_port_output();
|
||||||
|
|
||||||
|
/// @returns @c true if the interrupt output is currently active; @c false otherwise.s
|
||||||
bool get_interrupt_line();
|
bool get_interrupt_line();
|
||||||
|
|
||||||
static const int NoAcknowledgement = 0x100;
|
static const int NoAcknowledgement = 0x100;
|
||||||
|
|
||||||
|
/// Communicates an interrupt acknowledge cycle.
|
||||||
|
///
|
||||||
|
/// @returns the vector placed on the bus if any; @c NoAcknowledgement if nothing is loaded.
|
||||||
int acknowledge_interrupt();
|
int acknowledge_interrupt();
|
||||||
|
|
||||||
struct InterruptDelegate {
|
struct InterruptDelegate {
|
||||||
|
/// Informs the delegate of a change in the interrupt line of the nominated MFP.
|
||||||
virtual void mfp68901_did_change_interrupt_status(MFP68901 *) = 0;
|
virtual void mfp68901_did_change_interrupt_status(MFP68901 *) = 0;
|
||||||
};
|
};
|
||||||
|
/// Sets a delegate that will be notified upon any change in the interrupt line.
|
||||||
void set_interrupt_delegate(InterruptDelegate *delegate);
|
void set_interrupt_delegate(InterruptDelegate *delegate);
|
||||||
|
|
||||||
// ClockingHint::Source.
|
// ClockingHint::Source.
|
||||||
|
Loading…
Reference in New Issue
Block a user