1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-09-05 13:29:06 +00:00
CLK/Components/68901/MFP68901.hpp
2019-10-23 23:09:49 -04:00

113 lines
2.5 KiB
C++

//
// MFP68901.hpp
// Clock Signal
//
// Created by Thomas Harte on 06/10/2019.
// Copyright © 2019 Thomas Harte. All rights reserved.
//
#ifndef MFP68901_hpp
#define MFP68901_hpp
#include <cstdint>
#include "../../ClockReceiver/ClockReceiver.hpp"
namespace Motorola {
namespace MFP68901 {
class PortHandler {
public:
// TODO: announce changes in output.
};
class MFP68901 {
public:
uint8_t read(int address);
void write(int address, uint8_t value);
void run_for(HalfCycles);
HalfCycles get_next_sequence_point();
void set_timer_event_input(int channel, bool value);
void set_port_handler(PortHandler *);
void set_port_input(uint8_t);
uint8_t get_port_output();
private:
// MARK: - Timers
enum class TimerMode {
Stopped, EventCount, Delay, PulseWidth
};
void set_timer_mode(int timer, TimerMode, int prescale, bool reset_timer);
void set_timer_data(int timer, uint8_t);
uint8_t get_timer_data(int timer);
void decrement_timer(int timer);
struct Timer {
TimerMode mode = TimerMode::Stopped;
uint8_t value = 0;
uint8_t reload_value = 0;
int prescale = 1;
int divisor = 0;
bool event_input = false;
} timers_[4];
HalfCycles cycles_left_;
// MARK: - GPIP
uint8_t gpip_input_ = 0;
uint8_t gpip_output_ = 0;
uint8_t gpip_active_edge_ = 0;
uint8_t gpip_direction_ = 0;
uint8_t gpip_interrupt_state_ = 0;
void reevaluate_gpip_interrupts();
// MARK: - Interrupts
// Ad hoc documentation: there seems to be a four-stage process here.
// This is my current understanding:
//
// Interrupt in-service refers to whether the signal that would cause an
// interrupt is active.
//
// If the interrupt is in-service and enabled, it will be listed as pending.
//
// If a pending interrupt is enabled in the interrupt mask, it will generate
// a processor interrupt.
//
// So, the designers seem to have wanted to allow for polling and interrupts,
// and then also decided to have some interrupts be able to be completely
// disabled, so that don't even show up for polling.
uint8_t interrupt_in_service_[2] = {0, 0};
uint8_t interrupt_enable_[2] = {0, 0};
uint8_t interrupt_pending_[2] = {0, 0};
uint8_t interrupt_mask_[2] = {0, 0};
enum Interrupt {
GPIP0 = 0,
GPIP1,
GPIP2,
GPIP3,
TimerD,
TimerC,
GPIP4,
GPIP5,
TimerB,
TransmitError,
TransmitBufferEmpty,
ReceiveError,
ReceiveBufferFull,
GPIP6,
GPIP7
};
void begin_interrupt(Interrupt interrupt);
void end_interrupt(Interrupt interrupt);
};
}
}
#endif /* MFP68901_hpp */