Advertisement
justhrun

Arduino_RescueAVR

Jul 11th, 2014
230
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 40.05 KB | None | 0 0
  1. // -*- mode: c++; tab-width: 4; indent-tabs-mode: nil -*-
  2.  
  3. //  Title:        RescueAVR
  4.  
  5. #define VERSION  "2.1"
  6.  
  7. /*
  8.   based on Jeff Keyzer's HVRescue_Shield and manekinen's Fusebit Doctor.
  9.  
  10.   It uses the hardware dsigned by manekinen but the software is completely
  11.   new, using ideas und snippets from  Jeff Keyzer's sketch HVRescue_Shield.
  12.   In addition, the program can also be run on a native Arduino, provided
  13.   12V are supplied and the target chip is connected to the right Arduino
  14.   pins.
  15.  
  16.   The program decides on its own whether it runs in Arduino or
  17.   Fusebit-Doctor mode. This decision is based on the CPU frequency.
  18.   With F_CPU <= 8000000, it is assumed that the software runs on the Fusebit-Doctor
  19.   board. Otherwise it must be an Arduino board. This can be overriden with a define
  20.   below.
  21.  
  22.   Copyright 2013 by Bernhard Nebel and parts are copyrighted by Jeff Keyzer.
  23.  
  24.   This program is free software: you can redistribute it and/or modify
  25.   it under the terms of the GNU General Public License as published by
  26.   the Free Software Foundation, either version 3 of the License, or
  27.   (at your option) any later version.
  28.  
  29.   This program is distributed in the hope that it will be useful,
  30.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  31.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  32.   GNU General Public License for more details.
  33.  
  34.   You should have received a copy of the GNU General Public License
  35.   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  36. */
  37.  
  38. /* Uncomment one of the following two lines, if you do not want to
  39.    leave the decision on which board we are executed to the
  40.    the CPU frequency, i.e. F_CPU <= 8000000 -> FBD_MODE, otherwise ARDUNIO_MODE
  41. */
  42. // #define FBD_MODE
  43. // #define ARDUINO_MODE
  44.  
  45. #if !defined(FBD_MODE) && !defined(ARDUINO_MODE)
  46. #if F_CPU <= 8000000L
  47.    #define FBD_MODE
  48. #endif
  49. #endif
  50.  
  51. #include <avr/pgmspace.h>
  52.  
  53. // communication speed
  54. #define  BAUD         19200    // Serial port rate at which to talk to PC
  55.  
  56.  
  57. // The names of all MCUs known to us
  58. char at90s2313[] PROGMEM = "AT90S2313";
  59. char at90s2333[] PROGMEM = "AT90S2333";
  60. char at90s2343[] PROGMEM = "AT90S2343";
  61. char at90s4433[] PROGMEM = "AT90S4433";
  62. char at90s4434[] PROGMEM = "AT90S4434";
  63. char at90s8515[] PROGMEM = "AT90S8515";
  64. char at90s8535[] PROGMEM = "AT90S8535";
  65. char attiny11[] PROGMEM = "ATtiny11";
  66. char attiny12[] PROGMEM = "ATtiny12";
  67. char attiny13[] PROGMEM = "ATtiny13";
  68. char attiny15[] PROGMEM = "ATtiny15";
  69. char attiny2313[] PROGMEM = "ATtiny2313";
  70. char attiny4313[] PROGMEM = "ATtiny4313";
  71. char attiny24[] PROGMEM = "ATtiny24";
  72. char attiny44[] PROGMEM = "ATtiny44";
  73. char attiny84[] PROGMEM = "ATtiny84";
  74. char attiny25[] PROGMEM = "ATtiny25";
  75. char attiny45[] PROGMEM = "ATtiny45";
  76. char attiny85[] PROGMEM = "ATtiny85";
  77. char attiny26[] PROGMEM = "ATtiny26";
  78. char attiny261[] PROGMEM = "ATtiny261";
  79. char attiny461[] PROGMEM = "ATtiny461";
  80. char attiny861[] PROGMEM = "ATtiny861";
  81. char attiny28[] PROGMEM = "ATtiny28";
  82. char attiny48[] PROGMEM = "ATtiny48";
  83. char attiny88[] PROGMEM = "ATtiny88";
  84. char atmega8515[] PROGMEM = "ATmega8515";
  85. char atmega8535[] PROGMEM = "ATmega8535";
  86. char atmega8[] PROGMEM = "ATmega8";
  87. char atmega8hva[] PROGMEM = "ATmega8HVA";
  88. char atmega16[] PROGMEM = "ATmega16";
  89. char atmega16hva[] PROGMEM = "ATmega16HVA";
  90. char atmega16hvb[] PROGMEM = "ATmega16HVB";
  91. char atmega32[] PROGMEM = "ATmega32";
  92. char atmega32c1[] PROGMEM = "ATmega32C1";
  93. char atmega32hvb[] PROGMEM = "ATmega32HVB";
  94. char atmega64[] PROGMEM = "ATmega64";
  95. char atmega64c1[] PROGMEM = "ATmega64c1";
  96. char atmega64hev2[] PROGMEM = "ATmega64HEV2";
  97. char atmega64m1[] PROGMEM = "ATmega64m1";
  98. char atmega128[] PROGMEM = "ATmega128";
  99. char atmega128rfa1[] PROGMEM = "ATmega128RFA1";
  100. char atmega162[] PROGMEM = "ATmega162";
  101. char atmega48[] PROGMEM = "ATmega48";
  102. char atmega48p[] PROGMEM = "ATmega48P";
  103. char atmega88[] PROGMEM = "ATmega88";
  104. char atmega88p[] PROGMEM = "ATmega88P";
  105. char atmega168[] PROGMEM = "ATmega168";
  106. char atmega168p[] PROGMEM = "ATmega168P";
  107. char atmega328[] PROGMEM = "ATmega328";
  108. char atmega164a[] PROGMEM = "ATmega164A";
  109. char atmega164p[] PROGMEM = "ATmega164P";
  110. char atmega324a[] PROGMEM = "ATmega324A";
  111. char atmega324p[] PROGMEM = "ATmega324P";
  112. char atmega324pa[] PROGMEM = "ATmega324PA";
  113. char atmega644[] PROGMEM = "ATmega644";
  114. char atmega644p[] PROGMEM = "ATmega644P";
  115. char atmega644rfr2[] PROGMEM = "ATmega644RFR2";
  116. char atmega1284[] PROGMEM = "ATmega1284";
  117. char atmega1284p[] PROGMEM = "ATmega1284P";
  118. char atmega1284rfr2[] PROGMEM = "ATmega1284RFR2";
  119. char atmega328p[] PROGMEM = "ATmega328P";
  120.  
  121. // table with signatures
  122. // 1st word signature (w/o 1E), 2nd word: MSB number of fuses (or 0 if we do not know),
  123. // 2nd word LSB: low fuse, 3rd word MSB: high fuse, 3rd word LSB: extended fuse,
  124. // 4th word string address.
  125.  
  126. #define MCU_NUM 62
  127. uint16_t mcu_types[MCU_NUM][4] PROGMEM =
  128.   {
  129.     { 0x9101, 0x01FF, 0x0000, (uint16_t)at90s2313 },
  130.     { 0x9105, 0x01FF, 0x0000, (uint16_t)at90s2333 },
  131.     { 0x9103, 0x01FF, 0x0000, (uint16_t)at90s2343 },
  132.     { 0x9203, 0x01FF, 0x0000, (uint16_t)at90s4433 },
  133.     { 0x9202, 0x01FF, 0x0000, (uint16_t)at90s4434 },
  134.     { 0x9301, 0x01FF, 0x0000, (uint16_t)at90s8515 },
  135.     { 0x9303, 0x01FF, 0x0000, (uint16_t)at90s8535 },
  136.     { 0x9004, 0x01FF, 0x0000, (uint16_t)attiny11 },
  137.     { 0x9005, 0x01FF, 0x0000, (uint16_t)attiny12 },
  138.     { 0x9007, 0x026A, 0xFF00, (uint16_t)attiny13 },
  139.     { 0x9006, 0x01FF, 0x0000, (uint16_t)attiny15 },
  140.     { 0x910A, 0x0364, 0xDFFF, (uint16_t)attiny2313 },
  141.     { 0x920D, 0x0364, 0xDFFF, (uint16_t)attiny4313 },
  142.     { 0x910B, 0x0362, 0xDFFF, (uint16_t)attiny24 },
  143.     { 0x9207, 0x0362, 0xDFFF, (uint16_t)attiny44 },
  144.     { 0x930C, 0x0362, 0xDFFF, (uint16_t)attiny84 },
  145.     { 0x9108, 0x0362, 0xDFFF, (uint16_t)attiny25 },
  146.     { 0x9206, 0x0362, 0xDFFF, (uint16_t)attiny45 },
  147.     { 0x930B, 0x0362, 0xDFFF, (uint16_t)attiny85 },
  148.     { 0x9109, 0x0241, 0xF700, (uint16_t)attiny26 },
  149.     { 0x910C, 0x0362, 0xDFFF, (uint16_t)attiny261 },
  150.     { 0x9208, 0x0362, 0xDFFF, (uint16_t)attiny461 },
  151.     { 0x930D, 0x0362, 0xDFFF, (uint16_t)attiny861 },
  152.     { 0x9107, 0x01FF, 0x0000, (uint16_t)attiny28 },
  153.     { 0x9209, 0x036E, 0xDFFF, (uint16_t)attiny48 },
  154.     { 0x9311, 0x036E, 0xDFFF, (uint16_t)attiny88 },
  155.     { 0x9306, 0x02C1, 0xD900, (uint16_t)atmega8515 },
  156.     { 0x9308, 0x02C1, 0xD900, (uint16_t)atmega8535 },
  157.     { 0x9307, 0x02E1, 0xD900, (uint16_t)atmega8 },
  158.     { 0x9310, 0x01DF, 0x0000, (uint16_t)atmega8hva },
  159.     { 0x9403, 0x02E1, 0x9900, (uint16_t)atmega16 },
  160.     { 0x940c, 0x01DF, 0x0000, (uint16_t)atmega16hva },
  161.     { 0x940d, 0x02DE, 0xE900, (uint16_t)atmega16hvb },
  162.     { 0x9502, 0x02E1, 0x9900, (uint16_t)atmega32 },
  163.     { 0x9586, 0x0341, 0xD9F9, (uint16_t)atmega32c1 },
  164.     { 0x9510, 0x02DE, 0xE900, (uint16_t)atmega32hvb },
  165.     { 0x9602, 0x03C1, 0x99FF, (uint16_t)atmega64 },
  166.     { 0x9686, 0x0341, 0xD9F9, (uint16_t)atmega64c1 },
  167.     { 0x9610, 0x02D6, 0xF900, (uint16_t)atmega64hev2 },
  168.     { 0x9684, 0x0341, 0xD9F9, (uint16_t)atmega64m1 },
  169.     { 0x9702, 0x03C1, 0x99FD, (uint16_t)atmega128 },
  170.     { 0x9701, 0x03C1, 0x99FD, (uint16_t)atmega128rfa1 },
  171.     { 0x9404, 0x0362, 0x99FF, (uint16_t)atmega162 },
  172.     { 0x9205, 0x0362, 0xDFFF, (uint16_t)atmega48 },
  173.     { 0x920A, 0x0362, 0xDFFF, (uint16_t)atmega48p },
  174.     { 0x930A, 0x0362, 0xDFFF, (uint16_t)atmega88 },
  175.     { 0x930F, 0x0362, 0xDFF9, (uint16_t)atmega88p },
  176.     { 0x9406, 0x0362, 0xDFF9, (uint16_t)atmega168 },
  177.     { 0x940B, 0x0362, 0xDFFF, (uint16_t)atmega168p },
  178.     { 0x9514, 0x0362, 0xD9FF, (uint16_t)atmega328 },
  179.     { 0x940F, 0x0342, 0x99FF, (uint16_t)atmega164a },
  180.     { 0x940A, 0x0342, 0x99FF, (uint16_t)atmega164p },
  181.     { 0x9515, 0x0342, 0x99FF, (uint16_t)atmega324a },
  182.     { 0x9508, 0x0342, 0x99FF, (uint16_t)atmega324p },
  183.     { 0x9511, 0x0342, 0x99FF, (uint16_t)atmega324pa },
  184.     { 0x9609, 0x0362, 0x99FF, (uint16_t)atmega644 },
  185.     { 0x960A, 0x0362, 0x99FF, (uint16_t)atmega644p },
  186.     { 0x9602, 0x0000, 0x0000, (uint16_t)atmega644rfr2 },
  187.     { 0x9706, 0x0342, 0x99FF, (uint16_t)atmega1284 },
  188.     { 0x9705, 0x0342, 0x99FF, (uint16_t)atmega1284p },
  189.     { 0x9703, 0x0000, 0x0000, (uint16_t)atmega1284rfr2 },
  190.     { 0x950F, 0x0362, 0xD9FF, (uint16_t)atmega328p },
  191.   };
  192.  
  193.  
  194. #ifdef FBD_MODE
  195. /* pin assignment for the FBD board */
  196. /************************************/
  197. #define  VCC      5
  198. #define  RDY     14
  199. #define  OE       2
  200. #define  WR       4
  201. #define  BS1     15
  202. #define  BS2      6
  203. #define  XA0     16
  204. #define  ORIGXA1 17
  205. #define  RST      7
  206. #define  XTAL1    3
  207. #define  ORIGPAGEL 19
  208. #define  ECJUMPER 18
  209. // HVSP pins
  210. #define  SCI    RDY // note that the direction must be changed!
  211. #define  SDO    BS1
  212. #define  SII    XA0
  213. #define  SDI    ORIGXA1
  214. // special values to control the VCC line
  215. #define  VCCOFF   HIGH
  216. #define  VCCON    LOW
  217. #else
  218. /* pin assignment for Arduino board */
  219. /************************************/
  220. #define  VCC       12
  221. #define  RST       13
  222.  
  223. #define  RDY       A4
  224. #define  OE        A3
  225. #define  WR        A2
  226. #define  BS1       A1
  227. #define  BS2       A5
  228. #define  XA0       10
  229. #define  ORIGXA1   11
  230. #define  XTAL1     A0
  231. #define  ORIGPAGEL BS1 // is actually not used and tied to GND
  232. // HVSP pins
  233. #define  SCI       A5
  234. #define  SDO       A2
  235. #define  SII       A1
  236. #define  SDI       A0
  237. // special values to control the VCC line
  238. #define  VCCOFF    LOW
  239. #define  VCCON     HIGH
  240.  
  241. #endif
  242.  
  243. // These pin assignments change depending on which chip is being programmed
  244. byte PAGEL = ORIGPAGEL; // ATtiny2313: PAGEL = BS1
  245. byte XA1 = ORIGXA1; // ATtiny2313: XA1 = BS2
  246.  
  247.  
  248. // Serial instructions for HVSP mode
  249. // Based on the ATtiny85 datasheet Table 20-16 pg. 163-165.
  250. // These instructions don't contain the necessary zero padding, which is added later.
  251.  
  252. // LFUSE
  253. #define HVSP_READ_LFUSE_DATA     B00000100  // For the commands we are interested in
  254. #define HVSP_READ_LFUSE_INSTR1   B01001100  // only the 1st instruction contains a fixed data packet.
  255. #define HVSP_READ_LFUSE_INSTR2   B01101000  // Instructions 2-3 have data = all zeros.
  256. #define HVSP_READ_LFUSE_INSTR3   B01101100
  257.  
  258. #define HVSP_WRITE_LFUSE_DATA    B01000000  // For the write instructions, the data contents
  259. #define HVSP_WRITE_LFUSE_INSTR1  B01001100  // for instruction 2 are the desired fuse bits.
  260. #define HVSP_WRITE_LFUSE_INSTR2  B00101100  // Instructions 3-4 have data = all zeros.
  261. #define HVSP_WRITE_LFUSE_INSTR3  B01100100
  262. #define HVSP_WRITE_LFUSE_INSTR4  B01101100
  263.  
  264. // HFUSE
  265. #define HVSP_READ_HFUSE_DATA     B00000100
  266. #define HVSP_READ_HFUSE_INSTR1   B01001100
  267. #define HVSP_READ_HFUSE_INSTR2   B01111010
  268. #define HVSP_READ_HFUSE_INSTR3   B01111110
  269.  
  270. #define HVSP_WRITE_HFUSE_DATA    B01000000
  271. #define HVSP_WRITE_HFUSE_INSTR1  B01001100
  272. #define HVSP_WRITE_HFUSE_INSTR2  B00101100
  273. #define HVSP_WRITE_HFUSE_INSTR3  B01110100
  274. #define HVSP_WRITE_HFUSE_INSTR4  B01111100
  275.  
  276. // EFUSE
  277. // Note: not all ATtiny's have an EFUSE
  278. #define HVSP_READ_EFUSE_DATA     B00000100  
  279. #define HVSP_READ_EFUSE_INSTR1   B01001100
  280. #define HVSP_READ_EFUSE_INSTR2   B01101010
  281. #define HVSP_READ_EFUSE_INSTR3   B01101110
  282.  
  283. #define HVSP_WRITE_EFUSE_DATA    B01000000
  284. #define HVSP_WRITE_EFUSE_INSTR1  B01001100
  285. #define HVSP_WRITE_EFUSE_INSTR2  B00101100
  286. #define HVSP_WRITE_EFUSE_INSTR3  B01100110
  287. #define HVSP_WRITE_EFUSE_INSTR4  B01101110
  288.  
  289. // LOCK
  290. #define HVSP_READ_LOCK_DATA      B00000100
  291. #define HVSP_READ_LOCK_INSTR1    B01001100
  292. #define HVSP_READ_LOCK_INSTR2    B01111000
  293. #define HVSP_READ_LOCK_INSTR3    B01101100
  294.  
  295. #define HVSP_WRITE_LOCK_DATA     B00100000
  296. #define HVSP_WRITE_LOCK_INSTR1   B01001100
  297. #define HVSP_WRITE_LOCK_INSTR2   B00101100
  298. #define HVSP_WRITE_LOCK_INSTR3   B01100100
  299. #define HVSP_WRITE_LOCK_INSTR4   B01101100
  300.  
  301. // Signature read
  302. #define HVSP_READ_SIG_DATA       B00001000
  303. #define HVSP_READ_SIG_INSTR1     B01001100
  304. #define HVSP_READ_SIG_INSTR2     B00001100
  305. #define HVSP_READ_SIG_INSTR3     B01101000
  306. #define HVSP_READ_SIG_INSTR4     B01101100
  307.  
  308. // OSCCAL read
  309. #define HVSP_READ_OSC_DATA       B00001000
  310. #define HVSP_READ_OSC_INSTR1     B01001100
  311. #define HVSP_READ_OSC_INSTR2     B00001100
  312. #define HVSP_READ_OSC_INSTR3     B01111000
  313. #define HVSP_READ_OSC_INSTR4     B01111100
  314.  
  315. // Erase chip
  316. #define HVSP_ERASE_CHIP_DATA     B10000000
  317. #define HVSP_ERASE_CHIP_INSTR1   B01001100
  318. #define HVSP_ERASE_CHIP_INSTR2   B01100100
  319. #define HVSP_ERASE_CHIP_INSTR3   B01101100
  320.  
  321.  
  322. // Internal definitions
  323. enum { ATMEGA, TINY2313, HVSP };
  324. enum { LFUSE_SEL, HFUSE_SEL, EFUSE_SEL, LOCK_SEL };
  325. enum { RED, GREEN };
  326.  
  327. // Global variables
  328. byte mcu_mode;  // programming mode
  329. byte mcu_fuses = 0; // number of fuses for the actual chip
  330. boolean interactive_mode = true; // interaction over terminal
  331. int mcu_index = 0; // index into mcu_types array - see above
  332. unsigned long mcu_signature = 0; // signature as read from chip
  333. boolean ec_allowed = true; // whether chip erase is allowed - only relevant for FBD
  334.  
  335.  
  336. void setup() { // run once, when the sketch starts
  337.   char modec = ' ';
  338.  
  339.   // Set up control lines for HV parallel programming
  340.  
  341.   setData(0);
  342.   setDataDirection(INPUT);
  343.  
  344. #ifdef FBD_MODE
  345.   pinMode(ECJUMPER, INPUT_PULLUP); // the jumper that allows chip erase
  346. #endif
  347.   pinMode(VCC, OUTPUT);
  348.   pinMode(RDY, INPUT);
  349.   pinMode(OE, OUTPUT);
  350.   pinMode(WR, OUTPUT);
  351.   pinMode(BS1, OUTPUT);
  352.   pinMode(XA0, OUTPUT);
  353.   pinMode(XA1, OUTPUT);
  354.   pinMode(PAGEL, OUTPUT);
  355.   pinMode(RST, OUTPUT);  // 12V Reset signal
  356.   pinMode(BS2, OUTPUT);
  357.   pinMode(XTAL1, OUTPUT);
  358.  
  359. #ifdef FBD_MODE
  360.   if (digitalRead(0) == LOW)
  361.   interactive_mode = false; // no RS232 connection!
  362. #endif
  363.  
  364.   // Initialize output pins as needed
  365.   digitalWrite(RST, LOW);  // Turn off 12V
  366.  
  367.   digitalWrite(VCC, VCCOFF); // Turn off VCC
  368.  
  369.   Serial.begin(BAUD);  // Open serial port
  370.   Serial.println();
  371.   Serial.println();
  372.   Serial.print(F("RescueAVR Version "));
  373.   Serial.print(VERSION);
  374.   if (interactive_mode) Serial.print(F(" / interactive, "));
  375.   else Serial.print(F(" / non-interactive, "));
  376. #ifdef FBD_MODE
  377.   Serial.println(F("running on Fusebit-Doctor Board"));
  378. #else
  379.   Serial.println(F("running on Arduino"));
  380. #endif
  381.   Serial.println();
  382.  
  383.   for (mcu_mode = ATMEGA; mcu_mode <= HVSP; mcu_mode++) {
  384.     enterHVProgMode(mcu_mode);
  385.     mcu_signature = readSig(mcu_mode);
  386.     leaveHVProgMode();
  387.     // Serial.print(F("DEBUG: SIG="));
  388.     // Serial.println(mcu_signature,HEX);
  389.     if ((mcu_signature>>16) == 0x1E) break;
  390.   }
  391.   if (mcu_mode > HVSP) {
  392.     Serial.println(F("No chip found!"));
  393. #ifndef FBD_MODE
  394.     Serial.println(F("Check wiring and try again."));
  395.     Serial.println();
  396.     while (true) ;
  397. #endif
  398.     Serial.println(F("Insert chip and reset or give details."));
  399.     if (!interactive_mode) {
  400.       showLed(true,false,3000); // 3 secs of red
  401.       while (true) { };
  402.     }
  403.     while (Serial.available()) Serial.read();
  404.     while (true) {
  405.       Serial.println();
  406.       Serial.println(F("Choose from:"));
  407.       Serial.println(F("  P - HVPP"));
  408.       Serial.println(F("  T - HVPP for Tiny"));
  409.       Serial.println(F("  S - HVSP"));
  410.       Serial.println(F("  X - exit"));
  411.       Serial.print(F("Choice: "));
  412.       while (!Serial.available())  { };
  413.       modec = toupper(Serial.read());
  414.       Serial.println(modec);
  415.       while (Serial.available()) Serial.read();
  416.       if (modec == 'P' || modec == 'T' || modec == 'S' || modec == 'X') break;
  417.       Serial.print("'");
  418.       Serial.print(modec);
  419.       Serial.println(F("' is not valid choice."));
  420.     }
  421.     switch (modec) {
  422.     case 'P': mcu_mode = ATMEGA; break;
  423.     case 'T': mcu_mode = TINY2313; break;
  424.     case 'S': mcu_mode = HVSP; break;
  425.     default: while (true) { };
  426.     }
  427.   }
  428.   Serial.print(F("Signature: "));
  429.   Serial.println(mcu_signature,HEX);
  430.   mcu_index = searchMCU(mcu_signature);
  431.   Serial.print(F("MCU name:  "));
  432.   if (mcu_index >= 0) {
  433.     if ((pgm_read_word(&(mcu_types[mcu_index][1]))>>8) == false) {
  434.       // unfortunately, we do not have enough info about this chip
  435.       printMCUName(mcu_index);
  436.       Serial.print(F(" / "));
  437.       if (!interactive_mode) {
  438.         showLed(false,true,1000);
  439.       }
  440.       mcu_index = -1;
  441.     }
  442.   }
  443.   if (mcu_index < 0 ) {
  444.     Serial.println(F("Unknown"));
  445.     if (!interactive_mode) {
  446.       showLed(true,false,3000); // 3 secs of red
  447.       while (true) { };
  448.     } else {
  449.       mcu_fuses = 0;
  450.       while (Serial.available()) Serial.read();
  451.       while (mcu_fuses < 1 || mcu_fuses > 3) {
  452.         Serial.print(F("# of fuse bytes (1-3): "));
  453.         while (!Serial.available())  { };
  454.         mcu_fuses = Serial.read();
  455.         Serial.println((char)mcu_fuses);
  456.         while (Serial.available()) Serial.read();
  457.         mcu_fuses = mcu_fuses - '0';
  458.       }
  459.     }
  460.   } else {
  461.     printMCUName(mcu_index);
  462.     Serial.println();
  463.     mcu_fuses = (pgm_read_word(&(mcu_types[mcu_index][1]))>>8);
  464.     if (!interactive_mode) showLed(false,true,3000); // 3 secs of green
  465.   }
  466. }
  467.  
  468. void loop() {  // run over and over again
  469.  
  470.   byte hfuse, lfuse, efuse, lock, osccal;  // fuse and lock values
  471.   byte dhfuse, dlfuse, defuse;  // default values
  472.   char action = ' ';
  473.  
  474.   if (mcu_index >= 0) {
  475.     dlfuse = pgm_read_word(&(mcu_types[mcu_index][1]))&0xFF;
  476.     dhfuse = pgm_read_word(&(mcu_types[mcu_index][2]))>>8;
  477.     defuse = pgm_read_word(&(mcu_types[mcu_index][2]))&0xFF;
  478.   }
  479.  
  480.   enterHVProgMode(mcu_mode);
  481.  
  482.   lfuse = readFuse(mcu_mode,LFUSE_SEL);
  483.   if (mcu_fuses > 1) hfuse = readFuse(mcu_mode,HFUSE_SEL);
  484.   if (mcu_fuses > 2) efuse = readFuse(mcu_mode,EFUSE_SEL);
  485.   lock = readFuse(mcu_mode,LOCK_SEL);
  486.   osccal = readOSCCAL(mcu_mode);
  487.   leaveHVProgMode();
  488.  
  489.   printFuses("Current ",mcu_fuses,lfuse,hfuse,efuse);
  490.   if (mcu_index >= 0) printFuses("Default ",mcu_fuses,dlfuse,dhfuse,defuse);
  491.  
  492.   printLock(lock);
  493.   printOSCCAL(osccal);
  494.  
  495.  
  496.   if (interactive_mode) {
  497.     while (true) {
  498.       while (Serial.available()) Serial.read();
  499.       Serial.println();
  500.       Serial.println(F("Choose:"));
  501.       if (mcu_index >= 0) Serial.println(F("  R - Try to resurrect chip by all means"));
  502.       Serial.println(F("  E - Erase chip"));
  503.       if (mcu_index >= 0) Serial.println(F("  D - Burn default fuse values"));
  504.       Serial.println(F("  L - Change low fuse"));
  505.       if (mcu_fuses > 1) Serial.println(F("  H - Change high fuse"));
  506.       if (mcu_fuses > 2) Serial.println(F("  X - Change extended fuse"));
  507.       Serial.println(F("  K - Change lock byte"));
  508.       Serial.print(F("Action: "));
  509.      
  510.       while (!Serial.available()) { };
  511.       action = toupper(Serial.read());
  512.       Serial.println(action);
  513.      
  514.       if (action == 'E' || action == 'D' || action == 'L' ||
  515.           action == 'H' || action == 'X' || action == 'K' || action == 'R') break;
  516.       if (action >= ' ') {
  517.         Serial.print("'");
  518.         Serial.print(action);
  519.         Serial.println("' is not a valid command char.");
  520.       }
  521.     }
  522.  
  523.     enterHVProgMode(mcu_mode);
  524.     switch (action) {
  525.     case 'R':
  526.       if (mcu_index >= 0) resurrection(dlfuse, dhfuse, defuse);
  527.       break;
  528.     case 'E':
  529. #ifdef FBD_MODE
  530.       ec_allowed = (digitalRead(ECJUMPER) == LOW);
  531. #endif
  532.       if (ec_allowed) {
  533.         Serial.print(F("\nErasing chip ..."));
  534.         eraseChip(mcu_mode);
  535.         verifyOneByte(LOCK_SEL, 0xFF, "erasing chip");
  536.       }
  537.       else Serial.println(F("'Erase chip' is not allowed"));
  538.       break;
  539.     case 'D':
  540.       if (mcu_index >= 0) {
  541.         Serial.print(F("\nSetting fuses ... "));
  542.         burnFuse(mcu_mode, dlfuse, LFUSE_SEL);
  543.         if (mcu_fuses > 1) burnFuse(mcu_mode, dhfuse, HFUSE_SEL);
  544.         if (mcu_fuses > 2) burnFuse(mcu_mode, defuse, EFUSE_SEL);
  545.         showLed(true,true,600);
  546.         Serial.println(F("done"));
  547.         delay(100);
  548.         Serial.print(F("Verifying ... "));
  549.         lfuse = readFuse(mcu_mode,LFUSE_SEL);
  550.         if (mcu_fuses > 1) hfuse = readFuse(mcu_mode,HFUSE_SEL);
  551.         if (mcu_fuses > 2) efuse = readFuse(mcu_mode,EFUSE_SEL);
  552.         showLed(true,true,600);
  553.         if (verifyFuses(mcu_fuses,
  554.                         0xFF,0xFF,
  555.                         lfuse,dlfuse,
  556.                         hfuse,dhfuse,
  557.                         efuse,defuse)) {
  558.           Serial.println(F("done: Sucessfully set all fuses to default values"));
  559.         } else {
  560.           Serial.println(F("done: FAILED TO SET FUSES\x07"));
  561.         }
  562.       }
  563.       break;
  564.     case 'L': setAndVerifyOneByte(LFUSE_SEL, "setting low fuse");
  565.       break;
  566.     case 'H':
  567.       if (mcu_fuses > 1) {
  568.         setAndVerifyOneByte(HFUSE_SEL, "setting high fuse");
  569.       }
  570.       break;
  571.     case 'X':
  572.       if (mcu_fuses > 2) {
  573.         setAndVerifyOneByte(EFUSE_SEL, "setting extended fuse");
  574.       }
  575.       break;
  576.     case 'K':
  577.       setAndVerifyOneByte(LOCK_SEL, "setting lock byte");
  578.       break;
  579.     }
  580.     Serial.println();
  581.     leaveHVProgMode();
  582.   } else { // non-interactive mode
  583.     resurrection(dlfuse, dhfuse, defuse);
  584.     Serial.println(F("Bye, bye ..."));
  585.     while (true) { };
  586.   }
  587. }
  588.  
  589. void resurrection(byte dlf, byte dhf, byte def) {
  590.   byte lf, hf, ef, lk;
  591.  
  592.   Serial.println(F("Start HV programming mode..."));
  593.   enterHVProgMode(mcu_mode);
  594.   showLed(true,true,400);
  595.  
  596.   // try to reset all locks
  597.   Serial.println(F("Reset lock byte - if possible..."));
  598.   burnFuse(mcu_mode, 0xFF, LOCK_SEL);
  599.   showLed(true,false,200);
  600.   showLed(false,true,200);
  601.  
  602.   // remove lock by erasing chip - if necessary and allowed
  603.   lk = readFuse(mcu_mode, LOCK_SEL);
  604. #ifdef FBD_MODE
  605.   ec_allowed = (digitalRead(ECJUMPER) == LOW);
  606. #endif
  607.   if (lk != 0xFF && ec_allowed) {
  608.     Serial.println(F("Lock byte could not be changed. Erase chip ..."));
  609.     eraseChip(mcu_mode);
  610.     showLed(true,true,400);
  611.   }
  612.   // try to reset fuses
  613.   Serial.println(F("Set fuses to default values ..."));
  614.   burnFuse(mcu_mode, dlf, LFUSE_SEL);
  615.   if (mcu_fuses > 1) burnFuse(mcu_mode, dhf, HFUSE_SEL);
  616.   if (mcu_fuses > 2) burnFuse(mcu_mode, def, EFUSE_SEL);
  617.   showLed(true,true,400);
  618.  
  619.   // see whether successful
  620.   lk = readFuse(mcu_mode, LOCK_SEL);
  621.   lf = readFuse(mcu_mode,LFUSE_SEL);
  622.   if (mcu_fuses > 1) hf = readFuse(mcu_mode,HFUSE_SEL);
  623.   if (mcu_fuses > 2) ef = readFuse(mcu_mode,EFUSE_SEL);
  624.  
  625.   leaveHVProgMode();
  626.   // if successful blink green, otherwise blink red
  627.   Serial.println(F("Verify fuse settings..."));
  628.   showLed(true,false,100);
  629.   showLed(false,true,100);
  630.   showLed(true,false,100);
  631.   showLed(false,true,100);
  632.   showLed(true,false,100);
  633.   showLed(false,true,100);
  634.   if (verifyFuses(mcu_fuses,
  635.                   lk,0xFF,
  636.                   lf,dlf,
  637.                   hf,dhf,
  638.                   ef,def)) {
  639.     Serial.println(F("-> Resurrection was successful!"));
  640.     ledBlink(GREEN,5);
  641.   } else {
  642.     Serial.println(F("-> Resurrection FAILED!"));
  643.     if (!ec_allowed)
  644.       Serial.println(F("Try again with 'erase chip' jumper set"));
  645.     ledBlink(RED,5);
  646.   }
  647. }
  648.  
  649.  
  650. void setAndVerifyOneByte(int SEL, char* mess) {
  651.   int toburn;
  652.  
  653.   while (Serial.available()) Serial.read();
  654.   Serial.print(F("New "));
  655.   Serial.print(mess);
  656.   Serial.print(F(" : "));
  657.   toburn = askByte();
  658.   if (toburn >= 0x00) {
  659.     Serial.print(F("\nSetting "));
  660.     Serial.print(mess);
  661.     Serial.print(F(" ... "));
  662.     burnFuse(mcu_mode, toburn, SEL);
  663.     verifyOneByte(SEL, toburn, mess);
  664.   }
  665. }
  666.  
  667. void verifyOneByte(int SEL, byte desired, char* mess) {
  668.   byte newval;
  669.  
  670.   showLed(true,true,600);
  671.   Serial.println(F(" done"));
  672.   delay(200);
  673.   Serial.print(F("Verifying ... "));
  674.   newval = readFuse(mcu_mode,SEL);
  675.   showLed(true,true,600);
  676.   if (newval == desired) {
  677.     Serial.print(F("done: Successful in "));
  678.   } else {
  679.     Serial.print(F("done: FAILED in \x07"));
  680.   }
  681.   Serial.println(mess);
  682. }
  683.  
  684.  
  685.  
  686. int searchMCU(unsigned long sig) {
  687.   if ((sig>>16) != 0x1E) return -1;
  688.   for (int i=0; i < MCU_NUM; i++) {
  689.     if ((sig&0xFFFF) == pgm_read_word(&(mcu_types[i][0])))
  690.       return i;
  691.   }
  692.   return -1;
  693. }
  694.  
  695. void printMCUName(int ix) {
  696.   char buf[15];
  697.   if (ix < 0 || ix >= MCU_NUM) return;
  698.   strcpy_P(buf, (PGM_P)pgm_read_word(&(mcu_types[ix][3])));
  699.   Serial.print(buf);
  700. }
  701.  
  702. boolean verifyFuses(int num, byte k1, byte k2, byte l1, byte l2, byte h1, byte h2, byte e1, byte e2) {
  703.   boolean correct;
  704.   correct = (k1 == k2);
  705.   correct = (correct && (l1 == l2));
  706.   if (num > 1) correct = (correct && (h1 == h2));
  707.   if (num > 2) correct = (correct && (e1 == e2));
  708.   return correct;
  709. }
  710.  
  711. unsigned long readSig(int mode) {
  712.   if (mode == HVSP) return readHVSPSig();
  713.   else return readHVPPSig(mode);
  714. }
  715.  
  716. byte readOSCCAL(int mode) {
  717.   if (mode == HVSP) return readHVSPOSCCAL();
  718.   else return readHVPPOSCCAL(mode);
  719. }
  720.  
  721.  
  722.  
  723. byte readFuse(int mode, int selection) {
  724.   if (mode == HVSP) return readHVSPFuse(selection);
  725.   else return readHVPPFuse(mode,selection);
  726. }
  727.  
  728. void burnFuse(int mode, byte val, int selection) {
  729.   if (mode == HVSP) burnHVSPFuse(val,selection);
  730.   else burnHVPPFuse(mode,val,selection);
  731. }
  732.  
  733. void eraseChip(int mode) {
  734.   if (mode == HVSP) eraseHVSP();
  735.   else eraseHVPP(mode);  
  736. }
  737.  
  738. void enterHVProgMode(int mode) {
  739.  
  740.   // Initialize pins to enter programming mode
  741.   if (mode == TINY2313) {
  742.     PAGEL = BS1;
  743.     XA1 = BS2;
  744.   } else {
  745.     PAGEL = ORIGPAGEL;
  746.     XA1 = ORIGXA1;
  747.   }
  748.  
  749.   setData(0);
  750.   setDataDirection(INPUT);
  751.   digitalWrite(PAGEL, LOW);
  752.   digitalWrite(XA1, LOW);
  753.   digitalWrite(XA0, LOW);
  754.   digitalWrite(BS1, LOW);
  755.   digitalWrite(BS2, LOW);
  756.   digitalWrite(WR, LOW);  // ATtiny2313 needs this to be low to enter programming mode, ATmega doesn't care
  757.   digitalWrite(OE, LOW);
  758.   delay(100); // to let it settle, since otherwise Vcc may be already high due to XA1 high
  759.  
  760.   if(mode == HVSP) {
  761.     pinMode(SCI,OUTPUT);
  762.     pinMode(SDI,OUTPUT);
  763.     pinMode(SII,OUTPUT);
  764.     pinMode(SDO,OUTPUT);
  765.     digitalWrite(SDI, LOW);  // set necessary pin values to enter programming mode
  766.     digitalWrite(SII, LOW);
  767.     digitalWrite(SDO, LOW);  // needs to be low to enter programming mode
  768.     digitalWrite(SCI, LOW);
  769.   }
  770.  
  771.   // Enter programming mode
  772.   digitalWrite(VCC, VCCON);  // Apply VCC to start programming process
  773.   delayMicroseconds(80);
  774.   digitalWrite(RST, HIGH);   // Apply 12V to !RESET
  775.  
  776.   if(mode == HVSP) {
  777.     // reset SDO after short delay, longer leads to logic contention because target sets SDO high after entering programming mode
  778.     delayMicroseconds(1);   // datasheet says 10us, 1us is needed to avoid drive contention on SDO
  779.     pinMode(SDO, INPUT);    // set to input to avoid logic contention
  780.   }
  781.  
  782.   delayMicroseconds(10);  // Give lots of time for part to enter programming mode
  783.   digitalWrite(OE, HIGH);
  784.   digitalWrite(WR, HIGH);   // Now that we're in programming mode we can disable !WR
  785.   delay(1);
  786. }
  787.  
  788. void leaveHVProgMode() {
  789.   setData(0);
  790.   setDataDirection(INPUT);
  791.  
  792.   PAGEL = ORIGPAGEL;
  793.   XA1 = ORIGXA1;
  794.   digitalWrite(OE, HIGH);
  795.   digitalWrite(RST, LOW);  // exit programming mode
  796.   delay(1);
  797.   digitalWrite(OE, LOW);
  798.   digitalWrite(WR, LOW);
  799.   digitalWrite(PAGEL, LOW);
  800.   digitalWrite(XA1, LOW);
  801.   digitalWrite(XA0, LOW);
  802.   digitalWrite(BS1, LOW);
  803.   digitalWrite(BS2, LOW);
  804.   digitalWrite(VCC, VCCOFF);
  805. }
  806.  
  807.  
  808. void eraseHVPP(int mode) {
  809.  
  810.   sendHVPPCmdOrAddr(mode,true,B10000000);
  811.   digitalWrite(WR, LOW);
  812.   delay(1);
  813.   digitalWrite(WR, HIGH);
  814.   //delay(100);
  815.  
  816.   waitForHigh(RDY); // when RDY goes high, we are done
  817. }
  818.  
  819. void eraseHVSP(void) {
  820.   HVSP_write(HVSP_ERASE_CHIP_DATA, HVSP_ERASE_CHIP_INSTR1);
  821.   HVSP_write(0x00, HVSP_ERASE_CHIP_INSTR2);
  822.   HVSP_write(0x00, HVSP_ERASE_CHIP_INSTR3);
  823.   waitForHigh(SDO);
  824. }
  825.  
  826.  
  827. void burnHVPPFuse(int mode, byte fuse, int select)  // write high or low fuse to AVR
  828. {
  829.  
  830.   // Send command to enable fuse programming mode
  831.   if (select == LOCK_SEL)   sendHVPPCmdOrAddr(mode,true,B00100000);  
  832.   else sendHVPPCmdOrAddr(mode,true,B01000000);  
  833.  
  834.   // Enable data loading
  835.   digitalWrite(XA1, LOW);
  836.   digitalWrite(XA0, HIGH);
  837.   // Specify low byte
  838.   digitalWrite(BS1, LOW);
  839.   if (mode != TINY2313)
  840.     digitalWrite(BS2, LOW);  
  841.   delay(1);
  842.  
  843.   // Load fuse value into target
  844.   setData(fuse);
  845.   setDataDirection(OUTPUT);
  846.  
  847.   strobe_xtal();  // latch DATA
  848.  
  849.   setData(0);
  850.   setDataDirection(INPUT);
  851.    
  852.   // Decide which fuse location to burn
  853.   switch (select) {
  854.   case HFUSE_SEL:
  855.     digitalWrite(BS1, HIGH); // program HFUSE
  856.     digitalWrite(BS2, LOW);
  857.     break;
  858.   case LFUSE_SEL:
  859.     digitalWrite(BS1, LOW);  // program LFUSE
  860.     digitalWrite(BS2, LOW);
  861.     break;
  862.   case EFUSE_SEL:
  863.     digitalWrite(BS1, LOW);  // program EFUSE
  864.     digitalWrite(BS2, HIGH);
  865.     break;
  866.   }
  867.   delay(1);
  868.    // Burn the fuse
  869.   digitalWrite(WR, LOW);
  870.   delay(1);
  871.   digitalWrite(WR, HIGH);
  872.   //delay(100);
  873.  
  874.   waitForHigh(RDY); // when RDY goes high, we are done
  875.  
  876.   // Reset control lines to original state
  877.   digitalWrite(BS1, LOW);
  878.   digitalWrite(BS2, LOW);
  879. }
  880.  
  881. void burnHVSPFuse(byte fuse, int select) {
  882.  
  883.   switch (select) {
  884.   case LFUSE_SEL:
  885.     HVSP_write(HVSP_WRITE_LFUSE_DATA, HVSP_WRITE_LFUSE_INSTR1);
  886.     HVSP_write(fuse, HVSP_WRITE_LFUSE_INSTR2);
  887.     HVSP_write(0x00, HVSP_WRITE_LFUSE_INSTR3);
  888.     HVSP_write(0x00, HVSP_WRITE_LFUSE_INSTR4);
  889.     break;
  890.  
  891.   case HFUSE_SEL:    
  892.     HVSP_write(HVSP_WRITE_HFUSE_DATA, HVSP_WRITE_HFUSE_INSTR1);
  893.     HVSP_write(fuse, HVSP_WRITE_HFUSE_INSTR2);
  894.     HVSP_write(0x00, HVSP_WRITE_HFUSE_INSTR3);
  895.     HVSP_write(0x00, HVSP_WRITE_HFUSE_INSTR4);
  896.     break;
  897.    
  898.   case EFUSE_SEL:
  899.     HVSP_write(HVSP_WRITE_EFUSE_DATA, HVSP_WRITE_EFUSE_INSTR1);
  900.     HVSP_write(fuse, HVSP_WRITE_EFUSE_INSTR2);
  901.     HVSP_write(0x00, HVSP_WRITE_EFUSE_INSTR3);
  902.     HVSP_write(0x00, HVSP_WRITE_EFUSE_INSTR4);
  903.     break;
  904.  
  905.   case LOCK_SEL:
  906.     HVSP_write(HVSP_WRITE_LOCK_DATA, HVSP_WRITE_LOCK_INSTR1);
  907.     HVSP_write(fuse, HVSP_WRITE_LOCK_INSTR2);
  908.     HVSP_write(0x00, HVSP_WRITE_LOCK_INSTR3);
  909.     HVSP_write(0x00, HVSP_WRITE_LOCK_INSTR4);
  910.     break;
  911.   }
  912.   waitForHigh(SDO);
  913.   return;
  914. }
  915.  
  916.  
  917. byte readHVPPFuse(int mode, int select) {
  918.   byte fuse;
  919.  
  920.   sendHVPPCmdOrAddr(mode,true,B00000100);  // Send command to read fuse bits
  921.  
  922.   // Configure DATA as input so we can read back fuse values from target
  923.   setData(0);
  924.   setDataDirection(INPUT);
  925.  
  926.   // Set control lines
  927.   switch (select) {
  928.   case LFUSE_SEL:  
  929.       // Read LFUSE
  930.       digitalWrite(BS2, LOW);
  931.       digitalWrite(BS1, LOW);
  932.       break;
  933.   case HFUSE_SEL:
  934.       // Read HFUSE
  935.       digitalWrite(BS2, HIGH);
  936.       digitalWrite(BS1, HIGH);
  937.       break;
  938.   case EFUSE_SEL:
  939.       // Read EFUSE
  940.       digitalWrite(BS2, HIGH);
  941.       digitalWrite(BS1, LOW);
  942.       break;
  943.   case LOCK_SEL:
  944.       // Read LOCK
  945.       digitalWrite(BS2, LOW);
  946.       digitalWrite(BS1, HIGH);
  947.       break;    
  948.   }
  949.  
  950.   //  Read fuse
  951.   digitalWrite(OE, LOW);
  952.   delay(1);
  953.  
  954.   fuse = getData();
  955.  
  956.   digitalWrite(OE, HIGH);  // Done reading, disable output enable line
  957.   return fuse;
  958. }
  959.  
  960. byte readHVSPFuse(int select) {
  961.   byte fuse;
  962.  
  963.   switch (select) {
  964.  
  965.   case LFUSE_SEL:
  966.     HVSP_read(HVSP_READ_LFUSE_DATA, HVSP_READ_LFUSE_INSTR1);
  967.     HVSP_read(0x00, HVSP_READ_LFUSE_INSTR2);
  968.     fuse=HVSP_read(0x00, HVSP_READ_LFUSE_INSTR3);
  969.     break;
  970.  
  971.   case HFUSE_SEL:
  972.     HVSP_read(HVSP_READ_HFUSE_DATA, HVSP_READ_HFUSE_INSTR1);
  973.     HVSP_read(0x00, HVSP_READ_HFUSE_INSTR2);
  974.     fuse=HVSP_read(0x00, HVSP_READ_HFUSE_INSTR3);
  975.     break;
  976.  
  977.   case EFUSE_SEL:
  978.     HVSP_read(HVSP_READ_EFUSE_DATA, HVSP_READ_EFUSE_INSTR1);
  979.     HVSP_read(0x00, HVSP_READ_EFUSE_INSTR2);
  980.     fuse=HVSP_read(0x00, HVSP_READ_EFUSE_INSTR3);
  981.     break;
  982.  
  983.   case LOCK_SEL:
  984.     HVSP_read(HVSP_READ_LOCK_DATA, HVSP_READ_LOCK_INSTR1);
  985.     HVSP_read(0x00, HVSP_READ_LOCK_INSTR2);
  986.     fuse=HVSP_read(0x00, HVSP_READ_LOCK_INSTR3);
  987.     break;
  988.   }
  989.   return fuse;
  990. }
  991.  
  992. unsigned long readHVPPSig(int mode) {
  993.  
  994.   unsigned long result = 0;
  995.  
  996.   // Configure DATA as input so we can read back fuse values from target
  997.   setData(0);
  998.   setDataDirection(INPUT);
  999.   for (byte i=0;i<3;i++) {
  1000.     sendHVPPCmdOrAddr(mode,true,B00001000);
  1001.     sendHVPPCmdOrAddr(mode,false,i);
  1002.     digitalWrite(BS1,LOW);
  1003.     digitalWrite(OE, LOW);
  1004.     delay(1);
  1005.     result = (result<<8)+getData();
  1006.     digitalWrite(OE, HIGH);
  1007.   }
  1008.   return result;
  1009. }
  1010.  
  1011.  
  1012. byte readHVPPOSCCAL(int mode) {
  1013.   byte result;
  1014.  
  1015.   setData(0);
  1016.   setDataDirection(INPUT);
  1017.   sendHVPPCmdOrAddr(mode,true,B00001000);
  1018.   sendHVPPCmdOrAddr(mode,false,0);
  1019.   digitalWrite(BS1,LOW);
  1020.   digitalWrite(OE, LOW);
  1021.   delay(1);
  1022.   result = getData();
  1023.   digitalWrite(OE, HIGH);
  1024.   return result;
  1025. }
  1026.  
  1027. unsigned long readHVSPSig() {
  1028.  
  1029.   unsigned long result = 0;
  1030.  
  1031.   for (byte i=0;i<3;i++) {
  1032.     HVSP_read(HVSP_READ_SIG_DATA, HVSP_READ_SIG_INSTR1);
  1033.     HVSP_read(i, HVSP_READ_SIG_INSTR2);
  1034.     HVSP_read(0x00, HVSP_READ_SIG_INSTR3);
  1035.     result = (result<<8) + HVSP_read(0x00, HVSP_READ_SIG_INSTR4);
  1036.   }
  1037.   return result;
  1038. }
  1039.  
  1040. byte readHVSPOSCCAL() {
  1041.   HVSP_read(HVSP_READ_OSC_DATA, HVSP_READ_OSC_INSTR1);
  1042.   HVSP_read(0x00, HVSP_READ_OSC_INSTR2);
  1043.   HVSP_read(0x00, HVSP_READ_OSC_INSTR3);
  1044.   return HVSP_read(0x00, HVSP_READ_OSC_INSTR4);
  1045. }
  1046.  
  1047.  
  1048.  
  1049. byte HVSP_read(byte data, byte instr) { // Read a byte using the HVSP protocol
  1050.  
  1051.   byte response = 0x00; // a place to hold the response from target
  1052.  
  1053.   digitalWrite(SCI, LOW);  // set clock low
  1054.   // 1st bit is always zero
  1055.   digitalWrite(SDI, LOW);
  1056.   digitalWrite(SII, LOW);
  1057.   sclk();
  1058.  
  1059.   // We capture a response on every readm even though only certain responses contain
  1060.   // valid data.  For fuses, the valid response is captured on the 3rd instruction write.
  1061.   // It is up to the program calling this function to figure out which response is valid.
  1062.  
  1063.   // The MSB of the response byte comes "early", that is,
  1064.   // before the 1st non-zero-padded byte of the 3rd instruction is sent to the target.
  1065.   // For more information, see the ATtiny25/45/85 datasheet, Table 20-16 (pg. 164).
  1066.   if (digitalRead(SDO) == HIGH) // target sent back a '1'?
  1067.     response |= 0x80;  // set MSB of response byte high
  1068.  
  1069.   // Send each bit of data and instruction byte serially, MSB first
  1070.   // I do this by shifting the byte left 1 bit at a time and checking the value of the new MSB
  1071.   for (int i=0; i<8; i++) {  // i is bit number
  1072.     if ((data << i) & 0x80)  // shift data byte left and check if new MSB is 1 or 0
  1073.       digitalWrite(SDI, HIGH);  // bit was 1, set pin high
  1074.     else
  1075.       digitalWrite(SDI, LOW);   // bit was 0, set pin low
  1076.      
  1077.     if ((instr << i) & 0x80)   // same process for instruction byte
  1078.       digitalWrite(SII, HIGH);
  1079.     else
  1080.       digitalWrite(SII, LOW);
  1081.    sclk();
  1082.        
  1083.     if (i < 7) {  // remaining 7 bits of response are read here (one at a time)
  1084.       // note that i is one less than the bit position of response we are reading, since we read
  1085.       // the MSB above.  That's why I shift 0x40 right and not 0x80.
  1086.       if(digitalRead(SDO) == HIGH)  // if we get a logic 1 from target,
  1087.         response |= (0x40 >> i);    // set corresponding bit of response to 1
  1088.     }
  1089.   }
  1090.  
  1091.   // Last 2 bits are always zero
  1092.   for (int i=0; i<2; i++) {
  1093.     digitalWrite(SDI, LOW);
  1094.     digitalWrite(SII, LOW);
  1095.     sclk();
  1096.   }
  1097.  
  1098.   return response;
  1099. }
  1100.  
  1101. void HVSP_write(byte data, byte instr) { // Write to target using the HVSP protocol
  1102.  
  1103.   digitalWrite(SCI, LOW);  // set clock low
  1104.  
  1105.   // 1st bit is always zero
  1106.   digitalWrite(SDI, LOW);
  1107.   digitalWrite(SII, LOW);
  1108.   sclk();  // latch bit
  1109.  
  1110.   // Send each bit of data and instruction byte serially, MSB first
  1111.   // I do this by shifting the byte left 1 bit at a time and checking the value of the new MSB
  1112.   for (int i=0; i<8; i++) {  // i is bit number
  1113.     if ((data << i) & 0x80)  // shift data byte left and check if new MSB is 1 or 0
  1114.       digitalWrite(SDI, HIGH);  // bit was 1, set pin high
  1115.     else
  1116.       digitalWrite(SDI, LOW);   // bit was 0, set pin low
  1117.      
  1118.     if ((instr << i) & 0x80)  // same process for instruction byte
  1119.       digitalWrite(SII, HIGH);
  1120.     else
  1121.       digitalWrite(SII, LOW);
  1122.      
  1123.    sclk();  // strobe SCI (serial clock) to latch data
  1124.   }
  1125.  
  1126.   // Last 2 bits are always zero
  1127.   for (int i=0; i<2; i++) {
  1128.     digitalWrite(SDI, LOW);
  1129.     digitalWrite(SII, LOW);  
  1130.     sclk();
  1131.   }
  1132. }
  1133.  
  1134. void sendHVPPCmdOrAddr(int mode, boolean is_cmd, byte cmd_or_addr)  // Send command to target AVR
  1135. {
  1136.   // Set controls for command mode
  1137.   if (is_cmd) digitalWrite(XA1, HIGH);
  1138.   else   digitalWrite(XA1,LOW);
  1139.   digitalWrite(XA0, LOW);
  1140.   digitalWrite(BS1, LOW);  
  1141.  
  1142.   if (mode != TINY2313)
  1143.     digitalWrite(BS2, LOW);  // Command load seems not to work if BS2 is high
  1144.  
  1145.   setData(cmd_or_addr);
  1146.   setDataDirection(OUTPUT);
  1147.  
  1148.   strobe_xtal();  // latch DATA
  1149.  
  1150.   setData(0);
  1151.   setDataDirection(INPUT);
  1152.   digitalWrite(XA1, LOW);
  1153. }
  1154.  
  1155. void waitForHigh(byte signal) {
  1156.   for (int i=0; i<1000; i++) {
  1157.     if (digitalRead(signal) == HIGH) return;
  1158.     delay(1);
  1159.   }
  1160.   Serial.println(F("Timeout during write operation"));
  1161. }
  1162.  
  1163.  
  1164. void sclk(void) {  // send serial clock pulse, used by HVSP commands
  1165.  
  1166.   // These delays are much  longer than the minimum requirements,
  1167.   // but we don't really care about speed.
  1168.   delay(1);  
  1169.   digitalWrite(SCI, HIGH);
  1170.   delay(1);
  1171.   digitalWrite(SCI, LOW);
  1172. }
  1173.  
  1174. void strobe_xtal(void) {  // strobe xtal (usually to latch data on the bus)
  1175.  
  1176.   delay(1);
  1177.   digitalWrite(XTAL1, HIGH);  // pulse XTAL to send command to target
  1178.   delay(1);
  1179.   digitalWrite(XTAL1, LOW);
  1180. }
  1181.  
  1182. void setDataDirection(int dir) {
  1183. #ifdef FBD_MODE
  1184.   if (dir == INPUT) DDRB = 0;
  1185.   else DDRB = 0xFF;
  1186. #else
  1187.   for (byte pin = 2; pin < 10; pin++) pinMode(pin,dir);
  1188. #endif
  1189. }
  1190.  
  1191. byte getData(void) {
  1192. #ifdef FBD_MODE
  1193.   return PINB;
  1194. #else
  1195.   byte res = 0;
  1196.   for (byte pin = 2; pin < 10; pin++)
  1197.     res = (res<<1)+digitalRead(pin);
  1198.   return(res);
  1199. #endif
  1200. }
  1201.    
  1202. void setData(byte data) {
  1203. #ifdef FBD_MODE
  1204.   PORTB = data;
  1205. #else
  1206.   for (byte pin = 2; pin < 10; pin++) {
  1207.     digitalWrite(pin,((data&B10000000) != 0));
  1208.     data = data << 1;
  1209.   }
  1210. #endif
  1211. }
  1212.  
  1213.  
  1214.  
  1215. int askByte(void) {  // get new byte value
  1216.   char serbuffer[2];
  1217.   byte i = 0;
  1218.   char next;
  1219.  
  1220.   while (i <= 2) {
  1221.     while (Serial.available() == 0);   // wait for a character to come in
  1222.     next = Serial.read();
  1223.     if (i <= 2 && (next == '\b' || next == '\x7F')) {
  1224.       if (i > 0) {
  1225.         Serial.print("\b \b");
  1226.         i--;
  1227.       }
  1228.     } else {
  1229.       if (i == 2) {
  1230.         if (next == ' ' || next == '\r' || next == '\n') break;
  1231.         else {
  1232.           Serial.println(F("\nInvalid end-of-line character"));
  1233.           return -1;
  1234.         }
  1235.       } else {
  1236.         if (next >= 'a' && next <= 'f') next = toupper(next);
  1237.         if ((next >= '0' && next <= '9') || (next >= 'A' && next <= 'F')) {
  1238.           serbuffer[i++] = next;
  1239.           Serial.print(next);
  1240.         } else {
  1241.           Serial.println(F("Invalid hexadecimal character"));
  1242.           return -1;
  1243.         }
  1244.       }
  1245.     }
  1246.   }
  1247.   Serial.println();
  1248.   return(hex2dec(serbuffer[1]) + hex2dec(serbuffer[0]) * 16);
  1249. }
  1250.  
  1251.  
  1252. int hex2dec(byte c) { // converts one HEX character into a number
  1253.   if (c >= '0' && c <= '9') {
  1254.     return c - '0';
  1255.   }
  1256.   else if (c >= 'A' && c <= 'F') {
  1257.     return c - 'A' + 10;
  1258.   }
  1259.   else return 0;
  1260. }
  1261.  
  1262. void printFuses(char *str, byte num, byte l, byte h, byte e) {
  1263.   Serial.print(str);
  1264.   switch (num) {
  1265.   case 1: Serial.print(F("Fuse byte:   ")); break;
  1266.   case 2: Serial.print(F("L/H-Fuses:   ")); break;
  1267.   case 3: Serial.print(F("L/H/E-Fuses: ")); break;
  1268.   }
  1269.   print2Hex(l,true);
  1270.   if (num > 1) print2Hex(h,true);
  1271.   if (num > 2) print2Hex(e,true);
  1272.   Serial.println();
  1273. }
  1274.  
  1275. void printLock(byte l) {
  1276.   Serial.print(F("Current lock byte:   "));
  1277.   print2Hex(l,true);
  1278.   Serial.println();
  1279. }
  1280.  
  1281. void printOSCCAL(byte l) {
  1282.   Serial.print(F("Oscillator calibr.:  "));
  1283.   print2Hex(l,true);
  1284.   Serial.println();
  1285. }
  1286.  
  1287. void print2Hex(byte val, boolean blank)
  1288. { // print two hex digits
  1289.   if (val < 0x10) Serial.print('0');
  1290.   Serial.print(val,HEX);
  1291.   if (blank) Serial.print(' ');
  1292. }
  1293.  
  1294. void showLed(boolean red, boolean green, unsigned int time)
  1295. {
  1296. #ifdef FBD_MODE
  1297.   if (red) digitalWrite(XA0,HIGH);
  1298.   if (green) digitalWrite(ORIGXA1,HIGH);
  1299. #endif
  1300.   delay(time);
  1301. #ifdef FBD_MODE
  1302.   digitalWrite(XA0,LOW);
  1303.   digitalWrite(ORIGXA1,LOW);
  1304. #endif
  1305. }
  1306.  
  1307. void ledBlink(byte color,byte sec) {
  1308.  
  1309. #ifdef FBD_MODE
  1310.   for (int i=0; i < 10*sec; i++) {
  1311.     if (color == RED) digitalWrite(XA0,HIGH);
  1312.     else digitalWrite(XA1,HIGH);
  1313.     delay(50);
  1314.     digitalWrite(XA0,LOW);
  1315.     digitalWrite(XA1,LOW);
  1316.     delay(50);
  1317.   }
  1318. #endif
  1319. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement