summaryrefslogtreecommitdiffstats
path: root/src/progs/direct/base/direct_mem24.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/progs/direct/base/direct_mem24.cpp')
-rw-r--r--src/progs/direct/base/direct_mem24.cpp207
1 files changed, 207 insertions, 0 deletions
diff --git a/src/progs/direct/base/direct_mem24.cpp b/src/progs/direct/base/direct_mem24.cpp
new file mode 100644
index 0000000..a719add
--- /dev/null
+++ b/src/progs/direct/base/direct_mem24.cpp
@@ -0,0 +1,207 @@
+/***************************************************************************
+ * Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#include "direct_mem24.h"
+
+#include <qdatetime.h>
+
+#include "common/global/global.h"
+#include "common/common/misc.h"
+
+Direct::Mem24DeviceSpecific::Mem24DeviceSpecific(::Programmer::Base &base)
+ : ::Programmer::Mem24DeviceSpecific(base)
+{}
+
+bool Direct::Mem24DeviceSpecific::setPowerOn()
+{
+ hardware().setPin(Clock, Low);
+ hardware().setPin(DataOut, Low);
+ hardware().setPin(Vpp, Off);
+ if ( hardware().isGroundPin(Vdd) ) {
+ hardware().setPin(Clock, High);
+ Port::usleep(500000);
+ } else {
+ hardware().setPin(Vdd, On);
+ Port::usleep(10000);
+ }
+ return true;
+}
+
+bool Direct::Mem24DeviceSpecific::setPowerOff()
+{
+ hardware().setPin(Clock, Low);
+ hardware().setPin(DataOut, Low);
+ hardware().setPin(Vpp, Off);
+ hardware().setPin(Vdd, Off);
+ Port::usleep(10000);
+ return true;
+}
+
+bool Direct::Mem24DeviceSpecific::verifyPresence()
+{
+ if ( !start() ) return false;
+ bool acked;
+ if ( !writeByte(controlByte(0x0, Write), acked) ) return false;
+ if ( !acked ) {
+ log(Log::LineType::Error, i18n("Could not detect EEPROM"));
+ return false;
+ }
+ log(Log::LineType::Information, i18n("EEPROM detected"));
+ return stop();
+}
+
+uint Direct::Mem24DeviceSpecific::controlByte(uint address, Operation operation) const
+{
+ uint cbyte = (operation==Write ? 0xA0 : 0xA1);
+ uint bsize = device().nbBytes() / device().nbBlocks();
+ uint block = address / bsize;
+ uint nbb = nbBits(device().nbBlocks()-1);
+ for (uint i=0; i<nbb; i++)
+ if ( block & (1<<i) ) cbyte |= 1 << (4-nbb+i);
+ return cbyte;
+}
+
+bool Direct::Mem24DeviceSpecific::setAddress(uint address)
+{
+ log(Log::DebugLevel::Extra, QString("set address %1").arg(toHexLabel(address, nbChars(NumberBase::Hex, address))));
+ if ( !start() ) return false;
+ uint bsize = device().nbBytes() / device().nbBlocks();
+ uint block = address / bsize;
+ log(Log::DebugLevel::Extra, QString(" in block #%1/%2").arg(block).arg(device().nbBlocks()));
+ uint cbyte = controlByte(address, Write);
+ log(Log::DebugLevel::Max, QString(" control byte is %1").arg(toHexLabel(cbyte, 2)));
+ if ( !writeByteAck(cbyte) ) return false;
+ uint nb = nbBytes(bsize-1);
+ for (int i=nb-1; i>=0; i--) {
+ uint add = (address >> 8*i) & 0xFF;
+ log(Log::DebugLevel::Max, QString(" byte #%1: %2").arg(i).arg(toHexLabel(add, 2)));
+ if ( !writeByteAck(add) ) return false;
+ }
+ return true;
+}
+
+bool Direct::Mem24DeviceSpecific::doRead(Device::Array &data, const ::Programmer::VerifyData *vdata)
+{
+ // sequential read: all device memory
+ if ( !setAddress(0x0) ) return false;
+ if ( !start() ) return false;
+ if ( !writeByteAck(controlByte(0x0, Read)) ) return false;
+ data.resize(device().nbBytes());
+ for (uint i=0; i<data.count()-1; i++) data[i] = readByte(Low);
+ data[data.count()-1] = readByte(High);
+ if (vdata) {
+ for (uint i=0; i<data.count(); i++)
+ if ( !verifyByte(i, data[i], *vdata) ) return false;
+ }
+ return stop();
+}
+
+bool Direct::Mem24DeviceSpecific::doWrite(const Device::Array &data)
+{
+ QTime time;
+ // page by page (page_size==1: byte by byte)
+ uint nbPages = device().nbBytes() / device().nbBytesPage();
+ for (uint i=0; i<nbPages; i++) {
+ log(Log::DebugLevel::Extra, QString("write page #%1/%2").arg(i).arg(nbPages));
+ uint address = i * device().nbBytesPage();
+ // write bytes
+ if ( !setAddress(address) ) return false;
+ for (uint k=0; k<device().nbBytesPage(); k++)
+ if ( !writeByteAck(data[address+k]) ) return false;
+ if ( !stop() ) return false;
+ // poll
+ time.start();
+ for (;;) {
+ if ( !start() ) return false;
+ bool acked;
+ if ( !writeByte(controlByte(address, Write), acked) ) return false;
+ if (acked) break;
+ if ( time.elapsed()>200 ) { // 200 ms timeout
+ log(Log::LineType::Error, i18n("Timeout writing at address %1").arg(toHexLabel(address, nbChars(device().nbBytes()))));
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+void Direct::Mem24DeviceSpecific::set(State clock, State data)
+{
+ hardware().setPin(Clock, clock);
+ hardware().setPin(DataOut, data);
+ Port::usleep(5); // #### needed ?
+}
+
+void Direct::Mem24DeviceSpecific::setData(State data)
+{
+ set(Low, data);
+ set(High, data);
+ set(Low, data);
+}
+
+BitValue Direct::Mem24DeviceSpecific::readByte(State ack)
+{
+ hardware().setRead();
+ set(Low, High);
+ BitValue b = 0;
+ for (uint i=0; i<8; i++) {
+ set(High, High);
+ b <<= 1;
+ if ( hardware().readBit() ) b |= 0x1;
+ set(Low, High);
+ }
+ hardware().setWrite();
+ setData(ack);
+ return b;
+}
+
+bool Direct::Mem24DeviceSpecific::writeByteAck(BitValue value)
+{
+ bool acked;
+ if ( !writeByte(value, acked) ) return false;
+ if (!acked) {
+ log(Log::LineType::Error, i18n("Acknowledge bit incorrect"));
+ return false;
+ }
+ return true;
+}
+
+bool Direct::Mem24DeviceSpecific::writeByte(BitValue value, bool &acked)
+{
+ Q_ASSERT( value<=0xFF );
+ hardware().setWrite();
+ set(Low, Low);
+ for (int i=7; i>=0; i--) setData(value.bit(i) ? High : Low);
+ hardware().setRead();
+ set(Low, High);
+ set(High, High);
+ acked = !hardware().readBit();
+ hardware().setWrite();
+ set(Low, High);
+ return true;
+}
+
+bool Direct::Mem24DeviceSpecific::start()
+{
+ hardware().setWrite();
+ set(Low, High);
+ set(High, High);
+ set(High, Low);
+ set(Low, Low);
+ return true;
+}
+
+bool Direct::Mem24DeviceSpecific::stop()
+{
+ hardware().setWrite();
+ set(Low, Low);
+ set(High, Low);
+ set(High, High);
+ set(Low, High);
+ return true;
+}