summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author AJR <ariedlmayer@gmail.com>2024-10-27 10:14:19 -0400
committer AJR <ariedlmayer@gmail.com>2024-10-27 10:20:24 -0400
commitf63e8f0a55f08cea675dfd332cf8197a08bf5358 (patch)
tree642d4c47869ad100fd38bdf3b5f201f953307c27 /src
parent97c4c3bb298b30748cf34a4fd634be1735672342 (diff)
Thomson floppy disk updates
- to8, to9 & to9p now include the FDC in the base configuration. to9 uses a WD1770 (WD2793 appears to fail calibration), while to8 & to9p use the THM-FC-1 gate array (now a separate device). This eliminates the need to, and ability to, configure floppy disk extensions for the to8, to9 and to9p. - Changed sector offsets for double-sided .fd images so that they load correctly (usually).
Diffstat (limited to 'src')
-rw-r--r--src/devices/bus/thomson/cd90_351.cpp417
-rw-r--r--src/devices/bus/thomson/cd90_351.h79
-rw-r--r--src/devices/bus/thomson/cd90_640.cpp4
-rw-r--r--src/devices/machine/thmfc1.cpp438
-rw-r--r--src/devices/machine/thmfc1.h106
-rw-r--r--src/lib/formats/thom_dsk.cpp11
-rw-r--r--src/lib/formats/thom_dsk.h4
-rw-r--r--src/mame/thomson/thomson.cpp57
-rw-r--r--src/mame/thomson/thomson.h11
-rw-r--r--src/mame/thomson/thomson_m.cpp32
-rw-r--r--src/mame/thomson/to_kbd.cpp2
11 files changed, 666 insertions, 495 deletions
diff --git a/src/devices/bus/thomson/cd90_351.cpp b/src/devices/bus/thomson/cd90_351.cpp
index d4a610c1f3f..870c0843733 100644
--- a/src/devices/bus/thomson/cd90_351.cpp
+++ b/src/devices/bus/thomson/cd90_351.cpp
@@ -11,13 +11,13 @@
#include "emu.h"
#include "cd90_351.h"
#include "formats/thom_dsk.h"
+#include "machine/thmfc1.h"
DEFINE_DEVICE_TYPE(CD90_351, cd90_351_device, "cd90_351", "Thomson CD 90-351 Diskette Controller")
cd90_351_device::cd90_351_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, CD90_351, tag, owner, 16000000),
+ device_t(mconfig, CD90_351, tag, owner, clock),
thomson_extension_interface(mconfig, *this),
- m_floppy(*this, "%u", 0U),
m_rom(*this, "rom"),
m_rom_bank(*this, "rom_bank")
{
@@ -41,14 +41,7 @@ void cd90_351_device::rom_map(address_map &map)
void cd90_351_device::io_map(address_map &map)
{
- map(0x10, 0x10).rw(FUNC(cd90_351_device::stat0_r), FUNC(cd90_351_device::cmd0_w));
- map(0x11, 0x11).rw(FUNC(cd90_351_device::stat1_r), FUNC(cd90_351_device::cmd1_w));
- map(0x12, 0x12).w(FUNC(cd90_351_device::cmd2_w));
- map(0x13, 0x13).rw(FUNC(cd90_351_device::rdata_r), FUNC(cd90_351_device::wdata_w));
- map(0x14, 0x14).w(FUNC(cd90_351_device::wclk_w));
- map(0x15, 0x15).w(FUNC(cd90_351_device::wsect_w));
- map(0x16, 0x16).w(FUNC(cd90_351_device::wtrck_w));
- map(0x17, 0x17).w(FUNC(cd90_351_device::wcell_w));
+ map(0x10, 0x17).m("thmfc1", FUNC(thmfc1_device::map));
map(0x18, 0x18).w(FUNC(cd90_351_device::bank_w));
}
@@ -71,248 +64,19 @@ void cd90_351_device::floppy_formats(format_registration &fr)
void cd90_351_device::device_add_mconfig(machine_config &config)
{
- FLOPPY_CONNECTOR(config, m_floppy[0], floppy_drives, "dd90_352", floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy[1], floppy_drives, nullptr, floppy_formats).enable_sound(true);
+ THMFC1(config, "thmfc1", 16000000);
+ FLOPPY_CONNECTOR(config, "thmfc1:0", floppy_drives, "dd90_352", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "thmfc1:1", floppy_drives, nullptr, floppy_formats).enable_sound(true);
}
void cd90_351_device::device_start()
{
m_rom_bank->configure_entries(0, 4, m_rom->base(), 0x800);
- m_timer_motoroff = timer_alloc(FUNC(cd90_351_device::motor_off), this);
-
- save_item(NAME(m_cmd0));
- save_item(NAME(m_cmd1));
- save_item(NAME(m_cmd2));
- save_item(NAME(m_stat0));
- save_item(NAME(m_data));
- save_item(NAME(m_clk));
- save_item(NAME(m_sect));
- save_item(NAME(m_trck));
- save_item(NAME(m_cell));
- save_item(NAME(m_last_sync));
- save_item(NAME(m_window_start));
- save_item(NAME(m_shift_reg));
- save_item(NAME(m_crc));
- save_item(NAME(m_bit_counter));
- save_item(NAME(m_data_reg));
- save_item(NAME(m_data_separator_phase));
}
void cd90_351_device::device_reset()
{
m_rom_bank->set_entry(0);
-
- m_cmd0 = 0;
- m_cmd1 = 0;
- m_cmd2 = 0;
- m_stat0 = S0_FREE;
- m_data = 0;
- m_clk = 0;
- m_sect = 0;
- m_trck = 0;
- m_cell = 0;
- m_last_sync = 0;
- m_window_start = 0;
- m_shift_reg = 0;
- m_crc = 0;
- m_bit_counter = 0;
- m_data_reg = 0;
- m_data_separator_phase = false;
- m_state = S_IDLE;
- m_cur_floppy = nullptr;
-}
-
-TIMER_CALLBACK_MEMBER(cd90_351_device::motor_off)
-{
- logerror("motor off\n");
- if(m_cur_floppy)
- m_cur_floppy->mon_w(1);
-}
-
-void cd90_351_device::device_post_load()
-{
- if(m_cmd2 & C2_DRS0)
- m_cur_floppy = m_floppy[0]->get_device();
- else if(m_cmd2 & C2_DRS1)
- m_cur_floppy = m_floppy[1]->get_device();
- else
- m_cur_floppy = nullptr;
-}
-
-void cd90_351_device::cmd0_w(u8 data)
-{
- sync();
-
- static const char *const mode[4] = { "reset", "wsect", "rhead", "rsect" };
- m_cmd0 = data;
- logerror("cmd0_w %02x, code=%s, ensyn=%d nomck=%d wgc=%d mode=%s\n", m_cmd1,
- m_cmd0 & C0_FM ? "fm" : "mfm",
- m_cmd0 & C0_ENSYN ? 1 : 0,
- m_cmd0 & C0_NOMCK ? 1 : 0,
- m_cmd0 & C0_WGC ? 1 : 0,
- mode[m_cmd0 & 3]);
-
- if(m_stat0 & S0_FREE)
- switch(m_cmd0 & 3) {
- case 0:
- break;
- case 1:
- logerror("wsect\n");
- exit(0);
- case 2:
- logerror("rhead\n");
- exit(0);
- case 3:
- logerror("read_sector start h=%d t=%2d s=%2d sz=%d\n",
- m_cmd1 & C1_SIDE ? 1 : 0,
- m_trck,
- m_sect,
- 128 << ((m_cmd1 >> 5) & 3));
- m_state = S_WAIT_HEADER_SYNC;
- m_stat0 &= ~S0_FREE;
- m_window_start = m_last_sync;
- break;
- }
-}
-
-void cd90_351_device::cmd1_w(u8 data)
-{
- sync();
-
- m_cmd1 = data;
- logerror("cmd1_w %02x, sector=(size=%d, side=%d) precomp=%d sync_only_when_ready=%s\n", m_cmd1,
- 128 << ((m_cmd1 >> 5) & 3),
- m_cmd1 & C1_SIDE ? 1 : 0,
- (m_cmd1 >> 1) & 7,
- m_cmd1 & C1_DSYRD ? "on" : "off");
-}
-
-void cd90_351_device::cmd2_w(u8 data)
-{
- sync();
-
- u8 prev = m_cmd2;
-
- m_cmd2 = data;
- logerror("cmd2_w %02x, side=%d dir=%d step=%d motor=%s sel=%c%c\n", m_cmd2,
- m_cmd2 & C2_SISELB ? 1 : 0,
- m_cmd2 & C2_DIRECB ? 1 : 0,
- m_cmd2 & C2_STEP ? 1 : 0,
- m_cmd2 & C2_MTON ? "on" : "off",
- m_cmd2 & C2_DRS1 ? 'b' : '-',
- m_cmd2 & C2_DRS0 ? 'a' : '-');
-
- if(m_cmd2 & C2_DRS0)
- m_cur_floppy = m_floppy[0]->get_device();
- else if(m_cmd2 & C2_DRS1)
- m_cur_floppy = m_floppy[1]->get_device();
- else
- m_cur_floppy = nullptr;
-
- if(m_cur_floppy) {
- if((prev & C2_MTON) && !(m_cmd2 & C2_MTON))
- m_timer_motoroff->adjust(attotime::from_seconds(2));
- if(m_cmd2 & C2_MTON) {
- m_cur_floppy->mon_w(0);
- m_timer_motoroff->adjust(attotime::never);
- }
- m_cur_floppy->ss_w(m_cmd2 & C2_SISELB ? 0 : 1);
- m_cur_floppy->dir_w(m_cmd2 & C2_DIRECB ? 0 : 1);
- m_cur_floppy->stp_w(m_cmd2 & C2_STEP ? 0 : 1);
- }
-}
-
-void cd90_351_device::wdata_w(u8 data)
-{
- m_data = data;
- m_stat0 &= ~(S0_BYTE | S0_DREQ);
- logerror("wdata_w %02x\n", data);
-}
-
-void cd90_351_device::wclk_w(u8 data)
-{
- sync();
-
- m_clk = data;
- logerror("wclk_w %02x\n", data);
-}
-
-void cd90_351_device::wsect_w(u8 data)
-{
- sync();
-
- m_sect = data;
- logerror("wsect_w %02x\n", data);
-}
-
-void cd90_351_device::wtrck_w(u8 data)
-{
- sync();
-
- m_trck = data;
- logerror("wtrck_w %02x\n", data);
-}
-
-void cd90_351_device::wcell_w(u8 data)
-{
- sync();
-
- m_cell = data;
- logerror("wcell_w %02x\n", data);
-}
-
-u8 cd90_351_device::stat0_r()
-{
- if(!machine().side_effects_disabled()) {
- sync();
- static int ps = -1;
- if(m_stat0 != ps)
- logerror("stat0_r %02x -%s%s%s%s%s%s\n", m_stat0,
- m_stat0 & S0_BYTE ? " byte" : "",
- m_stat0 & S0_END ? " end" : "",
- m_stat0 & S0_FREE ? " free" : "",
- m_stat0 & S0_CRCER ? " crcer" : "",
- m_stat0 & S0_DREQ ? " dreq" : "",
- m_stat0 & S0_SYNC ? " sync" : "");
- ps = m_stat0;
- }
- return m_stat0;
-}
-
-u8 cd90_351_device::stat1_r()
-{
- u8 res = 0;
- if(m_cur_floppy) {
- if(m_cur_floppy->idx_r())
- res |= S1_INDX;
- if(!m_cur_floppy->dskchg_r())
- res |= S1_DKCH;
- if(!m_cur_floppy->mon_r())
- res |= S1_MTON;
- if(!m_cur_floppy->trk00_r())
- res |= S1_TRK0;
- if(!m_cur_floppy->wpt_r())
- res |= S1_WPRT;
- if(!m_cur_floppy->ready_r())
- res |= S1_RDY;
- }
-
- if(!machine().side_effects_disabled())
- logerror("stat1_r %02x -%s%s%s%s%s%s\n", res,
- res & S1_INDX ? " index" : "",
- res & S1_DKCH ? " dskchg" : "",
- res & S1_MTON ? " mton" : "",
- res & S1_TRK0 ? " trk0" : "",
- res & S1_WPRT ? " wprt" : "",
- res & S1_RDY ? " ready" : "");
- return res;
-}
-
-u8 cd90_351_device::rdata_r()
-{
- if(!machine().side_effects_disabled())
- m_stat0 &= ~(S0_BYTE | S0_DREQ);
- return m_data;
}
void cd90_351_device::bank_w(u8 data)
@@ -320,172 +84,3 @@ void cd90_351_device::bank_w(u8 data)
logerror("bank_w %d\n", data & 3);
m_rom_bank->set_entry(data & 3);
}
-
-u64 cd90_351_device::time_to_cycles(const attotime &tm) const
-{
- return tm.as_ticks(clock());
-}
-
-attotime cd90_351_device::cycles_to_time(u64 cycles) const
-{
- return attotime::from_ticks(cycles, clock());
-}
-
-bool cd90_351_device::read_one_bit(u64 limit, u64 &next_flux_change)
-{
- while(next_flux_change <= m_last_sync) {
- attotime flux = m_cur_floppy ? m_cur_floppy->get_next_transition(cycles_to_time(m_last_sync+1)) : attotime::never;
- next_flux_change = flux.is_never() ? u64(-1) : time_to_cycles(flux);
- }
-
- u64 window_end = m_window_start + (m_cell & 0x7f);
- if(window_end > limit)
- return true;
-
- int bit = next_flux_change < window_end;
- if(bit && (m_cmd0 & C0_NOMCK))
- m_window_start = next_flux_change + ((m_cell & 0x7f) >> 1);
- else
- m_window_start = window_end;
-
- m_last_sync = window_end;
-
- m_shift_reg = (m_shift_reg << 1) | bit;
- m_bit_counter++;
- if(m_data_separator_phase) {
- m_data_reg = (m_data_reg << 1) | bit;
- if((m_crc ^ (bit ? 0x8000 : 0x0000)) & 0x8000)
- m_crc = (m_crc << 1) ^ 0x1021;
- else
- m_crc = m_crc << 1;
- }
-
- m_data_separator_phase = !m_data_separator_phase;
- return false;
-}
-
-u8 cd90_351_device::clk_bits() const
-{
- return
- (m_shift_reg & 0x8000 ? 0x80 : 0x00) |
- (m_shift_reg & 0x2000 ? 0x40 : 0x00) |
- (m_shift_reg & 0x0800 ? 0x20 : 0x00) |
- (m_shift_reg & 0x0200 ? 0x10 : 0x00) |
- (m_shift_reg & 0x0080 ? 0x08 : 0x00) |
- (m_shift_reg & 0x0020 ? 0x04 : 0x00) |
- (m_shift_reg & 0x0008 ? 0x02 : 0x00) |
- (m_shift_reg & 0x0002 ? 0x01 : 0x00);
-}
-
-
-void cd90_351_device::sync()
-{
- u64 next_sync = machine().time().as_ticks(clock());
- u64 next_flux_change = 0;
- while(m_last_sync < next_sync)
- switch(m_state) {
- case S_IDLE:
- m_last_sync = next_sync;
- break;
-
- case S_WAIT_HEADER_SYNC: {
- if(read_one_bit(next_sync, next_flux_change))
- return;
- if(m_shift_reg == 0xaaaa) {
- m_crc = 0xffff;
- m_data_separator_phase = false;
- }
- if(m_data_reg == m_data && clk_bits() == m_clk) {
- m_bit_counter = 0;
- m_state = S_VERIFY_HEADER;
- }
- break;
- }
-
- case S_VERIFY_HEADER: {
- if(read_one_bit(next_sync, next_flux_change))
- return;
- if(m_bit_counter & 0xf)
- break;
- bool valid = true;
- switch(m_bit_counter >> 4) {
- case 1:
- case 2:
- valid = m_data_reg == m_data && clk_bits() == m_clk;
- break;
- case 3:
- valid = m_data_reg == 0xfe;
- break;
- case 4:
- valid = m_data_reg == m_trck;
- break;
- case 5:
- valid = (m_data_reg & 1) == (m_cmd1 & C1_SIDE ? 1 : 0);
- break;
- case 6:
- valid = m_data_reg == m_sect;
- break;
- case 7:
- valid = (m_data_reg & 3) == ((m_cmd1 >> 5) & 3);
- break;
- // 8 skipped
- case 9:
- valid = m_crc == 0;
- m_bit_counter = 0;
- m_state = S_SKIP_GAP;
- break;
- }
- if(!valid)
- m_state = S_WAIT_HEADER_SYNC;
- break;
- }
-
- case S_SKIP_GAP:
- if(read_one_bit(next_sync, next_flux_change))
- return;
- if(m_bit_counter == 27 << 4) {
- m_bit_counter = 0;
- m_state = S_WAIT_SECTOR_SYNC;
- }
- break;
-
-
- case S_WAIT_SECTOR_SYNC: {
- if(read_one_bit(next_sync, next_flux_change))
- return;
- if(m_shift_reg == 0xaaaa) {
- m_crc = 0xffff;
- m_data_separator_phase = false;
- }
- if(m_data_reg == m_data && clk_bits() == m_clk) {
- m_bit_counter = 0;
- m_data = m_data_reg;
- m_stat0 |= S0_DREQ;
- m_state = S_READ_SECTOR;
- }
- if(m_bit_counter == 42 << 4)
- m_state = S_WAIT_HEADER_SYNC;
- break;
- }
-
- case S_READ_SECTOR:
- if(read_one_bit(next_sync, next_flux_change))
- return;
- if(m_bit_counter != 16)
- break;
- if(m_stat0 & (S0_BYTE|S0_DREQ)) {
- logerror("read_sector end\n");
- if(m_crc)
- m_stat0 |= S0_CRCER;
- m_stat0 &= ~S0_BYTE;
- m_stat0 |= S0_FREE;
- m_cmd0 &= ~3;
- m_state = S_IDLE;
- break;
- }
- m_stat0 |= S0_BYTE;
- m_data = m_data_reg;
- m_bit_counter = 0;
- break;
- }
-}
diff --git a/src/devices/bus/thomson/cd90_351.h b/src/devices/bus/thomson/cd90_351.h
index 6b4b0784f3b..de5e40e1ac2 100644
--- a/src/devices/bus/thomson/cd90_351.h
+++ b/src/devices/bus/thomson/cd90_351.h
@@ -15,7 +15,7 @@
class cd90_351_device : public device_t, public thomson_extension_interface
{
public:
- cd90_351_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 16000000);
+ cd90_351_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~cd90_351_device() = default;
virtual void rom_map(address_map &map) override ATTR_COLD;
@@ -26,92 +26,15 @@ protected:
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
- virtual void device_post_load() override;
-
- TIMER_CALLBACK_MEMBER(motor_off);
private:
- enum {
- S0_BYTE = 0x80,
- S0_END = 0x10,
- S0_FREE = 0x08,
- S0_CRCER = 0x04,
- S0_DREQ = 0x02,
- S0_SYNC = 0x01,
-
- S1_INDX = 0x40,
- S1_DKCH = 0x20,
- S1_MTON = 0x10,
- S1_TRK0 = 0x08,
- S1_WPRT = 0x04,
- S1_RDY = 0x02,
-
- C0_FM = 0x20,
- C0_ENSYN = 0x10,
- C0_NOMCK = 0x08,
- C0_WGC = 0x04,
-
- C1_SIDE = 0x10,
- C1_DSYRD = 0x01,
-
- C2_SISELB = 0x40,
- C2_DIRECB = 0x20,
- C2_STEP = 0x10,
- C2_MTON = 0x04,
- C2_DRS1 = 0x02,
- C2_DRS0 = 0x01,
- };
-
- enum {
- S_IDLE,
- S_WAIT_HEADER_SYNC,
- S_VERIFY_HEADER,
- S_SKIP_GAP,
- S_WAIT_SECTOR_SYNC,
- S_READ_SECTOR,
- };
-
- required_device_array<floppy_connector, 2> m_floppy;
required_memory_region m_rom;
memory_bank_creator m_rom_bank;
- floppy_image_device *m_cur_floppy;
- emu_timer *m_timer_motoroff;
-
- u64 m_last_sync, m_window_start;
- int m_state;
-
- u16 m_shift_reg, m_crc, m_bit_counter;
- u8 m_data_reg;
-
- u8 m_cmd0, m_cmd1, m_cmd2, m_stat0;
- u8 m_data, m_clk, m_sect, m_trck, m_cell;
-
- bool m_data_separator_phase;
static void floppy_formats(format_registration &fr);
static void floppy_drives(device_slot_interface &device);
- u8 clk_bits() const;
-
- void cmd0_w(u8 data);
- void cmd1_w(u8 data);
- void cmd2_w(u8 data);
- void wdata_w(u8 data);
- void wclk_w(u8 data);
- void wsect_w(u8 data);
- void wtrck_w(u8 data);
- void wcell_w(u8 data);
void bank_w(u8 data);
-
- u8 stat0_r();
- u8 stat1_r();
- u8 rdata_r();
-
- u64 time_to_cycles(const attotime &tm) const;
- attotime cycles_to_time(u64 cycles) const;
-
- void sync();
- bool read_one_bit(u64 limit, u64 &next_flux_change);
};
DECLARE_DEVICE_TYPE(CD90_351, cd90_351_device)
diff --git a/src/devices/bus/thomson/cd90_640.cpp b/src/devices/bus/thomson/cd90_640.cpp
index 86453d795be..a49d579704e 100644
--- a/src/devices/bus/thomson/cd90_640.cpp
+++ b/src/devices/bus/thomson/cd90_640.cpp
@@ -43,7 +43,7 @@ const tiny_rom_entry *cd90_640_device::device_rom_region() const
void cd90_640_device::floppy_drives(device_slot_interface &device)
{
- device.option_add("dd90_640", FLOPPY_525_DD);
+ device.option_add("dd90_320", FLOPPY_525_DD);
}
void cd90_640_device::floppy_formats(format_registration &fr)
@@ -54,7 +54,7 @@ void cd90_640_device::floppy_formats(format_registration &fr)
void cd90_640_device::device_add_mconfig(machine_config &config)
{
WD1770(config, m_fdc, 8_MHz_XTAL);
- FLOPPY_CONNECTOR(config, m_floppy[0], floppy_drives, "dd90_640", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], floppy_drives, "dd90_320", floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, m_floppy[1], floppy_drives, nullptr, floppy_formats).enable_sound(true);
}
diff --git a/src/devices/machine/thmfc1.cpp b/src/devices/machine/thmfc1.cpp
new file mode 100644
index 00000000000..e485859f9b9
--- /dev/null
+++ b/src/devices/machine/thmfc1.cpp
@@ -0,0 +1,438 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Custom Thomson 3.5"/5.25"/QDD diskette controller gate array used in CD 90-351, TO8 and TO9+
+
+
+#include "emu.h"
+#include "thmfc1.h"
+
+DEFINE_DEVICE_TYPE(THMFC1, thmfc1_device, "thmfc1", "SGS-Thomson THM-FC-1 Diskette Controller") // SGS logo used on silkscreen
+
+thmfc1_device::thmfc1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, THMFC1, tag, owner, clock),
+ m_floppy(*this, "%u", 0U)
+{
+}
+
+void thmfc1_device::map(address_map &map)
+{
+ map(0, 0).rw(FUNC(thmfc1_device::stat0_r), FUNC(thmfc1_device::cmd0_w));
+ map(1, 1).rw(FUNC(thmfc1_device::stat1_r), FUNC(thmfc1_device::cmd1_w));
+ map(2, 2).w(FUNC(thmfc1_device::cmd2_w));
+ map(3, 3).rw(FUNC(thmfc1_device::rdata_r), FUNC(thmfc1_device::wdata_w));
+ map(4, 4).w(FUNC(thmfc1_device::wclk_w));
+ map(5, 5).w(FUNC(thmfc1_device::wsect_w));
+ map(6, 6).w(FUNC(thmfc1_device::wtrck_w));
+ map(7, 7).w(FUNC(thmfc1_device::wcell_w));
+}
+
+void thmfc1_device::device_start()
+{
+ m_timer_motoroff = timer_alloc(FUNC(thmfc1_device::motor_off), this);
+
+ save_item(NAME(m_cmd0));
+ save_item(NAME(m_cmd1));
+ save_item(NAME(m_cmd2));
+ save_item(NAME(m_stat0));
+ save_item(NAME(m_data));
+ save_item(NAME(m_clk));
+ save_item(NAME(m_sect));
+ save_item(NAME(m_trck));
+ save_item(NAME(m_cell));
+ save_item(NAME(m_last_sync));
+ save_item(NAME(m_window_start));
+ save_item(NAME(m_shift_reg));
+ save_item(NAME(m_crc));
+ save_item(NAME(m_bit_counter));
+ save_item(NAME(m_data_reg));
+ save_item(NAME(m_data_separator_phase));
+}
+
+void thmfc1_device::device_reset()
+{
+ m_cmd0 = 0;
+ m_cmd1 = 0;
+ m_cmd2 = 0;
+ m_stat0 = S0_FREE;
+ m_data = 0;
+ m_clk = 0;
+ m_sect = 0;
+ m_trck = 0;
+ m_cell = 0;
+ m_last_sync = 0;
+ m_window_start = 0;
+ m_shift_reg = 0;
+ m_crc = 0;
+ m_bit_counter = 0;
+ m_data_reg = 0;
+ m_data_separator_phase = false;
+ m_state = S_IDLE;
+ m_cur_floppy = nullptr;
+}
+
+TIMER_CALLBACK_MEMBER(thmfc1_device::motor_off)
+{
+ logerror("motor off\n");
+ if(m_cur_floppy)
+ m_cur_floppy->mon_w(1);
+}
+
+void thmfc1_device::device_post_load()
+{
+ if(m_cmd2 & C2_DRS0)
+ m_cur_floppy = m_floppy[0]->get_device();
+ else if(m_cmd2 & C2_DRS1)
+ m_cur_floppy = m_floppy[1]->get_device();
+ else
+ m_cur_floppy = nullptr;
+}
+
+void thmfc1_device::cmd0_w(u8 data)
+{
+ sync();
+
+ static const char *const mode[4] = { "reset", "wsect", "rhead", "rsect" };
+ m_cmd0 = data;
+ logerror("cmd0_w %02x, code=%s, ensyn=%d nomck=%d wgc=%d mode=%s\n", m_cmd1,
+ m_cmd0 & C0_FM ? "fm" : "mfm",
+ m_cmd0 & C0_ENSYN ? 1 : 0,
+ m_cmd0 & C0_NOMCK ? 1 : 0,
+ m_cmd0 & C0_WGC ? 1 : 0,
+ mode[m_cmd0 & 3]);
+
+ if(m_stat0 & S0_FREE)
+ switch(m_cmd0 & 3) {
+ case 0:
+ break;
+ case 1:
+ logerror("wsect\n");
+ exit(0);
+ case 2:
+ logerror("rhead\n");
+ exit(0);
+ case 3:
+ logerror("read_sector start h=%d t=%2d s=%2d sz=%d\n",
+ m_cmd1 & C1_SIDE ? 1 : 0,
+ m_trck,
+ m_sect,
+ 128 << ((m_cmd1 >> 5) & 3));
+ m_state = S_WAIT_HEADER_SYNC;
+ m_stat0 &= ~S0_FREE;
+ m_window_start = m_last_sync;
+ break;
+ }
+}
+
+void thmfc1_device::cmd1_w(u8 data)
+{
+ sync();
+
+ m_cmd1 = data;
+ logerror("cmd1_w %02x, sector=(size=%d, side=%d) precomp=%d sync_only_when_ready=%s\n", m_cmd1,
+ 128 << ((m_cmd1 >> 5) & 3),
+ m_cmd1 & C1_SIDE ? 1 : 0,
+ (m_cmd1 >> 1) & 7,
+ m_cmd1 & C1_DSYRD ? "on" : "off");
+}
+
+void thmfc1_device::cmd2_w(u8 data)
+{
+ sync();
+
+ u8 prev = m_cmd2;
+
+ m_cmd2 = data;
+ logerror("cmd2_w %02x, side=%d dir=%d step=%d motor=%s sel=%c%c\n", m_cmd2,
+ m_cmd2 & C2_SISELB ? 1 : 0,
+ m_cmd2 & C2_DIRECB ? 1 : 0,
+ m_cmd2 & C2_STEP ? 1 : 0,
+ m_cmd2 & C2_MTON ? "on" : "off",
+ m_cmd2 & C2_DRS1 ? 'b' : '-',
+ m_cmd2 & C2_DRS0 ? 'a' : '-');
+
+ if(m_cmd2 & C2_DRS0)
+ m_cur_floppy = m_floppy[0]->get_device();
+ else if(m_cmd2 & C2_DRS1)
+ m_cur_floppy = m_floppy[1]->get_device();
+ else
+ m_cur_floppy = nullptr;
+
+ if(m_cur_floppy) {
+ if((prev & C2_MTON) && !(m_cmd2 & C2_MTON))
+ m_timer_motoroff->adjust(attotime::from_seconds(2));
+ if(m_cmd2 & C2_MTON) {
+ m_cur_floppy->mon_w(0);
+ m_timer_motoroff->adjust(attotime::never);
+ }
+ m_cur_floppy->ss_w(m_cmd2 & C2_SISELB ? 0 : 1);
+ m_cur_floppy->dir_w(m_cmd2 & C2_DIRECB ? 0 : 1);
+ m_cur_floppy->stp_w(m_cmd2 & C2_STEP ? 0 : 1);
+ }
+}
+
+void thmfc1_device::wdata_w(u8 data)
+{
+ m_data = data;
+ m_stat0 &= ~(S0_BYTE | S0_DREQ);
+ logerror("wdata_w %02x\n", data);
+}
+
+void thmfc1_device::wclk_w(u8 data)
+{
+ sync();
+
+ m_clk = data;
+ logerror("wclk_w %02x\n", data);
+}
+
+void thmfc1_device::wsect_w(u8 data)
+{
+ sync();
+
+ m_sect = data;
+ logerror("wsect_w %02x\n", data);
+}
+
+void thmfc1_device::wtrck_w(u8 data)
+{
+ sync();
+
+ m_trck = data;
+ logerror("wtrck_w %02x\n", data);
+}
+
+void thmfc1_device::wcell_w(u8 data)
+{
+ sync();
+
+ m_cell = data;
+ logerror("wcell_w %02x\n", data);
+}
+
+u8 thmfc1_device::stat0_r()
+{
+ if(!machine().side_effects_disabled()) {
+ sync();
+#if 0
+ static int ps = -1;
+ if(m_stat0 != ps)
+ logerror("stat0_r %02x -%s%s%s%s%s%s\n", m_stat0,
+ m_stat0 & S0_BYTE ? " byte" : "",
+ m_stat0 & S0_END ? " end" : "",
+ m_stat0 & S0_FREE ? " free" : "",
+ m_stat0 & S0_CRCER ? " crcer" : "",
+ m_stat0 & S0_DREQ ? " dreq" : "",
+ m_stat0 & S0_SYNC ? " sync" : "");
+ ps = m_stat0;
+#endif
+ }
+ return m_stat0;
+}
+
+u8 thmfc1_device::stat1_r()
+{
+ u8 res = 0;
+ if(m_cur_floppy) {
+ if(m_cur_floppy->idx_r())
+ res |= S1_INDX;
+ if(!m_cur_floppy->dskchg_r())
+ res |= S1_DKCH;
+ if(!m_cur_floppy->mon_r())
+ res |= S1_MTON;
+ if(!m_cur_floppy->trk00_r())
+ res |= S1_TRK0;
+ if(!m_cur_floppy->wpt_r())
+ res |= S1_WPRT;
+ if(!m_cur_floppy->ready_r())
+ res |= S1_RDY;
+ }
+
+ if(!machine().side_effects_disabled())
+ logerror("stat1_r %02x -%s%s%s%s%s%s\n", res,
+ res & S1_INDX ? " index" : "",
+ res & S1_DKCH ? " dskchg" : "",
+ res & S1_MTON ? " mton" : "",
+ res & S1_TRK0 ? " trk0" : "",
+ res & S1_WPRT ? " wprt" : "",
+ res & S1_RDY ? " ready" : "");
+ return res;
+}
+
+u8 thmfc1_device::rdata_r()
+{
+ if(!machine().side_effects_disabled()) {
+ logerror("rdata_r %02X (stat0=%02X)\n", m_data, m_stat0);
+ m_stat0 &= ~(S0_BYTE | S0_DREQ);
+ }
+ return m_data;
+}
+
+u64 thmfc1_device::time_to_cycles(const attotime &tm) const
+{
+ return tm.as_ticks(clock());
+}
+
+attotime thmfc1_device::cycles_to_time(u64 cycles) const
+{
+ return attotime::from_ticks(cycles, clock());
+}
+
+bool thmfc1_device::read_one_bit(u64 limit, u64 &next_flux_change)
+{
+ while(next_flux_change <= m_last_sync) {
+ attotime flux = m_cur_floppy ? m_cur_floppy->get_next_transition(cycles_to_time(m_last_sync+1)) : attotime::never;
+ next_flux_change = flux.is_never() ? u64(-1) : time_to_cycles(flux);
+ }
+
+ u64 window_end = m_window_start + (m_cell & 0x7f);
+ if(window_end > limit)
+ return true;
+
+ int bit = next_flux_change < window_end;
+ if(bit && (m_cmd0 & C0_NOMCK))
+ m_window_start = next_flux_change + ((m_cell & 0x7f) >> 1);
+ else
+ m_window_start = window_end;
+
+ m_last_sync = window_end;
+
+ m_shift_reg = (m_shift_reg << 1) | bit;
+ m_bit_counter++;
+ if(m_data_separator_phase) {
+ m_data_reg = (m_data_reg << 1) | bit;
+ if((m_crc ^ (bit ? 0x8000 : 0x0000)) & 0x8000)
+ m_crc = (m_crc << 1) ^ 0x1021;
+ else
+ m_crc = m_crc << 1;
+ }
+
+ m_data_separator_phase = !m_data_separator_phase;
+ return false;
+}
+
+u8 thmfc1_device::clk_bits() const
+{
+ return
+ (m_shift_reg & 0x8000 ? 0x80 : 0x00) |
+ (m_shift_reg & 0x2000 ? 0x40 : 0x00) |
+ (m_shift_reg & 0x0800 ? 0x20 : 0x00) |
+ (m_shift_reg & 0x0200 ? 0x10 : 0x00) |
+ (m_shift_reg & 0x0080 ? 0x08 : 0x00) |
+ (m_shift_reg & 0x0020 ? 0x04 : 0x00) |
+ (m_shift_reg & 0x0008 ? 0x02 : 0x00) |
+ (m_shift_reg & 0x0002 ? 0x01 : 0x00);
+}
+
+
+void thmfc1_device::sync()
+{
+ u64 next_sync = machine().time().as_ticks(clock());
+ u64 next_flux_change = 0;
+ while(m_last_sync < next_sync)
+ switch(m_state) {
+ case S_IDLE:
+ m_last_sync = next_sync;
+ break;
+
+ case S_WAIT_HEADER_SYNC: {
+ if(read_one_bit(next_sync, next_flux_change))
+ return;
+ if(m_shift_reg == 0xaaaa) {
+ m_crc = 0xffff;
+ m_data_separator_phase = false;
+ }
+ if(m_data_reg == m_data && clk_bits() == m_clk) {
+ m_bit_counter = 0;
+ m_state = S_VERIFY_HEADER;
+ }
+ break;
+ }
+
+ case S_VERIFY_HEADER: {
+ if(read_one_bit(next_sync, next_flux_change))
+ return;
+ if(m_bit_counter & 0xf)
+ break;
+ bool valid = true;
+ switch(m_bit_counter >> 4) {
+ case 1:
+ case 2:
+ valid = m_data_reg == m_data && clk_bits() == m_clk;
+ break;
+ case 3:
+ valid = m_data_reg == 0xfe;
+ break;
+ case 4:
+ valid = m_data_reg == m_trck;
+ break;
+ case 5:
+ valid = (m_data_reg & 1) == (m_cmd1 & C1_SIDE ? 1 : 0);
+ break;
+ case 6:
+ valid = m_data_reg == m_sect;
+ break;
+ case 7:
+ valid = (m_data_reg & 3) == ((m_cmd1 >> 5) & 3);
+ break;
+ // 8 skipped
+ case 9:
+ valid = m_crc == 0;
+ m_bit_counter = 0;
+ m_state = S_SKIP_GAP;
+ break;
+ }
+ if(!valid)
+ m_state = S_WAIT_HEADER_SYNC;
+ break;
+ }
+
+ case S_SKIP_GAP:
+ if(read_one_bit(next_sync, next_flux_change))
+ return;
+ if(m_bit_counter == 27 << 4) {
+ m_bit_counter = 0;
+ m_state = S_WAIT_SECTOR_SYNC;
+ }
+ break;
+
+
+ case S_WAIT_SECTOR_SYNC: {
+ if(read_one_bit(next_sync, next_flux_change))
+ return;
+ if(m_shift_reg == 0xaaaa) {
+ m_crc = 0xffff;
+ m_data_separator_phase = false;
+ }
+ if(m_data_reg == m_data && clk_bits() == m_clk) {
+ m_bit_counter = 0;
+ m_data = m_data_reg;
+ m_stat0 |= S0_DREQ;
+ m_state = S_READ_SECTOR;
+ }
+ if(m_bit_counter == 42 << 4)
+ m_state = S_WAIT_HEADER_SYNC;
+ break;
+ }
+
+ case S_READ_SECTOR:
+ if(read_one_bit(next_sync, next_flux_change))
+ return;
+ if(m_bit_counter != 16)
+ break;
+ if(m_stat0 & (S0_BYTE|S0_DREQ)) {
+ logerror("read_sector end\n");
+ if(m_crc)
+ m_stat0 |= S0_CRCER;
+ m_stat0 &= ~S0_BYTE;
+ m_stat0 |= S0_FREE;
+ m_cmd0 &= ~3;
+ m_state = S_IDLE;
+ break;
+ }
+ m_stat0 |= S0_BYTE;
+ m_data = m_data_reg;
+ m_bit_counter = 0;
+ break;
+ }
+}
diff --git a/src/devices/machine/thmfc1.h b/src/devices/machine/thmfc1.h
new file mode 100644
index 00000000000..60a6d0f9183
--- /dev/null
+++ b/src/devices/machine/thmfc1.h
@@ -0,0 +1,106 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+#ifndef MAME_MACHINE_THMFC1_H
+#define MAME_MACHINE_THMFC1_H
+
+#pragma once
+
+#include "imagedev/floppy.h"
+
+class thmfc1_device : public device_t
+{
+public:
+ thmfc1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~thmfc1_device() = default;
+
+ void map(address_map &map) ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_post_load() override;
+
+ TIMER_CALLBACK_MEMBER(motor_off);
+
+private:
+ enum {
+ S0_BYTE = 0x80,
+ S0_END = 0x10,
+ S0_FREE = 0x08,
+ S0_CRCER = 0x04,
+ S0_DREQ = 0x02,
+ S0_SYNC = 0x01,
+
+ S1_INDX = 0x40,
+ S1_DKCH = 0x20,
+ S1_MTON = 0x10,
+ S1_TRK0 = 0x08,
+ S1_WPRT = 0x04,
+ S1_RDY = 0x02,
+
+ C0_FM = 0x20,
+ C0_ENSYN = 0x10,
+ C0_NOMCK = 0x08,
+ C0_WGC = 0x04,
+
+ C1_SIDE = 0x10,
+ C1_DSYRD = 0x01,
+
+ C2_SISELB = 0x40,
+ C2_DIRECB = 0x20,
+ C2_STEP = 0x10,
+ C2_MTON = 0x04,
+ C2_DRS1 = 0x02,
+ C2_DRS0 = 0x01,
+ };
+
+ enum {
+ S_IDLE,
+ S_WAIT_HEADER_SYNC,
+ S_VERIFY_HEADER,
+ S_SKIP_GAP,
+ S_WAIT_SECTOR_SYNC,
+ S_READ_SECTOR,
+ };
+
+ required_device_array<floppy_connector, 2> m_floppy;
+ floppy_image_device *m_cur_floppy;
+ emu_timer *m_timer_motoroff;
+
+ u64 m_last_sync, m_window_start;
+ int m_state;
+
+ u16 m_shift_reg, m_crc, m_bit_counter;
+ u8 m_data_reg;
+
+ u8 m_cmd0, m_cmd1, m_cmd2, m_stat0;
+ u8 m_data, m_clk, m_sect, m_trck, m_cell;
+
+ bool m_data_separator_phase;
+
+ u8 clk_bits() const;
+
+ void cmd0_w(u8 data);
+ void cmd1_w(u8 data);
+ void cmd2_w(u8 data);
+ void wdata_w(u8 data);
+ void wclk_w(u8 data);
+ void wsect_w(u8 data);
+ void wtrck_w(u8 data);
+ void wcell_w(u8 data);
+
+ u8 stat0_r();
+ u8 stat1_r();
+ u8 rdata_r();
+
+ u64 time_to_cycles(const attotime &tm) const;
+ attotime cycles_to_time(u64 cycles) const;
+
+ void sync();
+ bool read_one_bit(u64 limit, u64 &next_flux_change);
+};
+
+DECLARE_DEVICE_TYPE(THMFC1, thmfc1_device)
+
+#endif // MAME_MACHINE_THMFC1_H
diff --git a/src/lib/formats/thom_dsk.cpp b/src/lib/formats/thom_dsk.cpp
index ad2e4495ca2..f63b35f06ad 100644
--- a/src/lib/formats/thom_dsk.cpp
+++ b/src/lib/formats/thom_dsk.cpp
@@ -50,6 +50,12 @@ const thomson_525_format::format thomson_525_format::formats[] = {
{}
};
+int thomson_525_format::get_image_offset(const format &f, int head, int track) const
+{
+ return (track + (head ? f.track_count : 0)) * compute_track_size(f);
+}
+
+
thomson_35_format::thomson_35_format() : wd177x_format(formats)
{
@@ -90,5 +96,10 @@ const thomson_35_format::format thomson_35_format::formats[] = {
{}
};
+int thomson_35_format::get_image_offset(const format &f, int head, int track) const
+{
+ return (track + (head ? f.track_count : 0)) * compute_track_size(f);
+}
+
const thomson_525_format FLOPPY_THOMSON_525_FORMAT;
const thomson_35_format FLOPPY_THOMSON_35_FORMAT;
diff --git a/src/lib/formats/thom_dsk.h b/src/lib/formats/thom_dsk.h
index 52927f15de8..09ea1cbec0c 100644
--- a/src/lib/formats/thom_dsk.h
+++ b/src/lib/formats/thom_dsk.h
@@ -16,6 +16,8 @@ public:
virtual const char *description() const noexcept override;
virtual const char *extensions() const noexcept override;
+ int get_image_offset(const format &f, int head, int track) const override;
+
private:
static const format formats[];
};
@@ -29,6 +31,8 @@ public:
virtual const char *description() const noexcept override;
virtual const char *extensions() const noexcept override;
+ int get_image_offset(const format &f, int head, int track) const override;
+
private:
static const format formats[];
};
diff --git a/src/mame/thomson/thomson.cpp b/src/mame/thomson/thomson.cpp
index 67d77a2f035..2d6e844c1f5 100644
--- a/src/mame/thomson/thomson.cpp
+++ b/src/mame/thomson/thomson.cpp
@@ -92,12 +92,11 @@
#include "bus/thomson/speech.h"
#include "machine/clock.h"
#include "machine/ram.h"
-#include "machine/wd_fdc.h"
+#include "machine/thmfc1.h"
#include "softlist_dev.h"
#include "speaker.h"
-#include "formats/basicdsk.h"
#include "formats/thom_cas.h"
#include "formats/thom_dsk.h"
@@ -474,6 +473,23 @@ static INPUT_PORTS_START ( t9000 )
PORT_INCLUDE ( to7 )
INPUT_PORTS_END
+static void to9_floppy_drives(device_slot_interface &device)
+{
+ device.option_add("dd90_352", FLOPPY_35_DD);
+}
+
+static void to8_floppy_drives(device_slot_interface &device)
+{
+ device.option_add("dd90_352", FLOPPY_35_DD);
+ // device.option_add("qd90_280", FLOPPY_28_QDD);
+}
+
+static void to35_floppy_formats(format_registration &fr)
+{
+ fr.add_pc_formats();
+ fr.add(FLOPPY_THOMSON_35_FORMAT);
+}
+
/* ------------ driver ------------ */
void thomson_state::to7_base(machine_config &config, bool is_mo)
@@ -1037,7 +1053,7 @@ It was replaced quickly with the improved TO9+.
- MD 90-120: MODEM extension (identical to the TO7)
- IEEE extension ? (unemulated)
- floppy:
- . integrated floppy controller, based on WD2793
+ . integrated floppy controller, based on WD1770 or WD2793
. integrated one-sided double-density 3''1/2
. external two-sided double-density 3''1/2, 5''1/4 or QDD (extension)
. floppies are TO7 and MO5 compatible
@@ -1057,6 +1073,8 @@ void to9_state::to9_map(address_map &map)
map(0xe7c0, 0xe7c7).rw(m_mc6846, FUNC(mc6846_device::read), FUNC(mc6846_device::write));
map(0xe7c8, 0xe7cb).rw("pia_0", FUNC(pia6821_device::read_alt), FUNC(pia6821_device::write_alt));
map(0xe7cc, 0xe7cf).rw("pia_1", FUNC(pia6821_device::read_alt), FUNC(pia6821_device::write_alt));
+ map(0xe7d0, 0xe7d3).mirror(4).rw(m_fdc, FUNC(wd_fdc_device_base::read), FUNC(wd_fdc_device_base::write));
+ map(0xe7d8, 0xe7d8).rw(FUNC(to9_state::to9_floppy_control_r), FUNC(to9_state::to9_floppy_control_w));
map(0xe7da, 0xe7dd).rw(FUNC(to9_state::to9_vreg_r), FUNC(to9_state::to9_vreg_w));
map(0xe7de, 0xe7df).rw(m_to9_kbd, FUNC(to9_keyboard_device::kbd_acia_r), FUNC(to9_keyboard_device::kbd_acia_w));
map(0xe7e4, 0xe7e7).rw(FUNC(to9_state::to9_gatearray_r), FUNC(to9_state::to9_gatearray_w));
@@ -1164,6 +1182,16 @@ void to9_state::to9(machine_config &config)
m_mc6846->out_port().set(FUNC(to9_state::to9_timer_port_out));
+ WD1770(config, m_fdc, 16_MHz_XTAL / 2);
+ FLOPPY_CONNECTOR(config, m_floppy[0], to9_floppy_drives, "dd90_352", to35_floppy_formats, true).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], to9_floppy_drives, nullptr, to35_floppy_formats, false).enable_sound(true);
+
+ m_extension->option_remove("cd90_015");
+ m_extension->option_remove("cq90_028");
+ m_extension->option_remove("cd90_351");
+ m_extension->option_remove("cd90_640");
+ m_extension->option_remove("nanoreseau");
+
CENTRONICS(config, m_centronics, centronics_devices, "printer");
m_centronics->busy_handler().set(FUNC(to9_state::write_centronics_busy));
@@ -1252,6 +1280,7 @@ void to9_state::to8_map(address_map &map)
map(0xe7c0, 0xe7c7).rw(m_mc6846, FUNC(mc6846_device::read), FUNC(mc6846_device::write));
map(0xe7c8, 0xe7cb).rw("pia_0", FUNC(pia6821_device::read_alt), FUNC(pia6821_device::write_alt));
map(0xe7cc, 0xe7cf).rw("pia_1", FUNC(pia6821_device::read_alt), FUNC(pia6821_device::write_alt));
+ map(0xe7d0, 0xe7d7).m("thmfc1", FUNC(thmfc1_device::map));
map(0xe7da, 0xe7dd).rw(FUNC(to9_state::to8_vreg_r), FUNC(to9_state::to8_vreg_w));
map(0xe7e4, 0xe7e7).rw(FUNC(to9_state::to8_gatearray_r), FUNC(to9_state::to8_gatearray_w));
/* map(0xe7f0, 0xe7f7).rw(FUNC(to9_state::to9_ieee_r), FUNC(to9_state::to9_ieee_w )); */
@@ -1361,6 +1390,16 @@ void to9_state::to8(machine_config &config)
m_pia_sys->cb2_handler().set_nop();
m_pia_sys->irqa_handler().set_nop();
+ THMFC1(config, "thmfc1", 16_MHz_XTAL);
+ FLOPPY_CONNECTOR(config, "thmfc1:0", to8_floppy_drives, "dd90_352", to35_floppy_formats, false).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "thmfc1:1", to8_floppy_drives, nullptr, to35_floppy_formats, false).enable_sound(true);
+
+ m_extension->option_remove("cd90_015");
+ m_extension->option_remove("cq90_028");
+ m_extension->option_remove("cd90_351");
+ m_extension->option_remove("cd90_640");
+ m_extension->option_remove("nanoreseau");
+
CENTRONICS(config, m_centronics, centronics_devices, "printer");
m_centronics->busy_handler().set(FUNC(to9_state::write_centronics_busy));
@@ -1380,6 +1419,7 @@ void to9_state::to8(machine_config &config)
void to9_state::to8d(machine_config &config)
{
to8(config);
+ subdevice<floppy_connector>("thmfc1:0")->set_fixed(true);
}
@@ -1439,6 +1479,7 @@ void to9_state::to9p_map(address_map &map)
map(0xe7c0, 0xe7c7).rw(m_mc6846, FUNC(mc6846_device::read), FUNC(mc6846_device::write));
map(0xe7c8, 0xe7cb).rw("pia_0", FUNC(pia6821_device::read_alt), FUNC(pia6821_device::write_alt));
map(0xe7cc, 0xe7cf).rw("pia_1", FUNC(pia6821_device::read_alt), FUNC(pia6821_device::write_alt));
+ map(0xe7d0, 0xe7d7).m("thmfc1", FUNC(thmfc1_device::map));
map(0xe7da, 0xe7dd).rw(FUNC(to9_state::to8_vreg_r), FUNC(to9_state::to8_vreg_w));
map(0xe7de, 0xe7df).rw(m_to9_kbd, FUNC(to9_keyboard_device::kbd_acia_r), FUNC(to9_keyboard_device::kbd_acia_w));
map(0xe7e4, 0xe7e7).rw(FUNC(to9_state::to8_gatearray_r), FUNC(to9_state::to8_gatearray_w));
@@ -1516,6 +1557,16 @@ void to9_state::to9p(machine_config &config)
m_pia_sys->irqa_handler().set_nop();
m_pia_sys->irqb_handler().set("mainfirq", FUNC(input_merger_device::in_w<1>));
+ THMFC1(config, "thmfc1", 16_MHz_XTAL);
+ FLOPPY_CONNECTOR(config, "thmfc1:0", to8_floppy_drives, "dd90_352", to35_floppy_formats, true).enable_sound(true);
+ FLOPPY_CONNECTOR(config, "thmfc1:1", to8_floppy_drives, nullptr, to35_floppy_formats, false).enable_sound(true);
+
+ m_extension->option_remove("cd90_015");
+ m_extension->option_remove("cq90_028");
+ m_extension->option_remove("cd90_351");
+ m_extension->option_remove("cd90_640");
+ m_extension->option_remove("nanoreseau");
+
CENTRONICS(config, m_centronics, centronics_devices, "printer");
m_centronics->busy_handler().set(FUNC(to9_state::write_centronics_busy));
diff --git a/src/mame/thomson/thomson.h b/src/mame/thomson/thomson.h
index 905a7105698..69467714003 100644
--- a/src/mame/thomson/thomson.h
+++ b/src/mame/thomson/thomson.h
@@ -17,10 +17,12 @@
#include "cpu/m6809/m6809.h"
#include "imagedev/cassette.h"
+#include "imagedev/floppy.h"
#include "machine/6821pia.h"
#include "machine/input_merger.h"
#include "machine/mc6846.h"
#include "machine/ram.h"
+#include "machine/wd_fdc.h"
#include "sound/dac.h"
#include "bus/thomson/extension.h"
#include "bus/thomson/nanoreseau.h"
@@ -388,6 +390,8 @@ public:
thomson_state(mconfig, type, tag),
m_to8_kbd(*this, "to8_kbd"),
m_to9_kbd(*this, "to9_kbd"),
+ m_fdc(*this, "fdc"),
+ m_floppy(*this, "fdc:%u", 0U),
m_centronics(*this, "centronics"),
m_cent_data_out(*this, "cent_data_out"),
m_syslobank(*this, TO8_SYS_LO),
@@ -406,6 +410,8 @@ public:
protected:
optional_device<to8_keyboard_device> m_to8_kbd;
optional_device<to9_keyboard_device> m_to9_kbd;
+ optional_device<wd_fdc_device_base> m_fdc;
+ optional_device_array<floppy_connector, 2> m_floppy;
optional_device<centronics_device> m_centronics;
optional_device<output_latch_device> m_cent_data_out;
@@ -470,6 +476,10 @@ protected:
void to9_sys_porta_out(uint8_t data);
void to9_sys_portb_out(uint8_t data);
void to9_timer_port_out(uint8_t data);
+ uint8_t to9_fdc_r(offs_t offset);
+ void to9_fdc_w(offs_t offset, uint8_t data);
+ uint8_t to9_floppy_control_r();
+ void to9_floppy_control_w(uint8_t data);
DECLARE_MACHINE_RESET( to9 );
DECLARE_MACHINE_START( to9 );
uint8_t to9p_timer_port_in();
@@ -481,6 +491,7 @@ protected:
void to9_map(address_map &map) ATTR_COLD;
void to9p_map(address_map &map) ATTR_COLD;
+ uint8_t m_to9_floppy_control = 0;
uint8_t m_to9_palette_data[32]{};
uint8_t m_to9_palette_idx = 0;
uint8_t m_to9_soft_bank = 0;
diff --git a/src/mame/thomson/thomson_m.cpp b/src/mame/thomson/thomson_m.cpp
index b5bc183160d..7046871267b 100644
--- a/src/mame/thomson/thomson_m.cpp
+++ b/src/mame/thomson/thomson_m.cpp
@@ -1728,6 +1728,33 @@ void to9_state::to9_timer_port_out(uint8_t data)
}
+
+/* ------------ WD disk controller ------------ */
+
+
+
+void to9_state::to9_floppy_control_w(u8 data)
+{
+ m_to9_floppy_control = data;
+
+ floppy_image_device *floppy = nullptr;
+ if (BIT(m_to9_floppy_control, 1))
+ floppy = m_floppy[0]->get_device();
+ else if (BIT(m_to9_floppy_control, 2))
+ floppy = m_floppy[1]->get_device();
+ if (floppy)
+ floppy->ss_w(BIT(m_to9_floppy_control, 0));
+ m_fdc->set_floppy(floppy);
+
+ m_fdc->dden_w(BIT(m_to9_floppy_control, 7));
+}
+
+uint8_t to9_state::to9_floppy_control_r()
+{
+ return m_to9_floppy_control & 0x80;
+}
+
+
/* ------------ init / reset ------------ */
@@ -1780,6 +1807,10 @@ MACHINE_START_MEMBER( to9_state, to9 )
m_extension->rom_map(m_maincpu->space(AS_PROGRAM), 0xe000, 0xe7bf);
m_extension->io_map (m_maincpu->space(AS_PROGRAM), 0xe7c0, 0xe7ff);
+ m_to9_floppy_control = 0;
+ m_fdc->set_floppy(nullptr);
+ m_fdc->dden_w(0);
+
/* memory */
m_thom_vram = ram;
m_thom_cart_bank = 0;
@@ -1799,6 +1830,7 @@ MACHINE_START_MEMBER( to9_state, to9 )
save_item(NAME(m_to7_lightpen));
save_item(NAME(m_to7_lightpen_step));
save_item(NAME(m_to9_soft_bank));
+ save_item(NAME(m_to9_floppy_control));
save_pointer(NAME(cartmem), 0x10000 );
machine().save().register_postload(save_prepost_delegate(FUNC(to9_state::to9_update_ram_bank_postload), this));
machine().save().register_postload(save_prepost_delegate(FUNC(to9_state::to9_update_cart_bank_postload), this));
diff --git a/src/mame/thomson/to_kbd.cpp b/src/mame/thomson/to_kbd.cpp
index daf653db12c..12bbc042910 100644
--- a/src/mame/thomson/to_kbd.cpp
+++ b/src/mame/thomson/to_kbd.cpp
@@ -16,7 +16,7 @@
#define LOG_KBD (1U << 1)
#define LOG_ERRORS (1U << 2)
-#define VERBOSE (LOG_KBD | LOG_ERRORS)
+//#define VERBOSE (LOG_KBD | LOG_ERRORS)
#include "logmacro.h"