You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
5.7 KiB
188 lines
5.7 KiB
/***************************************************************************
|
|
* Copyright (C) 2003-2004 Alain Gibaud <alain.gibaud@free.fr> *
|
|
* *
|
|
* 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_pic.h"
|
|
|
|
#include "common/common/misc.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
Direct::PulseEngine::PulseEngine(::Programmer::Base &base)
|
|
: _pbase(base)
|
|
{
|
|
_clockDelay = 0;
|
|
}
|
|
|
|
BitValue Direct::PulseEngine::pulseEngine(const TQString &cmd, BitValue value)
|
|
{
|
|
_pbase.log(Log::DebugLevel::Extra, TQString("pulse engine: %1").tqarg(cmd));
|
|
TQByteArray a = toAscii(cmd);
|
|
BitValue res = 0;
|
|
for (const char *ptr=a.data(); (ptr-a.data())<int(a.count()); ++ptr)
|
|
if ( !pulse(ptr, value, res) ) qFatal("pulse engine: invalid command '%c'", *ptr);
|
|
return res;
|
|
}
|
|
|
|
// Electric signals level commands:
|
|
// UPPER case means signal High - lower case means Low
|
|
// Example: "cPCcp" means "clock-low, power on, clock high, clock low, power off".
|
|
// c/C = clock
|
|
// d/D = data
|
|
// p/P = power (vdd)
|
|
// Higher level commands:
|
|
// wnnnnn = wait nnnnn microseconds (nnnnn is decimal)
|
|
// , = a shorthand for w1
|
|
// ; or space = NOP (can be used as separator - useful in debug mode)
|
|
bool Direct::PulseEngine::pulse(const char * &cmd, BitValue, BitValue &)
|
|
{
|
|
switch (*cmd) {
|
|
case ';':
|
|
case ' ':
|
|
_pbase.log(Log::DebugLevel::Max, "NOP");
|
|
break;
|
|
case 'c':
|
|
_pbase.log(Log::DebugLevel::Max, "CLOCK L");
|
|
hardware().setPin(Clock, Low);
|
|
break;
|
|
case 'C':
|
|
_pbase.log(Log::DebugLevel::Max, "CLOCK H");
|
|
hardware().setPin(Clock, High);
|
|
break;
|
|
case 'd':
|
|
_pbase.log(Log::DebugLevel::Max, "DATA L");
|
|
hardware().setPin(DataOut, Low);
|
|
break;
|
|
case 'D':
|
|
_pbase.log(Log::DebugLevel::Max, "DATA H");
|
|
hardware().setPin(DataOut, High);
|
|
break;
|
|
case 'p':
|
|
_pbase.log(Log::DebugLevel::Max, "VDD Off");
|
|
hardware().setPin(Vdd, Off);
|
|
Port::usleep(10000);
|
|
break;
|
|
case 'P':
|
|
_pbase.log(Log::DebugLevel::Max, "VDD On");
|
|
hardware().setPin(Vdd, On);
|
|
// wait 10ms for ALL devices because some programmers (or target board) have capacitors to charge
|
|
Port::usleep(10000);
|
|
break;
|
|
case 'w': {
|
|
uint n = 0;
|
|
for(; *(cmd+1) && isdigit((int)*(cmd+1)); ++cmd)
|
|
n = (n * 10) + *(cmd+1) - '0';
|
|
_pbase.log(Log::DebugLevel::Max, "WAIT " + TQString::number(n) + " micro-sec.");
|
|
Port::usleep(n);
|
|
break;
|
|
}
|
|
case ',':
|
|
_pbase.log(Log::DebugLevel::Max, "WAIT 1 micro-sec");
|
|
Port::usleep(1);
|
|
break;
|
|
default: return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
Direct::PicDeviceSpecific::PicDeviceSpecific(::Programmer::Base &base)
|
|
: ::Programmer::PicDeviceSpecific(base), PulseEngine(base)
|
|
{}
|
|
|
|
// Electric signals level commands:
|
|
// UPPER case means signal High - lower case means Low
|
|
// b/B = burn (vpp)
|
|
bool Direct::PicDeviceSpecific::pulse(const char *&cmd, BitValue value, BitValue &res)
|
|
{
|
|
switch (*cmd) {
|
|
case 'b':
|
|
log(Log::DebugLevel::Max, "VPP Off");
|
|
hardware().setPin(Vpp, Off);
|
|
Port::usleep(10); // 10us
|
|
break;
|
|
case 'B':
|
|
log(Log::DebugLevel::Max, "VPP On");
|
|
hardware().setPin(Vpp, On);
|
|
Port::usleep(100000); // 100ms
|
|
break;
|
|
default: return PulseEngine::pulse(cmd, value, res);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Direct::PicDeviceSpecific::setPowerOnVddFirst()
|
|
{
|
|
setPowerOff();
|
|
switch (hardware().type()) {
|
|
case Normal:
|
|
if ( hardware().isGroundPin(Vdd) ) { // some programmer cannot change Vdd independently
|
|
pulseEngine("B"); // charge capacitor to have high Vdd
|
|
pulseEngine("bB"); // turn off Vpp briefly, Vpp on
|
|
} else pulseEngine("PB");
|
|
break;
|
|
case EPEToolkitMK3:
|
|
pulseEngine("B"); // put MCLR at 0V
|
|
pulseEngine("bP"); // put MCLR on multiplexer and turn multiplexer to 12V
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Direct::PicDeviceSpecific::setPowerOnVppFirst()
|
|
{
|
|
setPowerOff();
|
|
pulseEngine("BP");
|
|
return true;
|
|
}
|
|
|
|
bool Direct::PicDeviceSpecific::setPowerOff()
|
|
{
|
|
pulseEngine("cdpb"); // turn off Vpp after Vdd to prevent running device
|
|
pulseEngine("w50000"); // to be on the safe size with multiple on/off
|
|
return true;
|
|
}
|
|
|
|
bool Direct::PicDeviceSpecific::setTargetPowerOn(bool on)
|
|
{
|
|
pulseEngine(on ? "P" : "p");
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Higher level commands:
|
|
// S = send data word
|
|
// R = read data word
|
|
// r = read byte
|
|
// knn = send 6 or 4 bits command nn to PIC (nn is decimal)
|
|
bool Direct::Pic8DeviceSpecific::pulse(const char *&cmd, BitValue value, BitValue &res)
|
|
{
|
|
switch (*cmd) {
|
|
case 'S':
|
|
log(Log::DebugLevel::Max, "SEND " + toHexLabel(value, 4));
|
|
send_word(value);
|
|
break;
|
|
case 'R':
|
|
log(Log::DebugLevel::Max, "Read Word");
|
|
res = get_word();
|
|
break;
|
|
case 'r':
|
|
log(Log::DebugLevel::Max, "Read Byte");
|
|
res = get_byte();
|
|
break;
|
|
case 'k': {
|
|
uint n = 0;
|
|
for(; *(cmd+1) && isdigit((int)*(cmd+1)); ++cmd)
|
|
n = (n * 10) + *(cmd+1) - '0';
|
|
log(Log::DebugLevel::Max, "SEND cmd " + TQString::number(n));
|
|
send_cmd(n);
|
|
break;
|
|
}
|
|
default: return PicDeviceSpecific::pulse(cmd, value, res);
|
|
}
|
|
return true;
|
|
}
|