Hi guys,
I'm working on the configuration file format for the DiscFerret. As I
might have mentioned earlier, this is based on the Lua programming
language -- in fact it *is* Lua. To load the config, the DiscFerret
tools fire up a Lua virtual machine, compile the config file into
bytecode, then run it and pick the config values out of the VM's global
state.
What this gives you is an absolute ton of flexibility: you can do things
like use a FOR loop to generate repeated Drive or Format specs.
Something like this:
for kv in { "pc35a", "pc35b" } do
drivetypes[kv] = {}
drivetypes[kv]['friendlyname'] = kv
drivetypes[kv]['crossed_cable'] = true
end
In the DiscFerret implementation, you have two config files:
- DriveSpec: these tell the software how to talk to a given drive.
Basically, what to do with the I/O lines.
- DiscSpec: these tell the software what the parameters of a given
disc are. Minimum/maximum track numbers, double stepping required (or
not), hard/soft sectored, and so on.
( There are also DecodeSpec files, which MagDAS uses to decode
transition data into disc images -- and which I'll document when I've
actually designed them! )
Here's an example DriveSpec file:
--------------------8<-----------8<----------------------------
--[[
#######################
# DiscFerret Disc Drive Specification File
#
# PC 3.5in Drives A and B, twisted cable or CBL-01A cable kit
#######################
]]
-- DriveSpec version flags
drivespec_version = 1.0
-- Drive types recognised by this drivespec
drivespec = {
pc35a = {
-- Passed to Drivespec functions
drivetype = "pc35a"
-- Shown to user
friendlyname = "PC 3.5\", twisted cable (CBL-01A), drive A"
-- Default step rate in milliseconds
steprate = 3.0
-- Spin-up time in milliseconds
spinup = 1000
}
pc35b = {
drivetype = "pc35b"
friendlyname = "PC 3.5\", twisted cable (CBL-01A), drive B"
steprate = 3.0
spinup = 1000
}
}
--[[
Given the drive type, track, head and sector, return a list of output
pins which need to be set.
Called once per sector on hard-sectored media, once per track on
soft-sectored media
--]]
function getDriveOutputs(drivetype, track, head, sector)
pins = 0
-- 3.5in FDD settings are really easy to set up. First start with drive
selects.
if drivetype == "pc35a" then
-- Shugart DS0 = motor enable A, DS2 = drive select A
pins = pins or PIN_DS0 or PIN_DS2
else if drivetype == "pc35b" then
-- Shugart DS1 = drive select B, MOTEN = motor enable B
pins = pins or PIN_DS1 or PIN_MOTEN
else
error("Unrecognised drive type '" .. drivetype .. "'.")
end
-- Handle side selection
if head == 0 then
-- do nothing, Head 0 is PIN_SIDESEL (p32) inactive/floating high
else if head == 1 then
pins = pins or PIN_SIDESEL
else
error("Head number " .. head .. " out of range.")
end
-- That's pretty much it, unless we need to provide TG46 on the DENSITY
pin.
return pins
end
--[[
Given the current drive status flags, identify whether the drive is
ready for use.
]]
function isDriveReady(drivetype, status)
-- 3.5in drives don't generally have a working READY output, and we
don't give a damn about DISK CHANGE.
-- If this were a Winchester drive, we'd be checking READY and SEEK
COMPLETE.
return true
end
--------------------8<-----------8<----------------------------
So in about 70 lines of code (a fair few of which are comments), we've
added full control support for two 3.5in PC floppy drives connected via
a crossed cable. With a few more LOCs we could add support for 8-inch
and 5.25-inch drives which require a 'TG46' signal on pin 2, or an 'IN
USE' signal to mount the heads or switch on the LED.
FormatSpecs are even simpler:
--------------------8<-----------8<----------------------------
--[[
#############################
# DiscFerret Format Specification File
#
# 40/80 track generic, soft sectored
#############################
]]
formatspec_version = 1.0
formatspec = {
gen40ds = {
-- format name
friendlyname = "40 track, double-sided, soft-sectored, generic"
-- minimum track number
mintrack = 0
-- maximum track number
maxtrack = 39
-- track stepping -- 1=singlestep, 2=doublestep
trackstep = 1
-- minimum head number
minhead = 0
-- maximum head number
maxhead = 1
-- sectoring; 0=soft-sectored, or number of sectors if hard-sectored
sectors = 0
}
gen40ds = {
-- format name
friendlyname = "40 track double-stepped, double-sided, soft-sectored,
generic"
-- minimum track number
mintrack = 0
-- maximum track number
maxtrack = 39
-- track stepping -- 1=singlestep, 2=doublestep
trackstep = 2
-- minimum head number
minhead = 0
-- maximum head number
maxhead = 1
-- sectoring; 0=soft-sectored, or number of sectors if hard-sectored
sectors = 0
}
gen80ds = {
-- format name
name = "80 track, double-sided, soft-sectored, generic"
-- minimum track number
mintrack = 0
-- maximum track number
maxtrack = 79
-- track stepping -- 1=singlestep, 2=doublestep
trackstep = 1
-- minimum head number
minhead = 0
-- maximum head number
maxhead = 1
-- sectoring; 0=soft-sectored
sectors = 0
}
}
--------------------8<-----------8<----------------------------
In about 60 lines of code, again mostly comments, we've added support
for three types of disc. Not bad. You could even go as far as generating
all of these in code when the script loads.
So on to the point of my message: does anyone have any comments to make
on this type of config file format?
Is there anything you'd like to see added, or done differently?
Thanks,
--
Phil.
classiccmp at philpem.me.uk
http://www.philpem.me.uk/