am29f.cpp (4008B)
1 #include "am29f.h" 2 3 #include <cassert> 4 5 #include "mc68k/logging.h" 6 #include "mc68k/mc68k.h" 7 8 namespace hwLib 9 { 10 Am29f::Am29f(uint8_t* _buffer, const size_t _size, const bool _useWriteEnable, const bool _bitreversedCmdAddr) : m_buffer(_buffer), m_size(_size), m_useWriteEnable(_useWriteEnable), m_bitreverseCmdAddr(_bitreversedCmdAddr) 11 { 12 auto br = [&](uint16_t x) 13 { 14 return m_bitreverseCmdAddr ? static_cast<uint16_t>(bitreverse(x) >> 4) : x; 15 }; 16 17 // Chip Erase 18 m_commands.push_back({{{br(0x555),0xAA}, {br(0x2AA),0x55}, {br(0x555),0x80}, {br(0x555),0xAA}, {br(0x2AA),0x55}, {br(0x555),0x10}}}); 19 20 // Sector Erase 21 m_commands.push_back({{{br(0x555),0xAA}, {br(0x2AA),0x55}, {br(0x555),0x80}, {br(0x555),0xAA}, {br(0x2AA),0x55}}}); 22 23 // Program 24 m_commands.push_back({{{br(0x555),0xAA}, {br(0x2AA),0x55}, {br(0x555),0xA0}}}); 25 } 26 27 void Am29f::write(const uint32_t _addr, const uint16_t _data) 28 { 29 const auto reset = [this]() 30 { 31 m_currentBusCycle = 0; 32 m_currentCommand = -1; 33 }; 34 35 if(!writeEnabled()) 36 { 37 reset(); 38 return; 39 } 40 41 bool anyMatch = false; 42 43 const auto d = _data & 0xff; 44 const auto a = _addr & 0xfff; 45 46 for (size_t i=0; i<m_commands.size(); ++i) 47 { 48 auto& cycles = m_commands[i].cycles; 49 50 if(m_currentBusCycle < cycles.size()) 51 { 52 const auto& c = cycles[m_currentBusCycle]; 53 54 if(c.addr == a && c.data == d) 55 { 56 anyMatch = true; 57 58 if(m_currentBusCycle == cycles.size() - 1) 59 m_currentCommand = static_cast<int32_t>(i); 60 } 61 } 62 } 63 64 if(!anyMatch) 65 { 66 if(m_currentCommand >= 0) 67 { 68 const auto c = static_cast<CommandType>(m_currentCommand); 69 70 execCommand(c, _addr, _data); 71 } 72 73 reset(); 74 } 75 else 76 { 77 ++m_currentBusCycle; 78 } 79 } 80 81 bool Am29f::eraseSector(const uint32_t _addr, const size_t _sizeInKb) const 82 { 83 if (!_sizeInKb) 84 return false; 85 86 MCLOG("Erasing Sector at " << MCHEX(_addr) << ", size " << MCHEX(1024 * _sizeInKb)); 87 88 for(size_t i = _addr; i< _addr + _sizeInKb * 1024; ++i) 89 m_buffer[i] = 0xff; 90 91 return true; 92 } 93 94 bool Am29f::eraseSector1Mbit(const uint32_t _addr) const 95 { 96 switch (_addr) 97 { 98 case 0x00000: 99 case 0x04000: 100 case 0x08000: 101 case 0x0C000: 102 case 0x10000: 103 case 0x14000: 104 case 0x18000: 105 case 0x1C000: return eraseSector(_addr, 16); 106 default: return false; 107 } 108 } 109 110 bool Am29f::eraseSector2MbitTopBoot(const uint32_t _addr) const 111 { 112 switch (_addr) 113 { 114 case 0x00000: 115 case 0x10000: 116 case 0x20000: return eraseSector(_addr, 64); 117 case 0x30000: return eraseSector(_addr, 32); 118 case 0x38000: 119 case 0x3a000: return eraseSector(_addr, 8); 120 case 0x3c000: return eraseSector(_addr, 16); 121 default: return false; 122 } 123 } 124 125 bool Am29f::eraseSector4MbitTopBoot(const uint32_t _addr) const 126 { 127 switch (_addr) 128 { 129 case 0x00000: 130 case 0x10000: 131 case 0x20000: 132 case 0x30000: 133 case 0x40000: 134 case 0x50000: 135 case 0x60000: 136 case 0x70000: return eraseSector(_addr, 64); 137 case 0x78000: 138 case 0x7a000: return eraseSector(_addr, 8); 139 case 0x7c000: return eraseSector(_addr, 16); 140 default: return false; 141 } 142 } 143 144 void Am29f::execCommand(const CommandType _command, uint32_t _addr, const uint16_t _data) const 145 { 146 switch (_command) 147 { 148 case CommandType::ChipErase: 149 assert(false); 150 break; 151 case CommandType::SectorErase: 152 { 153 if (!eraseSector(_addr)) 154 { 155 assert(false); 156 MCLOG("Unable to erase sector at " << MCHEX(_addr) << ", unable to determine sector size!"); 157 } 158 } 159 break; 160 case CommandType::Program: 161 { 162 if(_addr >= m_size) 163 return; 164 #if defined(_DEBUG) && defined(_WIN32) 165 MCLOG("Programming word at " << MCHEX(_addr) << ", value " << MCHEXN(_data, 4)); 166 #endif 167 const auto old = mc68k::memoryOps::readU16(m_buffer, _addr); 168 // "A bit cannot be programmed from a 0 back to a 1" 169 const auto v = _data & old; 170 mc68k::memoryOps::writeU16(m_buffer, _addr, v); 171 // assert(v == _data); 172 break; 173 } 174 case CommandType::Invalid: 175 default: 176 assert(false); 177 break; 178 } 179 } 180 }