mirror of
https://github.com/TomHarte/CLK.git
synced 2024-08-16 16:28:59 +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.
|
||||
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) {
|
||||
@ -251,7 +260,10 @@ void MFP68901::decrement_timer(int timer, int amount) {
|
||||
case 2: begin_interrupts(Interrupt::TimerC); 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.
|
||||
}
|
||||
}
|
||||
@ -265,7 +277,7 @@ void MFP68901::set_port_input(uint8_t input) {
|
||||
}
|
||||
|
||||
uint8_t MFP68901::get_port_output() {
|
||||
return 0xff;
|
||||
return 0xff; // TODO.
|
||||
}
|
||||
|
||||
void MFP68901::reevaluate_gpip_interrupts() {
|
||||
|
@ -21,28 +21,58 @@ class PortHandler {
|
||||
// TODO: announce changes in output.
|
||||
};
|
||||
|
||||
/*!
|
||||
Models the Motorola 68901 Multi-Function Peripheral ('MFP').
|
||||
*/
|
||||
class MFP68901: public ClockingHint::Source {
|
||||
public:
|
||||
/// @returns the result of a read from @c address.
|
||||
uint8_t read(int address);
|
||||
|
||||
/// Performs a write of @c value to @c address.
|
||||
void write(int address, uint8_t value);
|
||||
|
||||
/// Advances the MFP by the supplied number of 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();
|
||||
|
||||
/// 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);
|
||||
|
||||
/// Sets a port handler, a receiver that will be notified upon any change in GPIP output.
|
||||
///
|
||||
/// @discussion TODO.
|
||||
void set_port_handler(PortHandler *);
|
||||
|
||||
/// Sets the current input GPIP values.
|
||||
void set_port_input(uint8_t);
|
||||
|
||||
/// @returns the current GPIP output values.
|
||||
///
|
||||
/// @discussion TODO.
|
||||
uint8_t get_port_output();
|
||||
|
||||
/// @returns @c true if the interrupt output is currently active; @c false otherwise.s
|
||||
bool get_interrupt_line();
|
||||
|
||||
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();
|
||||
|
||||
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;
|
||||
};
|
||||
/// Sets a delegate that will be notified upon any change in the interrupt line.
|
||||
void set_interrupt_delegate(InterruptDelegate *delegate);
|
||||
|
||||
// ClockingHint::Source.
|
||||
|
Loading…
Reference in New Issue
Block a user