From 96a9ae2ca5b0137f50a2f1130326ad1657c719b9 Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Thu, 17 Nov 2022 08:52:33 -0400 Subject: [PATCH] chore: refactor flash impl --- src/core/bus/backup.zig | 57 ++++--------------------- src/core/bus/backup/Flash.zig | 79 ++++++++++++++++++++++++++--------- 2 files changed, 67 insertions(+), 69 deletions(-) diff --git a/src/core/bus/backup.zig b/src/core/bus/backup.zig index fb96f73..5bb6547 100644 --- a/src/core/bus/backup.zig +++ b/src/core/bus/backup.zig @@ -40,61 +40,18 @@ pub const Backup = struct { None, }; - pub fn read(self: *const Self, address: usize) u8 { - const addr = address & 0xFFFF; - + pub fn read(self: *const Self, address: u32) u8 { switch (self.kind) { - .Flash => { - switch (addr) { - 0x0000 => if (self.flash.id_mode) return 0x32, // Panasonic manufacturer ID - 0x0001 => if (self.flash.id_mode) return 0x1B, // Panasonic device ID - else => {}, - } - - return self.flash.read(self.buf, addr); - }, - .Flash1M => { - switch (addr) { - 0x0000 => if (self.flash.id_mode) return 0x62, // Sanyo manufacturer ID - 0x0001 => if (self.flash.id_mode) return 0x13, // Sanyo device ID - else => {}, - } - - return self.flash.read(self.buf, addr); - }, - .Sram => return self.buf[addr & 0x7FFF], // 32K SRAM chip is mirrored + .Flash, .Flash1M => return self.flash.read(self.buf, address), + .Sram => return self.buf[address & 0x7FFF], // 32K SRAM chip is mirrored .None, .Eeprom => return 0xFF, } } - pub fn write(self: *Self, address: usize, byte: u8) void { - const addr = address & 0xFFFF; - + pub fn write(self: *Self, address: u32, value: u8) void { switch (self.kind) { - .Flash, .Flash1M => { - if (self.flash.prep_write) return self.flash.write(self.buf, addr, byte); - if (self.flash.shouldEraseSector(addr, byte)) return self.flash.erase(self.buf, addr); - - switch (addr) { - 0x0000 => if (self.kind == .Flash1M and self.flash.set_bank) { - self.flash.bank = @truncate(u1, byte); - }, - 0x5555 => { - if (self.flash.state == .Command) { - self.flash.handleCommand(self.buf, byte); - } else if (byte == 0xAA and self.flash.state == .Ready) { - self.flash.state = .Set; - } else if (byte == 0xF0) { - self.flash.state = .Ready; - } - }, - 0x2AAA => if (byte == 0x55 and self.flash.state == .Set) { - self.flash.state = .Command; - }, - else => {}, - } - }, - .Sram => self.buf[addr & 0x7FFF] = byte, + .Flash, .Flash1M => self.flash.write(self.buf, address, value), + .Sram => self.buf[address & 0x7FFF] = value, .None, .Eeprom => {}, } } @@ -118,7 +75,7 @@ pub const Backup = struct { .kind = kind, .title = title, .save_path = path, - .flash = Flash.create(), + .flash = try Flash.create(if (kind == .Flash1M) .Flash1M else .Flash), .eeprom = Eeprom.create(allocator), }; diff --git a/src/core/bus/backup/Flash.zig b/src/core/bus/backup/Flash.zig index b665b82..b9af071 100644 --- a/src/core/bus/backup/Flash.zig +++ b/src/core/bus/backup/Flash.zig @@ -3,42 +3,83 @@ const std = @import("std"); const Self = @This(); state: State, +kind: Kind, +bank: u1, id_mode: bool, set_bank: bool, prep_erase: bool, prep_write: bool, -bank: u1, +const Kind = enum { Flash, Flash1M }; +const State = enum { Ready, Set, Command }; -const State = enum { - Ready, - Set, - Command, -}; +pub fn read(self: *const Self, buf: []u8, address: u32) u8 { + const addr = address & 0xFFFF; -pub fn read(self: *const Self, buf: []u8, idx: usize) u8 { - return buf[self.address() + idx]; + if (self.kind == .Flash1M) { + switch (addr) { + 0x0000 => if (self.id_mode) return 0x32, // Panasonic manufacturer ID + 0x0001 => if (self.id_mode) return 0x1B, // Panasonic device ID + else => {}, + } + } else { + switch (addr) { + 0x0000 => if (self.id_mode) return 0x62, // Sanyo manufacturer ID + 0x0001 => if (self.id_mode) return 0x13, // Sanyo device ID + else => {}, + } + } + + return buf[self.baseAddress() + addr]; } -pub fn write(self: *Self, buf: []u8, idx: usize, byte: u8) void { - buf[self.address() + idx] = byte; +pub fn write(self: *Self, buf: []u8, address: u32, value: u8) void { + const addr = address & 0xFFFF; + + if (self.prep_write) return self._write(buf, addr, value); + if (self.shouldEraseSector(addr, value)) return self.erase(buf, addr); + + switch (addr) { + 0x0000 => if (self.kind == .Flash1M and self.set_bank) { + self.bank = @truncate(u1, value); + }, + 0x5555 => { + if (self.state == .Command) { + self.handleCommand(buf, value); + } else if (value == 0xAA and self.state == .Ready) { + self.state = .Set; + } else if (value == 0xF0) { + self.state = .Ready; + } + }, + 0x2AAA => if (value == 0x55 and self.state == .Set) { + self.state = .Command; + }, + else => {}, + } +} + +fn _write(self: *Self, buf: []u8, idx: usize, byte: u8) void { + buf[self.baseAddress() + idx] = byte; self.prep_write = false; } -pub fn create() Self { +pub fn create(kind: Kind) !Self { return .{ .state = .Ready, + .kind = kind, + .bank = 0, + .id_mode = false, .set_bank = false, .prep_erase = false, .prep_write = false, - .bank = 0, }; } -pub fn handleCommand(self: *Self, buf: []u8, byte: u8) void { - switch (byte) { +fn handleCommand(self: *Self, buf: []u8, value: u8) void { + switch (value) { 0x90 => self.id_mode = true, 0xF0 => self.id_mode = false, 0xB0 => self.set_bank = true, @@ -48,18 +89,18 @@ pub fn handleCommand(self: *Self, buf: []u8, byte: u8) void { self.prep_erase = false; }, 0xA0 => self.prep_write = true, - else => std.debug.panic("Unhandled Flash Command: 0x{X:0>2}", .{byte}), + else => std.debug.panic("Unhandled Flash Command: 0x{X:0>2}", .{value}), } self.state = .Ready; } -pub fn shouldEraseSector(self: *const Self, addr: usize, byte: u8) bool { +fn shouldEraseSector(self: *const Self, addr: usize, byte: u8) bool { return self.state == .Command and self.prep_erase and byte == 0x30 and addr & 0xFFF == 0x000; } -pub fn erase(self: *Self, buf: []u8, sector: usize) void { - const start = self.address() + (sector & 0xF000); +fn erase(self: *Self, buf: []u8, sector: usize) void { + const start = self.baseAddress() + (sector & 0xF000); std.mem.set(u8, buf[start..][0..0x1000], 0xFF); self.prep_erase = false; @@ -67,6 +108,6 @@ pub fn erase(self: *Self, buf: []u8, sector: usize) void { } /// Base Address -inline fn address(self: *const Self) usize { +inline fn baseAddress(self: *const Self) usize { return if (self.bank == 1) 0x10000 else @as(usize, 0); }