Overview
FM1Kit speaks the FM-1's update protocol. It reads .fwsc firmware packages, finds the device, answers its read requests while it stages and writes the new firmware, and checks the device reports the new firmware afterwards. It can also finish an update that was cut off, or one started from USB recovery mode.
It sticks to the device: finding and downloading firmwares is left to your app. FM-SWITCH is built on it.
ImportantFM1Kit has been tested on one FM-1 so far, from both a Mac and an iPhone. It isn't affiliated with M-VAVE, and installing custom firmware is at your own risk.
Install the package
Add FM1Kit with Swift Package Manager. Until 1.0, minor versions may change the API, so take 0.2.x fixes but not 0.3.0.
.package(url: "https://github.com/ocean/FM1Kit.git", .upToNextMinor(from: "0.2.0")),
Install a firmware
Read the package, check what installing it would do, then install it and follow its progress. Switching to a different firmware can erase the FM-1's projects and samples, so it needs confirming.
import FM1Kit
let package = try FwscPackage(data: Data(contentsOf: fileURL))
let updater = FM1Updater(transport: try CoreMIDITransport(clientName: "My App"))
let check = try await updater.check(package)
let confirmed = check.kind != .switchingFirmware || askToSwitch(from: check.device)
try await updater.install(package, options: InstallOptions(confirmsSwitchingFirmware: confirmed)) { event in
switch event {
case .writing(let fraction, _): print("Writing \(Int(fraction * 100))%")
case .finished(let identity): print("Now running \(identity)")
default: break
}
}
// Finish an update that was cut off, or one started in USB recovery mode.
if let identity = await updater.identify(), identity.isLoader {
try await updater.resume(package)
}
Topics
Packages
- structFwscPackage
Reads a
.fwscpackage: its identity, the image the device reads, and its SHA-256. - structOfficialFirmware
Recognises M-VAVE's official releases, V15 and Open V12, by size and checksum.
Devices
- structFM1Identity
Parses what a device reports, such as
FM-1_916, orota-FM-1_015for the update loader. - structFM1Capability
What M-VAVE's open firmware reports about itself.
- structFM1BuildID
The build ID open firmware is armed with before an update.
Updating
- actorFM1Updater
Finds the device, checks and installs, resumes, restores V15's voices, and reports progress.
- structInstallCheck
What an install would do, before it starts.
- structInstallOptions
Confirms a switch of firmware, or a reinstall of the identity already running.
- enumUpdateEvent
Progress: staging, writing, an optional checking pass, and finished.
Transports
- classCoreMIDITransport
CoreMIDI connections to real devices.
- classSimulatedFM1
A software FM-1 that speaks the whole protocol, for the iOS Simulator and tests.
fm1probe
A Mac command-line tool for checking a setup and watching an install closely. Only install and restore-voices write to the device, and only after you type YES.
swift run fm1probe ports # list MIDI ports
swift run fm1probe identify # ask the FM-1 what it's running
swift run fm1probe inspect FILE.fwsc # a package's identity, size and checksum
swift run fm1probe install FILE.fwsc # install a firmware
Recovery
Whenever the FM-1 is in its update loader, whether from USB recovery mode (hold OCT− while switching it on, on firmwares that offer it) or an interrupted update, resume(_:events:) can install a firmware. Beyond that is the chip's ROM bootloader, which FM1Kit doesn't cover.
See also
Source, documentation and changelog on GitHub
FM-1-RE: the reverse-engineering notes the protocol is written from.