How to program micro Atmega 64 using Arduino Nano

Hello
I want to program an Atmega 64 micro using Arduino Nano in such a way that I put the hex file on the main program or in the external memory.
Please help me if anyone has any information on how to write a program like this

MCUdude MegaCore supports the ATmega64. Check whether external program memory is supported by the core and by the bootloader.

1 Like

I moved your topic to an appropriate forum category @amir11228 .

In the future, please take some time to pick the forum category that best suits the subject of your topic. There is an "About the _____ category" topic at the top of each category that explains its purpose.

This is an important part of responsible forum usage, as explained in the "How to get the best out of this forum" guide. The guide contains a lot of other useful information. Please read it.

Thanks in advance for your cooperation.

hello
Thank you for your reply, but I have already done this by using a laptop to load the bootloader and then program the program, but I want to use the Arduino Nano micro64 ATmega without using a laptop and only by connecting the micro Program to Arduino by pressing a key and the hex file that I want to program is either inside the Arduino program itself or in the external storage of the SD card.

I asked ai and he gave me this program, that is, the hex file of the LED program, which is: 100000000C94A6000C94B8000C94B8000C94B800A2
:100010000C94B8000C94B8000C94B8000C94B80080
:100020000C94B8000C94B8000C94B8000C94B80070
:100030000C94B8000C94B8000C94B8000C94B80060
:100040000C9498010C94B8000C94B8000C94B8006F
:100050000C94B8000C94B8000C94B8000C94B80040
:100060000C94B8000C94B8000C94B8000C94B80030
:100070000C94B8000C94B8000C94B8000C94B80020
:100080000C94B8000C94B8000C94B80000003A002E
:1000900037003400310022006100640000003B00A2
:1000A00038003500320023006200650005050505B3
:1000B0000505050502020202020202020707040406
:1000C00004040404040407070303030303030303F2
:1000D00007010101010101010106060606060606E7
:1000E000060102040810204080010204081020408C
:1000F000800810010204081020408001020102045F
:1001000008102040800480402010080402010102F1
:100110000408102040800000000A0B0C00000000C2
:1001200000000104050600000000000000000000BF
:10013000000000000000000000000000000000000BF
:10014000000000000000000000000000011241FBE9D
:10015000CFEFD0E1DEBFCDBF21E0A0E0B1E001C034
:100160001D92A630B207E1F70E94DF010C94420213
:100170000C940000EEE3F1E02491E9E0F1E0349129
:10018000E4EDF0E09491992359F12223C1F021503C
:100190002C30A8F4E22FF0E0E053FF4F0C942D0236
:1001A00009010901DF00DC00F100F400F700DF00C5
:1001B000DF00FB00010105012FB52F772FBDE92FCF
:1001C000F0E0EE0FFF1FE456FF4FA591B4919FB7EB
:1001D000F894EC91811121C030953E233C939FBF50
:1001E00008952FB52F7DEACF2FB5277FE7CF25B50F
:1001F0002F7D25BDE4CF20918B002F7720938B009E
:10020000DECF20918B002F7DF9CF20918B00277FAF
:10021000F5CF23B72F7D23BFD2CF3E2BDFCFCF9299
:10022000DF92EF92FF926FB7F89480910201909164
:100230000301A0910401B09105015091010122B781
:1002400036B7432F417030FF04C041E02F3F09F41F
:1002500040E06FBF6C017D0137E0CC0CDD1CEE1C73
:10026000FF1C3A95D1F7C50ED11CE11CF11CC81A30
:10027000D90AEA0AFB0A880F991FAA1FBB1FC81ACE
:10028000D90AEA0AFB0A63E0CC0CDD1CEE1CFF1C59
:100290006A95D1F730E0A9ECB5E00E943302672FF0
:1002A000782F892F99276C0D7D1D8E1D9F1D44234E
:1002B00021F067537A4F8F4F9F4FFF90EF90DF9061
:1002C000CF9008958F929F92AF92BF92CF92DF927C
:1002D000EF92FF920E940F014B015C0188EEC82E45
:1002E00083E0D82EE12CF12C0E940F0168197909C6
:1002F0008A099B09683E734081059105A8F321E0B6
:10030000C21AD108E108F10888EE880E83E0981E31
:10031000A11CB11CC114D104E104F10429F7FF9020
:10032000EF90DF90CF90BF90AF909F908F90089507
:100330001F920F920FB60F9211244F935F936F93FA
:100340007F938F939F93409102015091030160919D
:1003500004017091050180910101909100019A3191
:1003600019F51092000190910001953008F1845C1C
:100370008D3700F18D574E5F5F4F6F4F7F4F8093EA
:1003800001014093020150930301609304017093B3
:1003900005019F918F917F916F915F914F910F9088
:1003A0000FBE0F901F9018959F5F90930001DBCFB9
:1003B000835CDECF4F5F5F4F6F4F7F4FE0CF78940E
:1003C00083B78C6483BF87B7816087BF82E08EBDAF
:1003D0008EB581608EBD8FB581608FBD85B584601F
:1003E00085BD85B5806485BD80918A0083608093DA
:1003F0008A0080918B00816080938B0086E886B9AB
:100400001AB8E9E0F1E02491E4EDF0E0849188236A
:1004100099F090E0880F991FFC01E457FF4FA591D8
:10042000B491FC01E456FF4F859194918FB7F894F5
:10043000EC91E22BEC938FBFC0E0D0E081E00E9412
:10044000BA000E94620180E00E94BA000E9462012C
:100450002097A1F30E940000F1CFEE0FFF1F05903F
:10046000F491E02D0994A29FB001B39FC001A39F16
:10047000700D811D1124911DB29F700D811D1124DD
:08048000911D0895F894FFCFCF
:00000001FF
I gave this to him and he gave me the following program, but I tested it and it didn't work, please help if anyone knows

#include <SPI.h>

#define SS_PIN 10 // Chip Select Pin
#define MOSI_PIN 11 // Master Out Slave In
#define MISO_PIN 12 // Master In Slave Out
#define SCK_PIN 13 // Serial Clock
#define RESET_PIN 8 // Reset Pin for ATmega64

void setup() {
// Pin settings
pinMode(SS_PIN, OUTPUT);
pinMode(RESET_PIN, OUTPUT);

// Enable SPI
SPI.begin();
SPI.setDataMode(SPI_MODE0); // Set SPI mode
SPI.setClockDivider(SPI_CLOCK_DIV64); // Setting the data transfer speed

// Set output pins
digitalWrite(SS_PIN, HIGH);
digitalWrite(RESET_PIN, HIGH);

// Set up a serial connection to display messages
Serial.begin(9600);
Serial.println("Arduino as ISP ready to program ATmega64");

// Start programming
initiateProgramming();
}

void loop() {
// Here you can send your hex file
// Note that the code below is an example of sending a hex

// Assume this data is part of a hex
byte hexData[] = {
// First part:
0x0C, 0x94, 0xA6, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0x98, 0x01, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x00, 0x00, 0x3A, 0x00,
0x37, 0x00, 0x34, 0x00, 0x31, 0x00, 0x22, 0x00,
0x61, 0x00, 0x64, 0x00, 0x00, 0x00, 0x3B, 0x00,
0x38, 0x00, 0x35, 0x00, 0x32, 0x00, 0x23, 0x00,
0x62, 0x00, 0x65, 0x00, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x07, 0x07, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x07, 0x07, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x07, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
0x80, 0x08, 0x10, 0x01, 0x02, 0x04, 0x08, 0x10,
0x20, 0x40, 0x80, 0x04, 0x80, 0x40, 0x20, 0x10,
0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x04, 0x08,
0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x0A,
0x0B, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x11, 0x24, 0x1F, 0xBE, 0xCF, 0xEF, 0xD0, 0xE1,
0xDE, 0xBF, 0xCD, 0xBF, 0x21, 0xE0, 0xA0, 0xE0,
0xB1, 0xE0, 0x01, 0xC0, 0x1D, 0x92, 0xA6, 0x30,
0xB2, 0x07, 0xE1, 0xF7, 0x0E, 0x94, 0xDF, 0x01,
0x0C, 0x94, 0x42, 0x02, 0x0C, 0x94, 0x00, 0x00,
0xEE, 0xE3, 0xF1, 0xE0, 0x24, 0x91, 0xE9, 0xE0,
0xF1, 0xE0, 0x34, 0x91, 0xE4, 0xED, 0xF0, 0xE0,
0x94, 0x91, 0x99, 0x23, 0x59, 0xF1, 0x22, 0x23,
0xC1, 0xF0, 0x21, 0x50, 0x2C, 0x30, 0xA8, 0xF4,
0xE2, 0x2F, 0xF0, 0xE0, 0xE0, 0x53, 0xFF, 0x4F,
0x0C, 0x94, 0x2D, ​​0x02, 0x09, 0x01, 0x09, 0x01,
0xDF, 0x00, 0xDC, 0x00, 0xF1, 0x00, 0xF4, 0x00,
0xF7, 0x00, 0xDF, 0x00, 0xDF, 0x00, 0xFB, 0x00,
0x01, 0x01, 0x05, 0x01, 0x2F, 0xB5, 0x2F, 0x77,
0x2F, 0xBD, 0xE9, 0x2F, 0xF0, 0xE0, 0xEE, 0x0F,
0xFF, 0x1F, 0xE4, 0x56, 0xFF, 0x4F, 0xA5, 0x91,
0xB4, 0x91, 0x9F, 0xB7, 0xF8, 0x94, 0xEC, 0x91,
0x81, 0x11, 0x21, 0xC0, 0x30, 0x95, 0x3E, 0x23,
0x3C, 0x93, 0x9F, 0xBF, 0x08, 0x95, 0x2F, 0xB5,
0x2F, 0x7D, 0xEA, 0xCF, 0x2F, 0xB5, 0x27, 0x7F,
0xE7, 0xCF, 0x25, 0xB5, 0x2F, 0x7D, 0x25, 0xBD,
0xE4, 0xCF, 0x20, 0x91, 0x8B, 0x00, 0x2F, 0x77,
0x20, 0x93, 0x8B, 0x00, 0xDE, 0xCF, 0x20, 0x91,
0x8B, 0x00, 0x2F, 0x7D, 0xF9, 0xCF, 0x20, 0x91,
0x8B, 0x00, 0x27, 0x7F, 0xF5, 0xCF, 0x23, 0xB7,
0x2F, 0x7D, 0x23, 0xBF, 0xD2, 0xCF, 0x3E, 0x2B,
0xDF, 0xCF, 0xCF, 0x92, 0xDF, 0x92, 0xEF, 0x92,
0xFF, 0x92, 0x6F, 0xB7, 0xF8, 0x94, 0x80, 0x91,
0x02, 0x01, 0x90, 0x91, 0x03, 0x01, 0xA0, 0x91,
0x04, 0x01, 0xB0, 0x91, 0x05, 0x01, 0x50, 0x91,
0x01, 0x01, 0x22, 0xB7, 0x36, 0xB7, 0x43, 0x2F,
0x41, 0x70, 0x30, 0xFF, 0x04, 0xC0, 0x41, 0xE0,
0x2F, 0x3F, 0x09, 0xF4, 0x40, 0xE0, 0x6F, 0xBF,
0x6C, 0x01, 0x7D, 0x01, 0x37, 0xE0, 0xCC, 0x0C,
0xDD, 0x1C, 0xEE, 0x1C, 0xFF, 0x1C, 0x3A, 0x95,
0xD1, 0xF7, 0xC5, 0x0E, 0xD1, 0x1C, 0xE1, 0x1C,
0xF1, 0x1C, 0xC8, 0x1A, 0xD9, 0x0A, 0xEA, 0x0A,
0xFB, 0x0A, 0x88, 0x0F, 0x99, 0x1F, 0xAA, 0x1F,
0xBB, 0x1F, 0xC8, 0x1A, 0xD9, 0x0A, 0xEA, 0x0A,
0xFB, 0x0A, 0x63, 0xE0, 0xCC, 0x0C, 0xDD, 0x1C,
0xEE, 0x1C, 0xFF, 0x1C, 0x6A, 0x95, 0xD1, 0xF7,
0x30, 0xE0, 0xA9, 0xEC, 0xB5, 0xE0, 0x0E, 0x94,
0x33, 0x02, 0x67, 0x2F, 0x78, 0x2F, 0x89, 0x2F,
0x99, 0x27, 0x6C, 0x0D, 0x7D, 0x1D, 0x8E, 0x1D,
0x9F, 0x1D, 0x44, 0x23, 0x21, 0xF0, 0x67, 0x53,
0x7A, 0x4F, 0x8F, 0x4F, 0x9F, 0x4F, 0xFF, 0x90,
0xEF, 0x90, 0xDF, 0x90, 0xCF, 0x90, 0x08, 0x95,
0x8F, 0x92, 0x9F, 0x92, 0xAF, 0x92, 0xBF, 0x92,
0xCF, 0x92, 0xDF, 0x92, 0xEF, 0x92, 0xFF, 0x92,
0x0E, 0x94, 0x0F, 0x01, 0x4B, 0x01, 0x5C, 0x01,
0x88, 0xEE, 0xC8, 0x2E, 0x83, 0xE0, 0xD8, 0x2E,
0xE1, 0x2C, 0xF1, 0x2C, 0x0E, 0x94, 0x0F, 0x01,
0x68, 0x19, 0x79, 0x09, 0x8A, 0x09, 0x68, 0x3E,
0x73, 0x40, 0x81, 0x05, 0x91, 0x05, 0xA8, 0xF3,
0x21, 0xE0, 0xC2, 0x1A, 0xD1, 0x08, 0xE1, 0x08,
0xF1, 0x08, 0x88, 0xEE, 0x88, 0x0E, 0x83, 0xE0,
0x98, 0x1E, 0xA1, 0x1C, 0xB1, 0x1C, 0xC1, 0x14,
0xD1, 0x04, 0xE1, 0x04, 0xF1, 0x04, 0x29, 0xF7,
0xFF, 0x90, 0xEF, 0x90, 0xDF, 0x90, 0xCF, 0x90,
0xBF, 0x90, 0xAF, 0x90, 0x9F, 0x90, 0x8F, 0x90,
0x08, 0x95
};

// Send hex data to ATmega64
for (int i = 0; i < sizeof(hexData); i++) {
SPI.transfer(hexData[i]); // Send data via SPI
delay(10); // Small delay to ensure correct processing
}

Serial.println("Programming finished");
while(1); // Stop the program after finishing programming
}

void initiateProgramming() {
// Activation of programming with microcontroller reset
digitalWrite(RESET_PIN, LOW);
delay(100); // Short delay
digitalWrite(RESET_PIN, HIGH);

// Selection of ATmega64 microcontroller for programming
digitalWrite(SS_PIN, LOW); // Enable ATmega64 via SS
delay(10); // Delay for preparation
}

void endProgramming() {
// End of programming
digitalWrite(SS_PIN, HIGH); // Disable ATmega64
digitalWrite(RESET_PIN, HIGH); // Exit from reset mode
SPI.end(); // Disable SPI
}

Hello
want to use the Arduino Nano ATmega 64 without using a laptop and only by connecting the micro Program to Arduino by pressing a key and the hex file that I want to program is either inside the Arduino program itself or in the external storage of the SD card.

I gave this to him and he gave me the following program, but I tested it and it didn't work, please help if anyone knows

#include <SPI.h>

#define SS_PIN 10 // Chip Select Pin
#define MOSI_PIN 11 // Master Out Slave In
#define MISO_PIN 12 // Master In Slave Out
#define SCK_PIN 13 // Serial Clock
#define RESET_PIN 8 // Reset Pin for ATmega64

void setup() {
// Pin settings
pinMode(SS_PIN, OUTPUT);
pinMode(RESET_PIN, OUTPUT);

// Enable SPI
SPI.begin();
SPI.setDataMode(SPI_MODE0); // Set SPI mode
SPI.setClockDivider(SPI_CLOCK_DIV64); // Setting the data transfer speed

// Set output pins
digitalWrite(SS_PIN, HIGH);
digitalWrite(RESET_PIN, HIGH);

// Set up a serial connection to display messages
Serial.begin(9600);
Serial.println("Arduino as ISP ready to program ATmega64");

// Start programming
initiateProgramming();
}

void loop() {
// Here you can send your hex file
// Note that the code below is an example of sending a hex

// Assume this data is part of a hex
byte hexData[] = {
// First part:
0x0C, 0x94, 0xA6, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0x98, 0x01, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x0C, 0x94, 0xB8, 0x00,
0x0C, 0x94, 0xB8, 0x00, 0x00, 0x00, 0x3A, 0x00,
0x37, 0x00, 0x34, 0x00, 0x31, 0x00, 0x22, 0x00,
0x61, 0x00, 0x64, 0x00, 0x00, 0x00, 0x3B, 0x00,
0x38, 0x00, 0x35, 0x00, 0x32, 0x00, 0x23, 0x00,
0x62, 0x00, 0x65, 0x00, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x07, 0x07, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x07, 0x07, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x07, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
0x80, 0x08, 0x10, 0x01, 0x02, 0x04, 0x08, 0x10,
0x20, 0x40, 0x80, 0x04, 0x80, 0x40, 0x20, 0x10,
0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x04, 0x08,
0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x0A,
0x0B, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x11, 0x24, 0x1F, 0xBE, 0xCF, 0xEF, 0xD0, 0xE1,
0xDE, 0xBF, 0xCD, 0xBF, 0x21, 0xE0, 0xA0, 0xE0,
0xB1, 0xE0, 0x01, 0xC0, 0x1D, 0x92, 0xA6, 0x30,
0xB2, 0x07, 0xE1, 0xF7, 0x0E, 0x94, 0xDF, 0x01,
0x0C, 0x94, 0x42, 0x02, 0x0C, 0x94, 0x00, 0x00,
0xEE, 0xE3, 0xF1, 0xE0, 0x24, 0x91, 0xE9, 0xE0,
0xF1, 0xE0, 0x34, 0x91, 0xE4, 0xED, 0xF0, 0xE0,
0x94, 0x91, 0x99, 0x23, 0x59, 0xF1, 0x22, 0x23,
0xC1, 0xF0, 0x21, 0x50, 0x2C, 0x30, 0xA8, 0xF4,
0xE2, 0x2F, 0xF0, 0xE0, 0xE0, 0x53, 0xFF, 0x4F,
0x0C, 0x94, 0x2D, ​​0x02, 0x09, 0x01, 0x09, 0x01,
0xDF, 0x00, 0xDC, 0x00, 0xF1, 0x00, 0xF4, 0x00,
0xF7, 0x00, 0xDF, 0x00, 0xDF, 0x00, 0xFB, 0x00,
0x01, 0x01, 0x05, 0x01, 0x2F, 0xB5, 0x2F, 0x77,
0x2F, 0xBD, 0xE9, 0x2F, 0xF0, 0xE0, 0xEE, 0x0F,
0xFF, 0x1F, 0xE4, 0x56, 0xFF, 0x4F, 0xA5, 0x91,
0xB4, 0x91, 0x9F, 0xB7, 0xF8, 0x94, 0xEC, 0x91,
0x81, 0x11, 0x21, 0xC0, 0x30, 0x95, 0x3E, 0x23,
0x3C, 0x93, 0x9F, 0xBF, 0x08, 0x95, 0x2F, 0xB5,
0x2F, 0x7D, 0xEA, 0xCF, 0x2F, 0xB5, 0x27, 0x7F,
0xE7, 0xCF, 0x25, 0xB5, 0x2F, 0x7D, 0x25, 0xBD,
0xE4, 0xCF, 0x20, 0x91, 0x8B, 0x00, 0x2F, 0x77,
0x20, 0x93, 0x8B, 0x00, 0xDE, 0xCF, 0x20, 0x91,
0x8B, 0x00, 0x2F, 0x7D, 0xF9, 0xCF, 0x20, 0x91,
0x8B, 0x00, 0x27, 0x7F, 0xF5, 0xCF, 0x23, 0xB7,
0x2F, 0x7D, 0x23, 0xBF, 0xD2, 0xCF, 0x3E, 0x2B,
0xDF, 0xCF, 0xCF, 0x92, 0xDF, 0x92, 0xEF, 0x92,
0xFF, 0x92, 0x6F, 0xB7, 0xF8, 0x94, 0x80, 0x91,
0x02, 0x01, 0x90, 0x91, 0x03, 0x01, 0xA0, 0x91,
0x04, 0x01, 0xB0, 0x91, 0x05, 0x01, 0x50, 0x91,
0x01, 0x01, 0x22, 0xB7, 0x36, 0xB7, 0x43, 0x2F,
0x41, 0x70, 0x30, 0xFF, 0x04, 0xC0, 0x41, 0xE0,
0x2F, 0x3F, 0x09, 0xF4, 0x40, 0xE0, 0x6F, 0xBF,
0x6C, 0x01, 0x7D, 0x01, 0x37, 0xE0, 0xCC, 0x0C,
0xDD, 0x1C, 0xEE, 0x1C, 0xFF, 0x1C, 0x3A, 0x95,
0xD1, 0xF7, 0xC5, 0x0E, 0xD1, 0x1C, 0xE1, 0x1C,
0xF1, 0x1C, 0xC8, 0x1A, 0xD9, 0x0A, 0xEA, 0x0A,
0xFB, 0x0A, 0x88, 0x0F, 0x99, 0x1F, 0xAA, 0x1F,
0xBB, 0x1F, 0xC8, 0x1A, 0xD9, 0x0A, 0xEA, 0x0A,
0xFB, 0x0A, 0x63, 0xE0, 0xCC, 0x0C, 0xDD, 0x1C,
0xEE, 0x1C, 0xFF, 0x1C, 0x6A, 0x95, 0xD1, 0xF7,
0x30, 0xE0, 0xA9, 0xEC, 0xB5, 0xE0, 0x0E, 0x94,
0x33, 0x02, 0x67, 0x2F, 0x78, 0x2F, 0x89, 0x2F,
0x99, 0x27, 0x6C, 0x0D, 0x7D, 0x1D, 0x8E, 0x1D,
0x9F, 0x1D, 0x44, 0x23, 0x21, 0xF0, 0x67, 0x53,
0x7A, 0x4F, 0x8F, 0x4F, 0x9F, 0x4F, 0xFF, 0x90,
0xEF, 0x90, 0xDF, 0x90, 0xCF, 0x90, 0x08, 0x95,
0x8F, 0x92, 0x9F, 0x92, 0xAF, 0x92, 0xBF, 0x92,
0xCF, 0x92, 0xDF, 0x92, 0xEF, 0x92, 0xFF, 0x92,
0x0E, 0x94, 0x0F, 0x01, 0x4B, 0x01, 0x5C, 0x01,
0x88, 0xEE, 0xC8, 0x2E, 0x83, 0xE0, 0xD8, 0x2E,
0xE1, 0x2C, 0xF1, 0x2C, 0x0E, 0x94, 0x0F, 0x01,
0x68, 0x19, 0x79, 0x09, 0x8A, 0x09, 0x68, 0x3E,
0x73, 0x40, 0x81, 0x05, 0x91, 0x05, 0xA8, 0xF3,
0x21, 0xE0, 0xC2, 0x1A, 0xD1, 0x08, 0xE1, 0x08,
0xF1, 0x08, 0x88, 0xEE, 0x88, 0x0E, 0x83, 0xE0,
0x98, 0x1E, 0xA1, 0x1C, 0xB1, 0x1C, 0xC1, 0x14,
0xD1, 0x04, 0xE1, 0x04, 0xF1, 0x04, 0x29, 0xF7,
0xFF, 0x90, 0xEF, 0x90, 0xDF, 0x90, 0xCF, 0x90,
0xBF, 0x90, 0xAF, 0x90, 0x9F, 0x90, 0x8F, 0x90,
0x08, 0x95
};

// Send hex data to ATmega64
for (int i = 0; i < sizeof(hexData); i++) {
SPI.transfer(hexData[i]); // Send data via SPI
delay(10); // Small delay to ensure correct processing
}

Serial.println("Programming finished");
while(1); // Stop the program after finishing programming
}

void initiateProgramming() {
// Activation of programming with microcontroller reset
digitalWrite(RESET_PIN, LOW);
delay(100); // Short delay
digitalWrite(RESET_PIN, HIGH);

// Selection of ATmega64 microcontroller for programming
digitalWrite(SS_PIN, LOW); // Enable ATmega64 via SS
delay(10); // Delay for preparation
}

void endProgramming() {
// End of programming
digitalWrite(SS_PIN, HIGH); // Disable ATmega64
digitalWrite(RESET_PIN, HIGH); // Exit from reset mode
SPI.end(); // Disable SPI

Please provide a link.

What is the "micro Program"? Another Arduino? Which one?

Who is "him"? What does "didn't work" mean?

There are two problems in your code; the first one is that you're missing a } after the last function. The second one is that there is a stray character in your code that you need to delete. It is between the 0x2D and 0x02 in this line: 0x0C, 0x94, 0x2D, ​​0x02, 0x09, 0x01, 0x09, 0x01,

Please edit your post, select all code and click the <CODE/> button; next save your post.

This will apply code tags to your code which makes it easier to read and easier to copy; the forum software will also display it properly.

I have a program named optiLoader which loads micro atmega 8 with its bootloader. I want to change this program so that it loads the hex file on micro atmega 64 using Arduino. I changed the program as below, but the hex file is complete. It doesn't work. Please help me to put the hex file on the micro atmega 64 with Arduino
`// optiLoader.pde
//
// this sketch allows an Arduino to program Optiboot onto any other
// Arduino-like device containing ATmega8, ATmega168, or ATmega328
// microcontroller chips.
//
// Copyright (c) 2011, 2015 by Bill Westfield ("WestfW")

//-------------------------------------------------------------------------------------
// "MIT Open Source Software License":
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in the
// Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//-------------------------------------------------------------------------------------

//
// this sketch allows an Arduino to program Optiboot onto any other
// Arduino-like device containing ATmega8, ATmega168, or ATmega328
// microcontroller chips.
//
// It is based on AVRISP
//
// Designed to connect to a generic programming cable,
// using the following pins:
// 10: slave reset
// 11: MOSI
// 12: MISO
// 13: SCK
// 9: Power to external chip.
// This is a little questionable, since the power it is legal to draw
// from a PIC pin is pretty close to the power consumption of an AVR
// chip being programmed. But it permits the target to be entirely
// powered down for safe reconnection of the programmer to additional
// targets, and it seems to work for most Arduinos. If the target board
// contains additional circuitry and is expected to draw more than 40mA,
// connect the target power to a stronger source of +5V. Do not use pin
// 9 to power more complex Arduino boards that draw more than 40mA, such
// as the Arduino Uno Ethernet !
//
// If the aim is to reprogram the bootloader in one Arduino using another
// Arudino as the programmer, you can just use jumpers between the connectors
// on the Arduino board. In this case, connect:
// Pin 13 to Pin 13
// Pin 12 to Pin 12
// Pin 11 to Pin 11
// Pin 10 (of "programmer") to RESET (of "target" (on the "power" connector))
// +5V to +5V and GND to GND. Only the "programmer" board should be powered
// by USB or external power.
//
// ----------------------------------------------------------------------

// The following credits are from AVRISP. It turns out that there isn't
// a lot of AVRISP left in this sketch, but probably if AVRISP had never
// existed, this sketch would not have been written.
//
// October 2009 by David A. Mellis
// - Added support for the read signature command
//
// February 2009 by Randall Bohn
// - Added support for writing to EEPROM (what took so long?)
// Windows users should consider WinAVR's avrdude instead of the
// avrdude included with Arduino software.
//
// January 2008 by Randall Bohn
// - Thanks to Amplificar for helping me with the STK500 protocol
// - The AVRISP/STK500 (mk I) protocol is used in the arduino bootloader
// - The SPI functions herein were developed for the AVR910_ARD programmer
// - More information at Google Code Archive - Long-term storage for Google Code Project Hosting.

#include <avr/pgmspace.h>
#include "optiLoader.h"

char Arduino_preprocessor_hint;

/*
Pins to target
*/
#define SCK 13
#define MISO 12
#define MOSI 11
#define RESET 10
#define POWER 9

// STK Definitions; we can still use these as return codes
#define STK_OK 0x10
#define STK_FAILED 0x11

// Useful message printing definitions
#define fp(string) flashprint(PSTR(string));
#define debug(string) // flashprint(PSTR(string));
#define error(string) flashprint(PSTR(string));

// Forward references
void pulse(int pin, int times);
void read_image(const image_t *ip);

// Global Variables

/*
Table of defined images
*/
const image_t * images[] = {
&image_328, &image_328p, &image_168, &image_8,&image_64, 0
};

/*
Table of "Aliases." Chips that are effectively the same as chips
that we have a bootloader for. These work by simply overriding the
signature read with the signature of the chip we "know."
/
const alias_t aliases[] = {
{ "ATmega168PA", 0x940B, 0x9406 }, /
Treat 168P same as 168 /
{ "ATmega168PB", 0x9415, 0x9406 }, /
Treat 168PB same as 168 /
{ "ATmega64", 0x1E9602, 0x1E9602 },
{ "ATmega328PB", 0x9516, 0x950F }, /
Treat 328PB same as 328P /
{ "ATmega328", 0x9514, 0x950F }, /
Treat 328 same as 328P */
};

int pmode = 0;
// address for reading and writing, set by 'U' command
int here;

uint16_t target_type = 0; /* type of target_cpu /
uint16_t target_startaddr;
uint8_t target_pagesize; /
Page size for flash programming (bytes) */
uint8_t *buff;

const image_t target_flashptr; / pointer to target info in flash /
uint8_t target_code[512]; /
The whole code /

void setup (void) {
Serial.begin(19200); /
Initialize serial for status msgs /
pinMode(13, OUTPUT); /
Blink the pin13 LED a few times */
#ifdef PIN_SPI_SS
#if PIN_SPI_SS != RESET
// on non-AtmegaXX8 boards (MEGA, Leonardo, etc) the SPI SS pin is NOT pin 10,
// and although SS is driven manually (RESET to the target), SS should not be
// allowed to default to INPUT and floating, or the SPI hardware may decide that
// some other SPI master is trying to use the bus. (See Datasheet SS description.)
pinMode(PIN_SPI_SS, INPUT_PULLUP);
#endif
#endif
pulse(13, 20);
}

void loop (void) {
fp("\nOptiLoader Bootstrap programmer.\n2011 by Bill Westfield (WestfW)\n\n");
if (target_poweron()) { /* Turn on target power /
do {
if (!target_identify()) /
Figure out what kind of CPU /
break;
if (!target_findimage()) /
look for an image /
break;
if (!target_progfuses()) /
get fuses ready to program /
break;
if (!target_program()) /
Program the image /
break;
(void) target_normfuses(); /
reset fuses to normal mode /
}
while (0);
}
else {
Serial.println();
}
target_poweroff(); /
turn power off */

fp ("\nType 'G' or hit RESET for next chip\n")
while (1) {
if (Serial.read() == 'G')
break;
}
}

/*
Low level support functions
*/

/*
flashprint
print a text string direct from flash memory to Serial
*/
void flashprint (const char p[])
{
uint8_t c;
while (0 != (c = pgm_read_byte(p++))) {
Serial.write(c);
}
}

/*
hexton
Turn a Hex digit (0..9, A..F) into the equivalent binary value (0-16)
*/
uint8_t hexton (uint8_t h)
{
if (h >= '0' && h <= '9')
return (h - '0');
if (h >= 'A' && h <= 'F')
return ((h - 'A') + 10);
error("Bad hex digit!");
return (0);
}

/*
pulse
turn a pin on and off a few times; indicates life via LED
*/
#define PTIME 30
void pulse (int pin, int times) {
do {
digitalWrite(pin, HIGH);
delay(PTIME);
digitalWrite(pin, LOW);
delay(PTIME);
}
while (times--);
}

/*
spi_init
initialize the AVR SPI peripheral
*/
void spi_init (void) {
uint8_t x;
SPCR = 0x53; // SPIE | MSTR | SPR1 | SPR0
x = SPSR;
x = SPDR;
}

/*
spi_wait
wait for SPI transfer to complete
*/
void spi_wait (void) {
debug("spi_wait");
do {
}
while (!(SPSR & (1 << SPIF)));
}

/*
spi_send
send a byte via SPI, wait for the transfer.
*/
uint8_t spi_send (uint8_t b) {
uint8_t reply;
SPDR = b;
spi_wait();
reply = SPDR;
return reply;
}

/*
Functions specific to ISP programming of an AVR
*/

/*
target_identify
read the signature bytes (if possible) and check whether it's
a legal value (atmega8, atmega168, atmega328)
*/

boolean target_identify ()
{
boolean result;
target_type = 0;
fp("\nReading signature:");
target_type = read_signature();
if (target_type == 0 || target_type == 0xFFFF) {
fp(" Bad value: ");
result = false;
}
else {
result = true;
}
Serial.println(target_type, HEX);
if (target_type == 0) {
fp(" (no target attached?)\n");
}
return result;
}

unsigned long spi_transaction (uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
uint8_t n, m;
spi_send(a);
n = spi_send(b);
//if (n != a) error = -1;
m = spi_send(c);
return 0xFFFFFF & ((((uint32_t)n) << 16) + (m << 8) + spi_send(d));
}

uint16_t start_pmode () {
uint16_t result;

pinMode(13, INPUT); // restore to default
spi_init();
debug("...spi_init done");
// following delays may not work on all targets...
pinMode(RESET, OUTPUT);
digitalWrite(RESET, HIGH);
pinMode(SCK, OUTPUT);
digitalWrite(SCK, LOW);
delay(50);
digitalWrite(RESET, LOW);
delay(50);
pinMode(MISO, INPUT);
pinMode(MOSI, OUTPUT);
debug("...spi_transaction");
result = spi_transaction(0xAC, 0x53, 0x00, 0x00);
debug("...Done");
pmode = 1;
return result;
}

void end_pmode (void) {
SPCR = 0; /* reset SPI /
digitalWrite(MISO, 0); /
Make sure pullups are off too /
pinMode(MISO, INPUT);
digitalWrite(MOSI, 0);
pinMode(MOSI, INPUT);
digitalWrite(SCK, 0);
pinMode(SCK, INPUT);
digitalWrite(RESET, 0);
pinMode(RESET, INPUT);
pmode = 0;
}

/

read_image

Read an intel hex image from a string in pgm memory.
We assume that the image does not exceed the 512 bytes that we have
allowed for it to have. that would be bad.
Also read other data from the image, such as fuse and protecttion byte
values during programming, and for after we're done.
*/
void read_image (const image_t *ip)
{
uint16_t len, totlen = 0, addr;
const char *hextext = &ip->image_hexcode[0];
target_startaddr = 0;
target_pagesize = pgm_read_byte(&ip->image_pagesize);
uint8_t b, cksum = 0;

while (1) {
if (pgm_read_byte(hextext++) != ':') {
error("No colon");
break;
}
len = hexton(pgm_read_byte(hextext++));
len = (len << 4) + hexton(pgm_read_byte(hextext++));
cksum = len;

b = hexton(pgm_read_byte(hextext++)); /* record type */
b = (b << 4) + hexton(pgm_read_byte(hextext++));
cksum += b;
addr = b;
b = hexton(pgm_read_byte(hextext++)); /* record type */
b = (b << 4) + hexton(pgm_read_byte(hextext++));
cksum += b;
addr = (addr << 8) + b;
if (target_startaddr == 0) {
  target_startaddr = addr;
  fp("  Start address at ");
  Serial.println(addr, HEX);
}
else if (addr == 0) {
  break;
}

b = hexton(pgm_read_byte(hextext++)); /* record type */
b = (b << 4) + hexton(pgm_read_byte(hextext++));
cksum += b;

for (uint8_t i = 0; i < len; i++) {
  b = hexton(pgm_read_byte(hextext++));
  b = (b << 4) + hexton(pgm_read_byte(hextext++));
  if (addr - target_startaddr >= sizeof(target_code)) {
    error("Code extends beyond allowed range");
    break;
  }
  target_code[addr++ - target_startaddr] = b;
  cksum += b;

#if VERBOSE
Serial.print(b, HEX);
Serial.write(' ');
#endif
totlen++;
if (totlen >= sizeof(target_code)) {
error("Too much code");
break;
}
}
b = hexton(pgm_read_byte(hextext++)); /* checksum /
b = (b << 4) + hexton(pgm_read_byte(hextext++));
cksum += b;
if (cksum != 0) {
error("Bad checksum: ");
Serial.print(cksum, HEX);
}
if (pgm_read_byte(hextext++) != '\n') {
error("No end of line");
break;
}
#if VERBOSE
Serial.println();
#endif
}
fp(" Total bytes read: ");
Serial.println(totlen);
}

/

target_findimage

given target_type loaded with the relevant part of the device signature,
search the hex images that we have programmed in flash, looking for one
that matches.
*/

boolean target_findimage ()
{
const image_t ip;
fp("Searching for image...\n");
/

Search through our table of chip aliases first
*/
for (uint8_t i = 0; i < sizeof(aliases) / sizeof(aliases[0]); i++) {
const alias_t a = &aliases[i];
if (a->real_chipsig == target_type) {
fp(" Compatible bootloader for ");
Serial.println(a->alias_chipname);
target_type = a->alias_chipsig; /
Overwrite chip signature /
break;
}
}
/

Search through our table of self-contained images.
*/
for (uint8_t i = 0; i < sizeof(images) / sizeof(images[0]); i++) {
target_flashptr = ip = images[i];
if (ip && (pgm_read_word(&ip->image_chipsig) == target_type)) {
fp(" Found "");
flashprint(&ip->image_name[0]);
fp("" for ");
flashprint(&ip->image_chipname[0]);
fp("\n");
read_image(ip);
return true;
}
}
fp(" Not Found\n");
return (false);
}

/*
target_progfuses
given initialized target image data, re-program the fuses to allow
the optiboot image to be programmed.
*/

boolean target_progfuses ()
{
uint8_t f;
fp("\nSetting fuses for programming");

f = pgm_read_byte(&target_flashptr->image_progfuses[FUSE_PROT]);
if (f) {
fp("\n Lock: ");
Serial.print(f, HEX);
fp(" ");
Serial.print(spi_transaction(0xAC, 0xE0, 0x00, f), HEX);
}
f = pgm_read_byte(&target_flashptr->image_progfuses[FUSE_LOW]);
if (f) {
fp(" Low: ");
Serial.print(f, HEX);
fp(" ");
Serial.print(spi_transaction(0xAC, 0xA0, 0x00, f), HEX);
}
f = pgm_read_byte(&target_flashptr->image_progfuses[FUSE_HIGH]);
if (f) {
fp(" High: ");
Serial.print(f, HEX);
fp(" ");
Serial.print(spi_transaction(0xAC, 0xA8, 0x00, f), HEX);
}
f = pgm_read_byte(&target_flashptr->image_progfuses[FUSE_EXT]);
if (f) {
fp(" Ext: ");
Serial.print(f, HEX);
fp(" ");
Serial.print(spi_transaction(0xAC, 0xA4, 0x00, f), HEX);
}
Serial.println();
return true; /* */
}

/*
target_program
Actually program the image into the target chip
*/

boolean target_program ()
{
int l; /* actual length */

fp("\nProgramming bootloader: ");
here = target_startaddr >> 1; /* word address */
buff = target_code;
l = 512;
Serial.print(l, DEC);
fp(" bytes at 0x");
Serial.println(here, HEX);

spi_transaction(0xAC, 0x80, 0, 0); /* chip erase /
delay(1000);
if (write_flash(l) != STK_OK) {
error("\nFlash Write Failed");
return false;
}
return true; /
*/
}

/*
target_normfuses
reprogram the fuses to the state they should be in for bootloader
based programming
*/
boolean target_normfuses ()
{
uint8_t f;
fp("\nRestoring normal fuses");

f = pgm_read_byte(&target_flashptr->image_normfuses[FUSE_PROT]);
if (f) {
fp("\n Lock: ");
Serial.print(f, HEX);
fp(" ");
Serial.print(spi_transaction(0xAC, 0xE0, 0x00, f), HEX);
}
f = pgm_read_byte(&target_flashptr->image_normfuses[FUSE_LOW]);
if (f) {
fp(" Low: ");
Serial.print(f, HEX);
fp(" ");
Serial.print(spi_transaction(0xAC, 0xA0, 0x00, f), HEX);
}
f = pgm_read_byte(&target_flashptr->image_normfuses[FUSE_HIGH]);
if (f) {
fp(" High: ");
Serial.print(f, HEX);
fp(" ");
Serial.print(spi_transaction(0xAC, 0xA8, 0x00, f), HEX);
}
f = pgm_read_byte(&target_flashptr->image_normfuses[FUSE_EXT]);
if (f) {
fp(" Ext: ");
Serial.print(f, HEX);
fp(" ");
Serial.print(spi_transaction(0xAC, 0xA4, 0x00, f), HEX);
}
Serial.println();
return true; /* */
}

/*
target_poweron
Turn on power to the target chip (assuming that it is powered through
the relevant IO pin of THIS arduino.)
*/
boolean target_poweron ()
{
uint16_t result;

fp("Target power on! ...");
digitalWrite(POWER, LOW);
pinMode(POWER, OUTPUT);
digitalWrite(POWER, HIGH);
digitalWrite(RESET, LOW); // reset it right away.
pinMode(RESET, OUTPUT);
/*
Check if the target is pulling RESET HIGH by reverting to input
*/
delay(5);
pinMode(RESET, INPUT);
delay(1);
if (digitalRead(RESET) != HIGH) {
fp("No RESET pullup detected! - no target?");
return false;
}
pinMode(RESET, OUTPUT);

delay(200);
fp("\nStarting Program Mode");
result = start_pmode();
if ((result & 0xFF00) != 0x5300) {
fp(" - Failed, result = 0x");
Serial.print(result, HEX);
return false;
}
fp(" [OK]\n");
return true;
}

boolean target_poweroff ()
{
end_pmode();
digitalWrite(POWER, LOW);
delay(200);
pinMode(POWER, INPUT);
fp("\nTarget power OFF!\n");
return true;
}

void flash (uint8_t hilo, int addr, uint8_t data) {
#if VERBOSE
Serial.print(data, HEX);
fp(":");
Serial.print(spi_transaction(0x40 + 8 * hilo,
addr >> 8 & 0xFF,
addr & 0xFF,
data), HEX);
fp(" ");
#else
(void) spi_transaction(0x40 + 8 * hilo,
addr >> 8 & 0xFF,
addr & 0xFF,
data);
#endif
}

void commit (int addr) {
fp(" Commit Page: ");
Serial.print(addr, HEX);
fp(":");
Serial.println(spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0), HEX);
delay(100);
}

//#define _current_page(x) (here & 0xFFFFE0)
int current_page (int addr) {
if (target_pagesize == 32) return here & 0xFFFFFFF0;
if (target_pagesize == 64) return here & 0xFFFFFFE0;
if (target_pagesize == 128) return here & 0xFFFFFFC0;
return here;
}

uint8_t write_flash (int length) {
if (target_pagesize < 1) return STK_FAILED;
//if (target_pagesize != 64) return STK_FAILED;
int page = current_page(here);
int x = 0;
while (x < length) {
if (page != current_page(here)) {
commit(page);
page = current_page(here);
}
flash(LOW, here, buff[x]);
flash(HIGH, here, buff[x + 1]);
x += 2;
here++;
}

commit(page);

return STK_OK;
}

uint16_t read_signature () {
uint8_t sig_middle = spi_transaction(0x30, 0x00, 0x01, 0x00);
uint8_t sig_low = spi_transaction(0x30, 0x00, 0x02, 0x00);
return ((sig_middle << 8) + sig_low);
}

/*
Bootload images.
These are the intel Hex files produced by the optiboot makefile,
with a small amount of automatic editing to turn them into C strings,
and a header attched to identify them

Emacs keyboard macro:

  4*SPC			;; self-insert-command
  "			;; self-insert-command
  C-e			;; move-end-of-line
  \			;; self-insert-command
  n"			;; self-insert-command * 2
  C-n			;; next-line
  C-a			;; move-beginning-of-line

*/

const image_t PROGMEM image_328 = {
{
"optiboot_atmega328.hex"
}
,
{
"atmega328"
}
,
0x9514, /* Signature bytes for 328 (non-P) */
{
0x3F, 0xFF, 0xDE, 0x05, 0
}
,
{
0x2F, 0, 0, 0, 0
}
,
128,
{
":107E0000112484B714BE81FFF0D085E080938100F7\n"
":107E100082E08093C00088E18093C10086E0809377\n"
":107E2000C20080E18093C4008EE0C9D0259A86E02C\n"
":107E300020E33CEF91E0309385002093840096BBD3\n"
":107E4000B09BFECF1D9AA8958150A9F7CC24DD24C4\n"
":107E500088248394B5E0AB2EA1E19A2EF3E0BF2EE7\n"
":107E6000A2D0813461F49FD0082FAFD0023811F036\n"
":107E7000013811F484E001C083E08DD089C08234E0\n"
":107E800011F484E103C0853419F485E0A6D080C0E4\n"
":107E9000853579F488D0E82EFF2485D0082F10E0AE\n"
":107EA000102F00270E291F29000F111F8ED06801E7\n"
":107EB0006FC0863521F484E090D080E0DECF843638\n"
":107EC00009F040C070D06FD0082F6DD080E0C81688\n"
":107ED00080E7D80618F4F601B7BEE895C0E0D1E017\n"
":107EE00062D089930C17E1F7F0E0CF16F0E7DF06D8\n"
":107EF00018F0F601B7BEE89568D007B600FCFDCFD4\n"
":107F0000A601A0E0B1E02C9130E011968C91119780\n"
":107F100090E0982F8827822B932B1296FA010C0160\n"
":107F200087BEE89511244E5F5F4FF1E0A038BF0790\n"
":107F300051F7F601A7BEE89507B600FCFDCF97BE46\n"
":107F4000E89526C08437B1F42ED02DD0F82E2BD052\n"
":107F50003CD0F601EF2C8F010F5F1F4F84911BD097\n"
":107F6000EA94F801C1F70894C11CD11CFA94CF0C13\n"
":107F7000D11C0EC0853739F428D08EE10CD085E9AC\n"
":107F80000AD08FE07ACF813511F488E018D01DD067\n"
":107F900080E101D065CF982F8091C00085FFFCCF94\n"
":107FA0009093C60008958091C00087FFFCCF809118\n"
":107FB000C00084FD01C0A8958091C6000895E0E648\n"
":107FC000F0E098E1908380830895EDDF803219F02E\n"
":107FD00088E0F5DFFFCF84E1DECF1F93182FE3DFCA\n"
":107FE0001150E9F7F2DF1F91089580E0E8DFEE27F6\n"
":047FF000FF270994CA\n"
":027FFE00040479\n"
":0400000300007E007B\n"
":00000001FF\n"
}
};

const image_t PROGMEM image_328p = {
{
"optiboot_atmega328.hex"
}
,
{
"atmega328P"
}
,
0x950F, /* Signature bytes for 328P /
{
0x3F, 0xFF, 0xDE, 0x05, 0
}
,
{
0x2F, 0, 0, 0, 0
}
,
128,
{
":107E0000112484B714BE81FFF0D085E080938100F7\n"
":107E100082E08093C00088E18093C10086E0809377\n"
":107E2000C20080E18093C4008EE0C9D0259A86E02C\n"
":107E300020E33CEF91E0309385002093840096BBD3\n"
":107E4000B09BFECF1D9AA8958150A9F7CC24DD24C4\n"
":107E500088248394B5E0AB2EA1E19A2EF3E0BF2EE7\n"
":107E6000A2D0813461F49FD0082FAFD0023811F036\n"
":107E7000013811F484E001C083E08DD089C08234E0\n"
":107E800011F484E103C0853419F485E0A6D080C0E4\n"
":107E9000853579F488D0E82EFF2485D0082F10E0AE\n"
":107EA000102F00270E291F29000F111F8ED06801E7\n"
":107EB0006FC0863521F484E090D080E0DECF843638\n"
":107EC00009F040C070D06FD0082F6DD080E0C81688\n"
":107ED00080E7D80618F4F601B7BEE895C0E0D1E017\n"
":107EE00062D089930C17E1F7F0E0CF16F0E7DF06D8\n"
":107EF00018F0F601B7BEE89568D007B600FCFDCFD4\n"
":107F0000A601A0E0B1E02C9130E011968C91119780\n"
":107F100090E0982F8827822B932B1296FA010C0160\n"
":107F200087BEE89511244E5F5F4FF1E0A038BF0790\n"
":107F300051F7F601A7BEE89507B600FCFDCF97BE46\n"
":107F4000E89526C08437B1F42ED02DD0F82E2BD052\n"
":107F50003CD0F601EF2C8F010F5F1F4F84911BD097\n"
":107F6000EA94F801C1F70894C11CD11CFA94CF0C13\n"
":107F7000D11C0EC0853739F428D08EE10CD085E9AC\n"
":107F80000AD08FE07ACF813511F488E018D01DD067\n"
":107F900080E101D065CF982F8091C00085FFFCCF94\n"
":107FA0009093C60008958091C00087FFFCCF809118\n"
":107FB000C00084FD01C0A8958091C6000895E0E648\n"
":107FC000F0E098E1908380830895EDDF803219F02E\n"
":107FD00088E0F5DFFFCF84E1DECF1F93182FE3DFCA\n"
":107FE0001150E9F7F2DF1F91089580E0E8DFEE27F6\n"
":047FF000FF270994CA\n"
":027FFE00040479\n"
":0400000300007E007B\n"
":00000001FF\n"
}
};

const image_t PROGMEM image_168 = {
{
"optiboot_atmega168.hex"
}
,
{
"atmega168"
}
,
0x9406, /
Signature bytes for 168 /
{
0x3F, 0xC6, 0xDD, 0x04
}
,
{
0x2F, 0, 0, 0, 0
}
,
128,
{
":103E0000112484B714BE81FFF0D085E08093810037\n"
":103E100082E08093C00088E18093C10086E08093B7\n"
":103E2000C20080E18093C4008EE0C9D0259A86E06C\n"
":103E300020E33CEF91E0309385002093840096BB13\n"
":103E4000B09BFECF1D9AA8958150A9F7CC24DD2404\n"
":103E500088248394B5E0AB2EA1E19A2EF3E0BF2E27\n"
":103E6000A2D0813461F49FD0082FAFD0023811F076\n"
":103E7000013811F484E001C083E08DD089C0823420\n"
":103E800011F484E103C0853419F485E0A6D080C024\n"
":103E9000853579F488D0E82EFF2485D0082F10E0EE\n"
":103EA000102F00270E291F29000F111F8ED0680127\n"
":103EB0006FC0863521F484E090D080E0DECF843678\n"
":103EC00009F040C070D06FD0082F6DD080E0C816C8\n"
":103ED00088E3D80618F4F601B7BEE895C0E0D1E053\n"
":103EE00062D089930C17E1F7F0E0CF16F8E3DF0614\n"
":103EF00018F0F601B7BEE89568D007B600FCFDCF14\n"
":103F0000A601A0E0B1E02C9130E011968C911197C0\n"
":103F100090E0982F8827822B932B1296FA010C01A0\n"
":103F200087BEE89511244E5F5F4FF1E0A038BF07D0\n"
":103F300051F7F601A7BEE89507B600FCFDCF97BE86\n"
":103F4000E89526C08437B1F42ED02DD0F82E2BD092\n"
":103F50003CD0F601EF2C8F010F5F1F4F84911BD0D7\n"
":103F6000EA94F801C1F70894C11CD11CFA94CF0C53\n"
":103F7000D11C0EC0853739F428D08EE10CD084E9ED\n"
":103F80000AD086E07ACF813511F488E018D01DD0B0\n"
":103F900080E101D065CF982F8091C00085FFFCCFD4\n"
":103FA0009093C60008958091C00087FFFCCF809158\n"
":103FB000C00084FD01C0A8958091C6000895E0E688\n"
":103FC000F0E098E1908380830895EDDF803219F06E\n"
":103FD00088E0F5DFFFCF84E1DECF1F93182FE3DF0A\n"
":103FE0001150E9F7F2DF1F91089580E0E8DFEE2736\n"
":043FF000FF2709940A\n"
":023FFE000404B9\n"
":0400000300003E00BB\n"
":00000001FF\n"
}
};

const image_t PROGMEM image_8 = {
{
"optiboot_atmega8.hex"
}
,
{
"atmega8"
}
,
0x9307, /
Signature bytes for 8 /
{
0x3F, 0xBF, 0xCC, 0, 0
}
,
{
0x2F, 0xBF, 0xCC, 0, 0
}
,
64,
{
":101E000011248FE594E09EBF8DBF84B714BE81FF7F\n"
":101E1000E2D085E08EBD82E08BB988E18AB986E8A0\n"
":101E200080BD80E189B98EE0C2D0BD9A96E020E302\n"
":101E30003CEF54E040E23DBD2CBD58BF08B602FE69\n"
":101E4000FDCF88B3842788BBA8959150A1F7CC24F7\n"
":101E5000DD2488248394B5E0AB2EA1E19A2EF3E033\n"
":101E6000BF2E9ED0813461F49BD0082FA4D00238BD\n"
":101E700011F0013811F484E001C083E08DD089C0F5\n"
":101E8000823411F484E103C0853419F485E09BD0D9\n"
":101E900080C0853579F484D0E82EFF2481D0082FC6\n"
":101EA00010E0102F00270E291F29000F111F83D0CB\n"
":101EB00068016FC0863521F484E085D080E0DECFF4\n"
":101EC000843609F040C06CD06BD0082F69D080E018\n"
":101ED000C81688E1D80618F4F601B7BEE895C0E048\n"
":101EE000D1E05ED089930C17E1F7F0E0CF16F8E16E\n"
":101EF000DF0618F0F601B7BEE8955DD007B600FC26\n"
":101F0000FDCFA601A0E0B1E02C9130E011968C91BC\n"
":101F1000119790E0982F8827822B932B1296FA0125\n"
":101F20000C0187BEE89511244E5F5F4FF1E0A034AD\n"
":101F3000BF0751F7F601A7BEE89507B600FCFDCF35\n"
":101F400097BEE89526C08437B1F42AD029D0F82E60\n"
":101F500027D031D0F601EF2C8F010F5F1F4F8491F6\n"
":101F60001BD0EA94F801C1F70894C11CD11CFA9463\n"
":101F7000CF0CD11C0EC0853739F41DD08EE10CD0AA\n"
":101F800083E90AD087E07ACF813511F488E00FD059\n"
":101F900012D080E101D065CF5D9BFECF8CB9089552\n"
":101FA0005F9BFECF5C9901C0A8958CB1089598E124\n"
":101FB00091BD81BD0895F4DF803219F088E0F7DF2C\n"
":101FC000FFCF84E1E9CF1F93182FEADF1150E9F723\n"
":101FD000F2DF1F91089580E0EADFEE27FF270994E2\n"
":021FFE000404D9\n"
":0400000300001E00DB\n"
":00000001FF\n"
}
};
const image_t PROGMEM image_64 = {
{
"optiboot_atmega64.hex"
}
,
{
"atmega64"
}
,
0x1E9602, /
Signature bytes for ATmega64 /
{
0xFF, 0xDC, 0xC0, 0, 0 /
Example low, high, and extended fuse settings /
}
,
{
0xEF, 0xDF, 0xC0, 0, 0 /
Example extended fuse settings /
}
,
64, /
Bootloader size in bytes */
{
":200000000C94A6000C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B80032\n"
":200020000C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B80000\n"
":200040000C9498010C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B800FF\n"
":200060000C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B800C0\n"
":200080000C94B8000C94B8000C94B80000003A0037003400310022006100640000003B0060\n"
":2000A000380035003200230062006500050505050505050502020202020202020707040469\n"
":2000C0000404040404040707030303030303030307010101010101010106060606060606A9\n"
":2000E0000601020408102040800102040810204080081001020408102040800102010204DB\n"
":20010000081020408004804020100804020101020408102040800000000A0B0C00000000C4\n"
":200120000000010405060000000000000000000000000000000000000000000000000000AF\n"
":2001400000000000000000000000000011241FBECFEFD0E1DEBFCDBF21E0A0E0B1E001C022\n"
":200160001D92A630B207E1F70E94DF010C9442020C940000EEE3F1E02491E9E0F1E03491AD\n"
":20018000E4EDF0E09491992359F12223C1F021502C30A8F4E22FF0E0E053FF4F0C942D0203\n"
":2001A00009010901DF00DC00F100F400F700DF00DF00FB00010105012FB52F772FBDE92F45\n"
":2001C000F0E0EE0FFF1FE456FF4FA591B4919FB7F894EC91811121C030953E233C939FBF0C\n"
":2001E00008952FB52F7DEACF2FB5277FE7CF25B52F7D25BDE4CF20918B002F7720938B009E\n"
":20020000DECF20918B002F7DF9CF20918B00277FF5CF23B72F7D23BFD2CF3E2BDFCFCF925A\n"
":20022000DF92EF92FF926FB7F8948091020190910301A0910401B09105015091010122B717\n"
":2002400036B7432F417030FF04C041E02F3F09F440E06FBF6C017D0137E0CC0CDD1CEE1CE4\n"
":20026000FF1C3A95D1F7C50ED11CE11CF11CC81AD90AEA0AFB0A880F991FAA1FBB1FC81A70\n"
":20028000D90AEA0AFB0A63E0CC0CDD1CEE1CFF1C6A95D1F730E0A9ECB5E00E943302672FDB\n"
":2002A000782F892F99276C0D7D1D8E1D9F1D442321F067537A4F8F4F9F4FFF90EF90DF9061\n"
":2002C000CF9008958F929F92AF92BF92CF92DF92EF92FF920E940F014B015C0188EEC82E93\n"
":2002E00083E0D82EE12CF12C0E940F01681979098A099B09683E734081059105A8F321E06E\n"
":20030000C21AD108E108F10888EE880E83E0981EA11CB11CC114D104E104F10429F7FF9064\n"
":20032000EF90DF90CF90BF90AF909F908F9008951F920F920FB60F9211244F935F936F9334\n"
":200340007F938F939F934091020150910301609104017091050180910101909100019A3181\n"
":2003600019F51092000190910001953008F1845C8D3700F18D574E5F5F4F6F4F7F4F809379\n"
":200380000101409302015093030160930401709305019F918F917F916F915F914F910F90CE\n"
":2003A0000FBE0F901F9018959F5F90930001DBCF835CDECF4F5F5F4F6F4F7F4FE0CF78947A\n"
":2003C00083B78C6483BF87B7816087BF82E08EBD8EB581608EBD8FB581608FBD85B58460A1\n"
":2003E00085BD85B5806485BD80918A00836080938A0080918B00816080938B0086E886B978\n"
":200400001AB8E9E0F1E02491E4EDF0E08491882399F090E0880F991FFC01E457FF4FA59156\n"
":20042000B491FC01E456FF4F859194918FB7F894EC91E22BEC938FBFC0E0D0E081E00E943B\n"
":20044000BA000E94620180E00E94BA000E9462012097A1F30E940000F1CFEE0FFF1F0590BF\n"
":20046000F491E02D0994A29FB001B39FC001A39F700D811D1124911DB29F700D811D112467\n"
":08048000911D0895F894FFCFCF\n"
":00000001FF\n"

}
};`

I have a program named optiLoader which loads micro atmega 8 with its bootloader. I want to change this program so that it loads the hex file on micro atmega 64 using Arduino. I changed the program as below, but the hex file is complete. It doesn't work. Please help me to put the hex file on the micro atmega 64 with Arduino

کد را در اینجا بنویسید یا بچسبانید// optiLoader.pde
//
// this sketch allows an Arduino to program Optiboot onto any other
// Arduino-like device containing ATmega8, ATmega168, or ATmega328
// microcontroller chips.
//
// Copyright (c) 2011, 2015 by Bill Westfield ("WestfW")

//-------------------------------------------------------------------------------------
// "MIT Open Source Software License":
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in the
// Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//-------------------------------------------------------------------------------------

//
// this sketch allows an Arduino to program Optiboot onto any other
// Arduino-like device containing ATmega8, ATmega168, or ATmega328
// microcontroller chips.
//
// It is based on AVRISP
//
// Designed to connect to a generic programming cable,
// using the following pins:
// 10: slave reset
// 11: MOSI
// 12: MISO
// 13: SCK
//  9: Power to external chip.
//     This is a little questionable, since the power it is legal to draw
//     from a PIC pin is pretty close to the power consumption of an AVR
//     chip being programmed.  But it permits the target to be entirely
//     powered down for safe reconnection of the programmer to additional
//     targets, and it seems to work for most Arduinos.  If the target board
//     contains additional circuitry and is expected to draw more than 40mA,
//     connect the target power to a stronger source of +5V.  Do not use pin
//     9 to power more complex Arduino boards that draw more than 40mA, such
//     as the Arduino Uno Ethernet !
//
// If the aim is to reprogram the bootloader in one Arduino using another
// Arudino as the programmer, you can just use jumpers between the connectors
// on the Arduino board.  In this case, connect:
// Pin 13 to Pin 13
// Pin 12 to Pin 12
// Pin 11 to Pin 11
// Pin 10 (of "programmer") to RESET (of "target" (on the "power" connector))
// +5V to +5V and GND to GND.  Only the "programmer" board should be powered
//     by USB or external power.
//
// ----------------------------------------------------------------------

// The following credits are from AVRISP.  It turns out that there isn't
// a lot of AVRISP left in this sketch, but probably if AVRISP had never
// existed,  this sketch would not have been written.
//
// October 2009 by David A. Mellis
// - Added support for the read signature command
//
// February 2009 by Randall Bohn
// - Added support for writing to EEPROM (what took so long?)
// Windows users should consider WinAVR's avrdude instead of the
// avrdude included with Arduino software.
//
// January 2008 by Randall Bohn
// - Thanks to Amplificar for helping me with the STK500 protocol
// - The AVRISP/STK500 (mk I) protocol is used in the arduino bootloader
// - The SPI functions herein were developed for the AVR910_ARD programmer
// - More information at http://code.google.com/p/mega-isp


#include <avr/pgmspace.h>
#include "optiLoader.h"

char Arduino_preprocessor_hint;

/*
   Pins to target
*/
#define SCK 13
#define MISO 12
#define MOSI 11
#define RESET 10
#define POWER 9

// STK Definitions; we can still use these as return codes
#define STK_OK 0x10
#define STK_FAILED 0x11


// Useful message printing definitions
#define fp(string) flashprint(PSTR(string));
#define debug(string) // flashprint(PSTR(string));
#define error(string) flashprint(PSTR(string));

// Forward references
void pulse(int pin, int times);
void read_image(const image_t *ip);

// Global Variables

/*
   Table of defined images
*/
const image_t * images[] = {
  &image_328, &image_328p, &image_168, &image_8,&image_64, 0
};

/*
   Table of "Aliases."  Chips that are effectively the same as chips
   that we have a bootloader for.  These work by simply overriding the
   signature read with the signature of the chip we "know."
*/
const alias_t aliases[] = {
  { "ATmega168PA", 0x940B, 0x9406 },	/* Treat 168P same as 168 */
  { "ATmega168PB", 0x9415, 0x9406 },	/* Treat 168PB same as 168 */
  { "ATmega64", 0x1E9602, 0x1E9602 }, 
  { "ATmega328PB", 0x9516, 0x950F },	/* Treat 328PB same as 328P */
  { "ATmega328",   0x9514, 0x950F },	/* Treat 328 same as 328P */
};

int pmode = 0;
// address for reading and writing, set by 'U' command
int here;

uint16_t target_type = 0;		/* type of target_cpu */
uint16_t target_startaddr;
uint8_t target_pagesize;       /* Page size for flash programming (bytes) */
uint8_t *buff;

const image_t *target_flashptr; 	       /* pointer to target info in flash */
uint8_t target_code[512];	       /* The whole code */

void setup (void) {
  Serial.begin(19200); 			/* Initialize serial for status msgs */
  pinMode(13, OUTPUT); 			/* Blink the pin13 LED a few times */
#ifdef PIN_SPI_SS
#if PIN_SPI_SS != RESET
  // on non-AtmegaXX8 boards (MEGA, Leonardo, etc) the SPI SS pin is NOT pin 10,
  // and although SS is driven manually (RESET to the target), SS should not be
  // allowed to default to INPUT and floating, or the SPI hardware may decide that
  // some other SPI master is trying to use the bus.  (See Datasheet SS description.)
  pinMode(PIN_SPI_SS, INPUT_PULLUP);
#endif
#endif
  pulse(13, 20);
}

void loop (void) {
  fp("\nOptiLoader Bootstrap programmer.\n2011 by Bill Westfield (WestfW)\n\n");
  if (target_poweron()) {		/* Turn on target power */
    do {
      if (!target_identify()) 		/* Figure out what kind of CPU */
        break;
      if (!target_findimage())		/* look for an image */
        break;
      if (!target_progfuses())		/* get fuses ready to program */
        break;
      if (!target_program()) 		/* Program the image */
        break;
      (void) target_normfuses(); 	/* reset fuses to normal mode */
    }
    while (0);
  }
  else {
    Serial.println();
  }
  target_poweroff(); 			/* turn power off */

  fp ("\nType 'G' or hit RESET for next chip\n")
  while (1) {
    if (Serial.read() == 'G')
      break;
  }
}

/*
   Low level support functions
*/

/*
   flashprint
   print a text string direct from flash memory to Serial
*/
void flashprint (const char p[])
{
  uint8_t c;
  while (0 != (c = pgm_read_byte(p++))) {
    Serial.write(c);
  }
}

/*
   hexton
   Turn a Hex digit (0..9, A..F) into the equivalent binary value (0-16)
*/
uint8_t hexton (uint8_t h)
{
  if (h >= '0' && h <= '9')
    return (h - '0');
  if (h >= 'A' && h <= 'F')
    return ((h - 'A') + 10);
  error("Bad hex digit!");
  return (0);
}

/*
   pulse
   turn a pin on and off a few times; indicates life via LED
*/
#define PTIME 30
void pulse (int pin, int times) {
  do {
    digitalWrite(pin, HIGH);
    delay(PTIME);
    digitalWrite(pin, LOW);
    delay(PTIME);
  }
  while (times--);
}

/*
   spi_init
   initialize the AVR SPI peripheral
*/
void spi_init (void) {
  uint8_t x;
  SPCR = 0x53;  // SPIE | MSTR | SPR1 | SPR0
  x = SPSR;
  x = SPDR;
}

/*
   spi_wait
   wait for SPI transfer to complete
*/
void spi_wait (void) {
  debug("spi_wait");
  do {
  }
  while (!(SPSR & (1 << SPIF)));
}

/*
   spi_send
   send a byte via SPI, wait for the transfer.
*/
uint8_t spi_send (uint8_t b) {
  uint8_t reply;
  SPDR = b;
  spi_wait();
  reply = SPDR;
  return reply;
}


/*
   Functions specific to ISP programming of an AVR
*/

/*
   target_identify
   read the signature bytes (if possible) and check whether it's
   a legal value (atmega8, atmega168, atmega328)
*/

boolean target_identify ()
{
  boolean result;
  target_type = 0;
  fp("\nReading signature:");
  target_type = read_signature();
  if (target_type == 0 || target_type == 0xFFFF) {
    fp(" Bad value: ");
    result = false;
  }
  else {
    result = true;
  }
  Serial.println(target_type, HEX);
  if (target_type == 0) {
    fp("  (no target attached?)\n");
  }
  return result;
}

unsigned long spi_transaction (uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
  uint8_t n, m;
  spi_send(a);
  n = spi_send(b);
  //if (n != a) error = -1;
  m = spi_send(c);
  return 0xFFFFFF & ((((uint32_t)n) << 16) + (m << 8) + spi_send(d));
}

uint16_t start_pmode () {
  uint16_t result;

  pinMode(13, INPUT); // restore to default
  spi_init();
  debug("...spi_init done");
  // following delays may not work on all targets...
  pinMode(RESET, OUTPUT);
  digitalWrite(RESET, HIGH);
  pinMode(SCK, OUTPUT);
  digitalWrite(SCK, LOW);
  delay(50);
  digitalWrite(RESET, LOW);
  delay(50);
  pinMode(MISO, INPUT);
  pinMode(MOSI, OUTPUT);
  debug("...spi_transaction");
  result = spi_transaction(0xAC, 0x53, 0x00, 0x00);
  debug("...Done");
  pmode = 1;
  return result;
}

void end_pmode (void) {
  SPCR = 0; 				/* reset SPI */
  digitalWrite(MISO, 0); 		/* Make sure pullups are off too */
  pinMode(MISO, INPUT);
  digitalWrite(MOSI, 0);
  pinMode(MOSI, INPUT);
  digitalWrite(SCK, 0);
  pinMode(SCK, INPUT);
  digitalWrite(RESET, 0);
  pinMode(RESET, INPUT);
  pmode = 0;
}

/*
   read_image

   Read an intel hex image from a string in pgm memory.
   We assume that the image does not exceed the 512 bytes that we have
   allowed for it to have.  that would be bad.
   Also read other data from the image, such as fuse and protecttion byte
   values during programming, and for after we're done.
*/
void read_image (const image_t *ip)
{
  uint16_t len, totlen = 0, addr;
  const char *hextext = &ip->image_hexcode[0];
  target_startaddr = 0;
  target_pagesize = pgm_read_byte(&ip->image_pagesize);
  uint8_t b, cksum = 0;

  while (1) {
    if (pgm_read_byte(hextext++) != ':') {
      error("No colon");
      break;
    }
    len = hexton(pgm_read_byte(hextext++));
    len = (len << 4) + hexton(pgm_read_byte(hextext++));
    cksum = len;

    b = hexton(pgm_read_byte(hextext++)); /* record type */
    b = (b << 4) + hexton(pgm_read_byte(hextext++));
    cksum += b;
    addr = b;
    b = hexton(pgm_read_byte(hextext++)); /* record type */
    b = (b << 4) + hexton(pgm_read_byte(hextext++));
    cksum += b;
    addr = (addr << 8) + b;
    if (target_startaddr == 0) {
      target_startaddr = addr;
      fp("  Start address at ");
      Serial.println(addr, HEX);
    }
    else if (addr == 0) {
      break;
    }

    b = hexton(pgm_read_byte(hextext++)); /* record type */
    b = (b << 4) + hexton(pgm_read_byte(hextext++));
    cksum += b;

    for (uint8_t i = 0; i < len; i++) {
      b = hexton(pgm_read_byte(hextext++));
      b = (b << 4) + hexton(pgm_read_byte(hextext++));
      if (addr - target_startaddr >= sizeof(target_code)) {
        error("Code extends beyond allowed range");
        break;
      }
      target_code[addr++ - target_startaddr] = b;
      cksum += b;
#if VERBOSE
      Serial.print(b, HEX);
      Serial.write(' ');
#endif
      totlen++;
      if (totlen >= sizeof(target_code)) {
        error("Too much code");
        break;
      }
    }
    b = hexton(pgm_read_byte(hextext++)); /* checksum */
    b = (b << 4) + hexton(pgm_read_byte(hextext++));
    cksum += b;
    if (cksum != 0) {
      error("Bad checksum: ");
      Serial.print(cksum, HEX);
    }
    if (pgm_read_byte(hextext++) != '\n') {
      error("No end of line");
      break;
    }
#if VERBOSE
    Serial.println();
#endif
  }
  fp("  Total bytes read: ");
  Serial.println(totlen);
}

/*
   target_findimage

   given target_type loaded with the relevant part of the device signature,
   search the hex images that we have programmed in flash, looking for one
   that matches.
*/

boolean target_findimage ()
{
  const image_t *ip;
  fp("Searching for image...\n");
  /*
     Search through our table of chip aliases first
  */
  for (uint8_t i = 0; i < sizeof(aliases) / sizeof(aliases[0]); i++) {
    const alias_t *a = &aliases[i];
    if (a->real_chipsig == target_type) {
      fp("  Compatible bootloader for ");
      Serial.println(a->alias_chipname);
      target_type = a->alias_chipsig;  /* Overwrite chip signature */
      break;
    }
  }
  /*
     Search through our table of self-contained images.
  */
  for (uint8_t i = 0; i < sizeof(images) / sizeof(images[0]); i++) {
    target_flashptr = ip = images[i];
    if (ip && (pgm_read_word(&ip->image_chipsig) == target_type)) {
      fp("  Found \"");
      flashprint(&ip->image_name[0]);
      fp("\" for ");
      flashprint(&ip->image_chipname[0]);
      fp("\n");
      read_image(ip);
      return true;
    }
  }
  fp(" Not Found\n");
  return (false);
}

/*
   target_progfuses
   given initialized target image data, re-program the fuses to allow
   the optiboot image to be programmed.
*/

boolean target_progfuses ()
{
  uint8_t f;
  fp("\nSetting fuses for programming");

  f = pgm_read_byte(&target_flashptr->image_progfuses[FUSE_PROT]);
  if (f) {
    fp("\n  Lock: ");
    Serial.print(f, HEX);
    fp(" ");
    Serial.print(spi_transaction(0xAC, 0xE0, 0x00, f), HEX);
  }
  f = pgm_read_byte(&target_flashptr->image_progfuses[FUSE_LOW]);
  if (f) {
    fp("  Low: ");
    Serial.print(f, HEX);
    fp(" ");
    Serial.print(spi_transaction(0xAC, 0xA0, 0x00, f), HEX);
  }
  f = pgm_read_byte(&target_flashptr->image_progfuses[FUSE_HIGH]);
  if (f) {
    fp("  High: ");
    Serial.print(f, HEX);
    fp(" ");
    Serial.print(spi_transaction(0xAC, 0xA8, 0x00, f), HEX);
  }
  f = pgm_read_byte(&target_flashptr->image_progfuses[FUSE_EXT]);
  if (f) {
    fp("  Ext: ");
    Serial.print(f, HEX);
    fp(" ");
    Serial.print(spi_transaction(0xAC, 0xA4, 0x00, f), HEX);
  }
  Serial.println();
  return true; 			/* */
}

/*
   target_program
   Actually program the image into the target chip
*/

boolean target_program ()
{
  int l; 				/* actual length */

  fp("\nProgramming bootloader: ");
  here = target_startaddr >> 1; 		/* word address */
  buff = target_code;
  l = 512;
  Serial.print(l, DEC);
  fp(" bytes at 0x");
  Serial.println(here, HEX);

  spi_transaction(0xAC, 0x80, 0, 0); 	/* chip erase */
  delay(1000);
  if (write_flash(l) != STK_OK) {
    error("\nFlash Write Failed");
    return false;
  }
  return true; 			/*  */
}

/*
   target_normfuses
   reprogram the fuses to the state they should be in for bootloader
   based programming
*/
boolean target_normfuses ()
{
  uint8_t f;
  fp("\nRestoring normal fuses");

  f = pgm_read_byte(&target_flashptr->image_normfuses[FUSE_PROT]);
  if (f) {
    fp("\n  Lock: ");
    Serial.print(f, HEX);
    fp(" ");
    Serial.print(spi_transaction(0xAC, 0xE0, 0x00, f), HEX);
  }
  f = pgm_read_byte(&target_flashptr->image_normfuses[FUSE_LOW]);
  if (f) {
    fp("  Low: ");
    Serial.print(f, HEX);
    fp(" ");
    Serial.print(spi_transaction(0xAC, 0xA0, 0x00, f), HEX);
  }
  f = pgm_read_byte(&target_flashptr->image_normfuses[FUSE_HIGH]);
  if (f) {
    fp("  High: ");
    Serial.print(f, HEX);
    fp(" ");
    Serial.print(spi_transaction(0xAC, 0xA8, 0x00, f), HEX);
  }
  f = pgm_read_byte(&target_flashptr->image_normfuses[FUSE_EXT]);
  if (f) {
    fp("  Ext: ");
    Serial.print(f, HEX);
    fp(" ");
    Serial.print(spi_transaction(0xAC, 0xA4, 0x00, f), HEX);
  }
  Serial.println();
  return true; 			/* */
}

/*
   target_poweron
   Turn on power to the target chip (assuming that it is powered through
   the relevant IO pin of THIS arduino.)
*/
boolean target_poweron ()
{
  uint16_t result;

  fp("Target power on! ...");
  digitalWrite(POWER, LOW);
  pinMode(POWER, OUTPUT);
  digitalWrite(POWER, HIGH);
  digitalWrite(RESET, LOW);  // reset it right away.
  pinMode(RESET, OUTPUT);
  /*
     Check if the target is pulling RESET HIGH by reverting to input
  */
  delay(5);
  pinMode(RESET, INPUT);
  delay(1);
  if (digitalRead(RESET) != HIGH) {
    fp("No RESET pullup detected! - no target?");
    return false;
  }
  pinMode(RESET, OUTPUT);

  delay(200);
  fp("\nStarting Program Mode");
  result = start_pmode();
  if ((result & 0xFF00) != 0x5300) {
    fp(" - Failed, result = 0x");
    Serial.print(result, HEX);
    return false;
  }
  fp(" [OK]\n");
  return true;
}

boolean target_poweroff ()
{
  end_pmode();
  digitalWrite(POWER, LOW);
  delay(200);
  pinMode(POWER, INPUT);
  fp("\nTarget power OFF!\n");
  return true;
}

void flash (uint8_t hilo, int addr, uint8_t data) {
#if VERBOSE
  Serial.print(data, HEX);
  fp(":");
  Serial.print(spi_transaction(0x40 + 8 * hilo,
                               addr >> 8 & 0xFF,
                               addr & 0xFF,
                               data), HEX);
  fp(" ");
#else
  (void) spi_transaction(0x40 + 8 * hilo,
                         addr >> 8 & 0xFF,
                         addr & 0xFF,
                         data);
#endif
}

void commit (int addr) {
  fp("  Commit Page: ");
  Serial.print(addr, HEX);
  fp(":");
  Serial.println(spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0), HEX);
  delay(100);
}

//#define _current_page(x) (here & 0xFFFFE0)
int current_page (int addr) {
  if (target_pagesize == 32) return here & 0xFFFFFFF0;
  if (target_pagesize == 64) return here & 0xFFFFFFE0;
  if (target_pagesize == 128) return here & 0xFFFFFFC0;
  return here;
}

uint8_t write_flash (int length) {
  if (target_pagesize < 1) return STK_FAILED;
  //if (target_pagesize != 64) return STK_FAILED;
  int page = current_page(here);
  int x = 0;
  while (x < length) {
    if (page != current_page(here)) {
      commit(page);
      page = current_page(here);
    }
    flash(LOW, here, buff[x]);
    flash(HIGH, here, buff[x + 1]);
    x += 2;
    here++;
  }

  commit(page);

  return STK_OK;
}

uint16_t read_signature () {
  uint8_t sig_middle = spi_transaction(0x30, 0x00, 0x01, 0x00);
  uint8_t sig_low = spi_transaction(0x30, 0x00, 0x02, 0x00);
  return ((sig_middle << 8) + sig_low);
}

/*
   Bootload images.
   These are the intel Hex files produced by the optiboot makefile,
   with a small amount of automatic editing to turn them into C strings,
   and a header attched to identify them

   Emacs keyboard macro:

      4*SPC			;; self-insert-command
      "			;; self-insert-command
      C-e			;; move-end-of-line
      \			;; self-insert-command
      n"			;; self-insert-command * 2
      C-n			;; next-line
      C-a			;; move-beginning-of-line

*/


const image_t PROGMEM image_328 = {
  {
    "optiboot_atmega328.hex"
  }
  ,
  {
    "atmega328"
  }
  ,
  0x9514,				/* Signature bytes for 328 (non-P) */
  {
    0x3F, 0xFF, 0xDE, 0x05, 0
  }
  ,
  {
    0x2F, 0, 0, 0, 0
  }
  ,
  128,
  {
    ":107E0000112484B714BE81FFF0D085E080938100F7\n"
    ":107E100082E08093C00088E18093C10086E0809377\n"
    ":107E2000C20080E18093C4008EE0C9D0259A86E02C\n"
    ":107E300020E33CEF91E0309385002093840096BBD3\n"
    ":107E4000B09BFECF1D9AA8958150A9F7CC24DD24C4\n"
    ":107E500088248394B5E0AB2EA1E19A2EF3E0BF2EE7\n"
    ":107E6000A2D0813461F49FD0082FAFD0023811F036\n"
    ":107E7000013811F484E001C083E08DD089C08234E0\n"
    ":107E800011F484E103C0853419F485E0A6D080C0E4\n"
    ":107E9000853579F488D0E82EFF2485D0082F10E0AE\n"
    ":107EA000102F00270E291F29000F111F8ED06801E7\n"
    ":107EB0006FC0863521F484E090D080E0DECF843638\n"
    ":107EC00009F040C070D06FD0082F6DD080E0C81688\n"
    ":107ED00080E7D80618F4F601B7BEE895C0E0D1E017\n"
    ":107EE00062D089930C17E1F7F0E0CF16F0E7DF06D8\n"
    ":107EF00018F0F601B7BEE89568D007B600FCFDCFD4\n"
    ":107F0000A601A0E0B1E02C9130E011968C91119780\n"
    ":107F100090E0982F8827822B932B1296FA010C0160\n"
    ":107F200087BEE89511244E5F5F4FF1E0A038BF0790\n"
    ":107F300051F7F601A7BEE89507B600FCFDCF97BE46\n"
    ":107F4000E89526C08437B1F42ED02DD0F82E2BD052\n"
    ":107F50003CD0F601EF2C8F010F5F1F4F84911BD097\n"
    ":107F6000EA94F801C1F70894C11CD11CFA94CF0C13\n"
    ":107F7000D11C0EC0853739F428D08EE10CD085E9AC\n"
    ":107F80000AD08FE07ACF813511F488E018D01DD067\n"
    ":107F900080E101D065CF982F8091C00085FFFCCF94\n"
    ":107FA0009093C60008958091C00087FFFCCF809118\n"
    ":107FB000C00084FD01C0A8958091C6000895E0E648\n"
    ":107FC000F0E098E1908380830895EDDF803219F02E\n"
    ":107FD00088E0F5DFFFCF84E1DECF1F93182FE3DFCA\n"
    ":107FE0001150E9F7F2DF1F91089580E0E8DFEE27F6\n"
    ":047FF000FF270994CA\n"
    ":027FFE00040479\n"
    ":0400000300007E007B\n"
    ":00000001FF\n"
  }
};

const image_t PROGMEM image_328p = {
  {
    "optiboot_atmega328.hex"
  }
  ,
  {
    "atmega328P"
  }
  ,
  0x950F,				/* Signature bytes for 328P */
  {
    0x3F, 0xFF, 0xDE, 0x05, 0
  }
  ,
  {
    0x2F, 0, 0, 0, 0
  }
  ,
  128,
  {
    ":107E0000112484B714BE81FFF0D085E080938100F7\n"
    ":107E100082E08093C00088E18093C10086E0809377\n"
    ":107E2000C20080E18093C4008EE0C9D0259A86E02C\n"
    ":107E300020E33CEF91E0309385002093840096BBD3\n"
    ":107E4000B09BFECF1D9AA8958150A9F7CC24DD24C4\n"
    ":107E500088248394B5E0AB2EA1E19A2EF3E0BF2EE7\n"
    ":107E6000A2D0813461F49FD0082FAFD0023811F036\n"
    ":107E7000013811F484E001C083E08DD089C08234E0\n"
    ":107E800011F484E103C0853419F485E0A6D080C0E4\n"
    ":107E9000853579F488D0E82EFF2485D0082F10E0AE\n"
    ":107EA000102F00270E291F29000F111F8ED06801E7\n"
    ":107EB0006FC0863521F484E090D080E0DECF843638\n"
    ":107EC00009F040C070D06FD0082F6DD080E0C81688\n"
    ":107ED00080E7D80618F4F601B7BEE895C0E0D1E017\n"
    ":107EE00062D089930C17E1F7F0E0CF16F0E7DF06D8\n"
    ":107EF00018F0F601B7BEE89568D007B600FCFDCFD4\n"
    ":107F0000A601A0E0B1E02C9130E011968C91119780\n"
    ":107F100090E0982F8827822B932B1296FA010C0160\n"
    ":107F200087BEE89511244E5F5F4FF1E0A038BF0790\n"
    ":107F300051F7F601A7BEE89507B600FCFDCF97BE46\n"
    ":107F4000E89526C08437B1F42ED02DD0F82E2BD052\n"
    ":107F50003CD0F601EF2C8F010F5F1F4F84911BD097\n"
    ":107F6000EA94F801C1F70894C11CD11CFA94CF0C13\n"
    ":107F7000D11C0EC0853739F428D08EE10CD085E9AC\n"
    ":107F80000AD08FE07ACF813511F488E018D01DD067\n"
    ":107F900080E101D065CF982F8091C00085FFFCCF94\n"
    ":107FA0009093C60008958091C00087FFFCCF809118\n"
    ":107FB000C00084FD01C0A8958091C6000895E0E648\n"
    ":107FC000F0E098E1908380830895EDDF803219F02E\n"
    ":107FD00088E0F5DFFFCF84E1DECF1F93182FE3DFCA\n"
    ":107FE0001150E9F7F2DF1F91089580E0E8DFEE27F6\n"
    ":047FF000FF270994CA\n"
    ":027FFE00040479\n"
    ":0400000300007E007B\n"
    ":00000001FF\n"
  }
};

const image_t PROGMEM image_168 = {
  {
    "optiboot_atmega168.hex"
  }
  ,
  {
    "atmega168"
  }
  ,
  0x9406,				/* Signature bytes for 168 */
  {
    0x3F, 0xC6, 0xDD, 0x04
  }
  ,
  {
    0x2F, 0, 0, 0, 0
  }
  ,
  128,
  {
    ":103E0000112484B714BE81FFF0D085E08093810037\n"
    ":103E100082E08093C00088E18093C10086E08093B7\n"
    ":103E2000C20080E18093C4008EE0C9D0259A86E06C\n"
    ":103E300020E33CEF91E0309385002093840096BB13\n"
    ":103E4000B09BFECF1D9AA8958150A9F7CC24DD2404\n"
    ":103E500088248394B5E0AB2EA1E19A2EF3E0BF2E27\n"
    ":103E6000A2D0813461F49FD0082FAFD0023811F076\n"
    ":103E7000013811F484E001C083E08DD089C0823420\n"
    ":103E800011F484E103C0853419F485E0A6D080C024\n"
    ":103E9000853579F488D0E82EFF2485D0082F10E0EE\n"
    ":103EA000102F00270E291F29000F111F8ED0680127\n"
    ":103EB0006FC0863521F484E090D080E0DECF843678\n"
    ":103EC00009F040C070D06FD0082F6DD080E0C816C8\n"
    ":103ED00088E3D80618F4F601B7BEE895C0E0D1E053\n"
    ":103EE00062D089930C17E1F7F0E0CF16F8E3DF0614\n"
    ":103EF00018F0F601B7BEE89568D007B600FCFDCF14\n"
    ":103F0000A601A0E0B1E02C9130E011968C911197C0\n"
    ":103F100090E0982F8827822B932B1296FA010C01A0\n"
    ":103F200087BEE89511244E5F5F4FF1E0A038BF07D0\n"
    ":103F300051F7F601A7BEE89507B600FCFDCF97BE86\n"
    ":103F4000E89526C08437B1F42ED02DD0F82E2BD092\n"
    ":103F50003CD0F601EF2C8F010F5F1F4F84911BD0D7\n"
    ":103F6000EA94F801C1F70894C11CD11CFA94CF0C53\n"
    ":103F7000D11C0EC0853739F428D08EE10CD084E9ED\n"
    ":103F80000AD086E07ACF813511F488E018D01DD0B0\n"
    ":103F900080E101D065CF982F8091C00085FFFCCFD4\n"
    ":103FA0009093C60008958091C00087FFFCCF809158\n"
    ":103FB000C00084FD01C0A8958091C6000895E0E688\n"
    ":103FC000F0E098E1908380830895EDDF803219F06E\n"
    ":103FD00088E0F5DFFFCF84E1DECF1F93182FE3DF0A\n"
    ":103FE0001150E9F7F2DF1F91089580E0E8DFEE2736\n"
    ":043FF000FF2709940A\n"
    ":023FFE000404B9\n"
    ":0400000300003E00BB\n"
    ":00000001FF\n"
  }
};

const image_t PROGMEM image_8 = {
  {
    "optiboot_atmega8.hex"
  }
  ,
  {
    "atmega8"
  }
  ,
  0x9307,				/* Signature bytes for 8 */
  {
    0x3F, 0xBF, 0xCC, 0, 0
  }
  ,
  {
    0x2F, 0xBF, 0xCC, 0, 0
  }
  ,
  64,
  {
    ":101E000011248FE594E09EBF8DBF84B714BE81FF7F\n"
    ":101E1000E2D085E08EBD82E08BB988E18AB986E8A0\n"
    ":101E200080BD80E189B98EE0C2D0BD9A96E020E302\n"
    ":101E30003CEF54E040E23DBD2CBD58BF08B602FE69\n"
    ":101E4000FDCF88B3842788BBA8959150A1F7CC24F7\n"
    ":101E5000DD2488248394B5E0AB2EA1E19A2EF3E033\n"
    ":101E6000BF2E9ED0813461F49BD0082FA4D00238BD\n"
    ":101E700011F0013811F484E001C083E08DD089C0F5\n"
    ":101E8000823411F484E103C0853419F485E09BD0D9\n"
    ":101E900080C0853579F484D0E82EFF2481D0082FC6\n"
    ":101EA00010E0102F00270E291F29000F111F83D0CB\n"
    ":101EB00068016FC0863521F484E085D080E0DECFF4\n"
    ":101EC000843609F040C06CD06BD0082F69D080E018\n"
    ":101ED000C81688E1D80618F4F601B7BEE895C0E048\n"
    ":101EE000D1E05ED089930C17E1F7F0E0CF16F8E16E\n"
    ":101EF000DF0618F0F601B7BEE8955DD007B600FC26\n"
    ":101F0000FDCFA601A0E0B1E02C9130E011968C91BC\n"
    ":101F1000119790E0982F8827822B932B1296FA0125\n"
    ":101F20000C0187BEE89511244E5F5F4FF1E0A034AD\n"
    ":101F3000BF0751F7F601A7BEE89507B600FCFDCF35\n"
    ":101F400097BEE89526C08437B1F42AD029D0F82E60\n"
    ":101F500027D031D0F601EF2C8F010F5F1F4F8491F6\n"
    ":101F60001BD0EA94F801C1F70894C11CD11CFA9463\n"
    ":101F7000CF0CD11C0EC0853739F41DD08EE10CD0AA\n"
    ":101F800083E90AD087E07ACF813511F488E00FD059\n"
    ":101F900012D080E101D065CF5D9BFECF8CB9089552\n"
    ":101FA0005F9BFECF5C9901C0A8958CB1089598E124\n"
    ":101FB00091BD81BD0895F4DF803219F088E0F7DF2C\n"
    ":101FC000FFCF84E1E9CF1F93182FEADF1150E9F723\n"
    ":101FD000F2DF1F91089580E0EADFEE27FF270994E2\n"
    ":021FFE000404D9\n"
    ":0400000300001E00DB\n"
    ":00000001FF\n"
  }
};
const image_t PROGMEM image_64 = {
  {
    "optiboot_atmega64.hex"
  }
  ,
  {
    "atmega64"
  }
  ,
  0x1E9602,        /* Signature bytes for ATmega64 */
  {
    0xFF, 0xDC, 0xC0, 0, 0    /* Example low, high, and extended fuse settings */
  }
  ,
  {
    0xEF, 0xDF, 0xC0, 0, 0    /* Example extended fuse settings */
  }
  ,
  64,    /* Bootloader size in bytes */
  {
":200000000C94A6000C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B80032\n"
":200020000C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B80000\n"
":200040000C9498010C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B800FF\n"
":200060000C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B800C0\n"
":200080000C94B8000C94B8000C94B80000003A0037003400310022006100640000003B0060\n"
":2000A000380035003200230062006500050505050505050502020202020202020707040469\n"
":2000C0000404040404040707030303030303030307010101010101010106060606060606A9\n"
":2000E0000601020408102040800102040810204080081001020408102040800102010204DB\n"
":20010000081020408004804020100804020101020408102040800000000A0B0C00000000C4\n"
":200120000000010405060000000000000000000000000000000000000000000000000000AF\n"
":2001400000000000000000000000000011241FBECFEFD0E1DEBFCDBF21E0A0E0B1E001C022\n"
":200160001D92A630B207E1F70E94DF010C9442020C940000EEE3F1E02491E9E0F1E03491AD\n"
":20018000E4EDF0E09491992359F12223C1F021502C30A8F4E22FF0E0E053FF4F0C942D0203\n"
":2001A00009010901DF00DC00F100F400F700DF00DF00FB00010105012FB52F772FBDE92F45\n"
":2001C000F0E0EE0FFF1FE456FF4FA591B4919FB7F894EC91811121C030953E233C939FBF0C\n"
":2001E00008952FB52F7DEACF2FB5277FE7CF25B52F7D25BDE4CF20918B002F7720938B009E\n"
":20020000DECF20918B002F7DF9CF20918B00277FF5CF23B72F7D23BFD2CF3E2BDFCFCF925A\n"
":20022000DF92EF92FF926FB7F8948091020190910301A0910401B09105015091010122B717\n"
":2002400036B7432F417030FF04C041E02F3F09F440E06FBF6C017D0137E0CC0CDD1CEE1CE4\n"
":20026000FF1C3A95D1F7C50ED11CE11CF11CC81AD90AEA0AFB0A880F991FAA1FBB1FC81A70\n"
":20028000D90AEA0AFB0A63E0CC0CDD1CEE1CFF1C6A95D1F730E0A9ECB5E00E943302672FDB\n"
":2002A000782F892F99276C0D7D1D8E1D9F1D442321F067537A4F8F4F9F4FFF90EF90DF9061\n"
":2002C000CF9008958F929F92AF92BF92CF92DF92EF92FF920E940F014B015C0188EEC82E93\n"
":2002E00083E0D82EE12CF12C0E940F01681979098A099B09683E734081059105A8F321E06E\n"
":20030000C21AD108E108F10888EE880E83E0981EA11CB11CC114D104E104F10429F7FF9064\n"
":20032000EF90DF90CF90BF90AF909F908F9008951F920F920FB60F9211244F935F936F9334\n"
":200340007F938F939F934091020150910301609104017091050180910101909100019A3181\n"
":2003600019F51092000190910001953008F1845C8D3700F18D574E5F5F4F6F4F7F4F809379\n"
":200380000101409302015093030160930401709305019F918F917F916F915F914F910F90CE\n"
":2003A0000FBE0F901F9018959F5F90930001DBCF835CDECF4F5F5F4F6F4F7F4FE0CF78947A\n"
":2003C00083B78C6483BF87B7816087BF82E08EBD8EB581608EBD8FB581608FBD85B58460A1\n"
":2003E00085BD85B5806485BD80918A00836080938A0080918B00816080938B0086E886B978\n"
":200400001AB8E9E0F1E02491E4EDF0E08491882399F090E0880F991FFC01E457FF4FA59156\n"
":20042000B491FC01E456FF4F859194918FB7F894EC91E22BEC938FBFC0E0D0E081E00E943B\n"
":20044000BA000E94620180E00E94BA000E9462012097A1F30E940000F1CFEE0FFF1F0590BF\n"
":20046000F491E02D0994A29FB001B39FC001A39F700D811D1124911DB29F700D811D112467\n"
":08048000911D0895F894FFCFCF\n"
":00000001FF\n"


  }
};

Please, refrain from starting multiple topics with the same subject.

Your other topic is nicely formatted... keep that topic (link below) and delete this unformatted topic.

https://forum.arduino.cc/t/programming-atmega-64-with-arduino-nano/1310884

I have a program named optiLoader which loads micro atmega 8 with its bootloader. I want to change this program so that it loads the hex file on micro atmega 64 using Arduino. I changed the program as below, but the hex file is complete. It doesn't work. Please help me to put the hex file on the micro atmega 64 with Arduino

کد را در اینجا بنویسید یا بچسبانید// optiLoader.pde
//
// this sketch allows an Arduino to program Optiboot onto any other
// Arduino-like device containing ATmega8, ATmega168, or ATmega328
// microcontroller chips.
//
// Copyright (c) 2011, 2015 by Bill Westfield ("WestfW")

//-------------------------------------------------------------------------------------
// "MIT Open Source Software License":
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in the
// Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//-------------------------------------------------------------------------------------

//
// this sketch allows an Arduino to program Optiboot onto any other
// Arduino-like device containing ATmega8, ATmega168, or ATmega328
// microcontroller chips.
//
// It is based on AVRISP
//
// Designed to connect to a generic programming cable,
// using the following pins:
// 10: slave reset
// 11: MOSI
// 12: MISO
// 13: SCK
//  9: Power to external chip.
//     This is a little questionable, since the power it is legal to draw
//     from a PIC pin is pretty close to the power consumption of an AVR
//     chip being programmed.  But it permits the target to be entirely
//     powered down for safe reconnection of the programmer to additional
//     targets, and it seems to work for most Arduinos.  If the target board
//     contains additional circuitry and is expected to draw more than 40mA,
//     connect the target power to a stronger source of +5V.  Do not use pin
//     9 to power more complex Arduino boards that draw more than 40mA, such
//     as the Arduino Uno Ethernet !
//
// If the aim is to reprogram the bootloader in one Arduino using another
// Arudino as the programmer, you can just use jumpers between the connectors
// on the Arduino board.  In this case, connect:
// Pin 13 to Pin 13
// Pin 12 to Pin 12
// Pin 11 to Pin 11
// Pin 10 (of "programmer") to RESET (of "target" (on the "power" connector))
// +5V to +5V and GND to GND.  Only the "programmer" board should be powered
//     by USB or external power.
//
// ----------------------------------------------------------------------

// The following credits are from AVRISP.  It turns out that there isn't
// a lot of AVRISP left in this sketch, but probably if AVRISP had never
// existed,  this sketch would not have been written.
//
// October 2009 by David A. Mellis
// - Added support for the read signature command
//
// February 2009 by Randall Bohn
// - Added support for writing to EEPROM (what took so long?)
// Windows users should consider WinAVR's avrdude instead of the
// avrdude included with Arduino software.
//
// January 2008 by Randall Bohn
// - Thanks to Amplificar for helping me with the STK500 protocol
// - The AVRISP/STK500 (mk I) protocol is used in the arduino bootloader
// - The SPI functions herein were developed for the AVR910_ARD programmer
// - More information at http://code.google.com/p/mega-isp


#include <avr/pgmspace.h>
#include "optiLoader.h"

char Arduino_preprocessor_hint;

/*
   Pins to target
*/
#define SCK 13
#define MISO 12
#define MOSI 11
#define RESET 10
#define POWER 9

// STK Definitions; we can still use these as return codes
#define STK_OK 0x10
#define STK_FAILED 0x11


// Useful message printing definitions
#define fp(string) flashprint(PSTR(string));
#define debug(string) // flashprint(PSTR(string));
#define error(string) flashprint(PSTR(string));

// Forward references
void pulse(int pin, int times);
void read_image(const image_t *ip);
 
// Global Variables

/*
   Table of defined images
*/
const image_t * images[] = {
  &image_328, &image_328p, &image_168, &image_8,&image_64, 0
};

/*
   Table of "Aliases."  Chips that are effectively the same as chips
   that we have a bootloader for.  These work by simply overriding the
   signature read with the signature of the chip we "know."
*/
const alias_t aliases[] = {
  { "ATmega168PA", 0x940B, 0x9406 },	/* Treat 168P same as 168 */
  { "ATmega168PB", 0x9415, 0x9406 },	/* Treat 168PB same as 168 */
  { "ATmega64", 0x1E9602, 0x1E9602 }, 
  { "ATmega328PB", 0x9516, 0x950F },	/* Treat 328PB same as 328P */
  { "ATmega328",   0x9514, 0x950F },	/* Treat 328 same as 328P */
};

int pmode = 0;
// address for reading and writing, set by 'U' command
int here;

uint16_t target_type = 0;		/* type of target_cpu */
uint16_t target_startaddr;
uint8_t target_pagesize;       /* Page size for flash programming (bytes) */
uint8_t *buff;

const image_t *target_flashptr; 	       /* pointer to target info in flash */
uint8_t target_code[512];	       /* The whole code */
 
void setup (void) {
  Serial.begin(19200); 			/* Initialize serial for status msgs */
  pinMode(13, OUTPUT); 			/* Blink the pin13 LED a few times */
#ifdef PIN_SPI_SS
#if PIN_SPI_SS != RESET
  // on non-AtmegaXX8 boards (MEGA, Leonardo, etc) the SPI SS pin is NOT pin 10,
  // and although SS is driven manually (RESET to the target), SS should not be
  // allowed to default to INPUT and floating, or the SPI hardware may decide that
  // some other SPI master is trying to use the bus.  (See Datasheet SS description.)
  pinMode(PIN_SPI_SS, INPUT_PULLUP);
#endif
#endif
  pulse(13, 20);
}

void loop (void) {
  fp("\nOptiLoader Bootstrap programmer.\n2011 by Bill Westfield (WestfW)\n\n");
  if (target_poweron()) {		/* Turn on target power */
    do {
      if (!target_identify()) 		/* Figure out what kind of CPU */
        break;
      if (!target_findimage())		/* look for an image */
        break;
      if (!target_progfuses())		/* get fuses ready to program */
        break;
      if (!target_program()) 		/* Program the image */
        break;
      (void) target_normfuses(); 	/* reset fuses to normal mode */
    }
    while (0);
  }
  else {
    Serial.println();
  }
  target_poweroff(); 			/* turn power off */

  fp ("\nType 'G' or hit RESET for next chip\n")
  while (1) {
    if (Serial.read() == 'G')
      break;
  }
}
 
/*
   Low level support functions
*/

/*
   flashprint
   print a text string direct from flash memory to Serial
*/
void flashprint (const char p[])
{
  uint8_t c;
  while (0 != (c = pgm_read_byte(p++))) {
    Serial.write(c);
  }
}

/*
   hexton
   Turn a Hex digit (0..9, A..F) into the equivalent binary value (0-16)
*/
uint8_t hexton (uint8_t h)
{
  if (h >= '0' && h <= '9')
    return (h - '0');
  if (h >= 'A' && h <= 'F')
    return ((h - 'A') + 10);
  error("Bad hex digit!");
  return (0);
}

/*
   pulse
   turn a pin on and off a few times; indicates life via LED
*/
#define PTIME 30
void pulse (int pin, int times) {
  do {
    digitalWrite(pin, HIGH);
    delay(PTIME);
    digitalWrite(pin, LOW);
    delay(PTIME);
  }
  while (times--);
}

/*
   spi_init
   initialize the AVR SPI peripheral
*/
void spi_init (void) {
  uint8_t x;
  SPCR = 0x53;  // SPIE | MSTR | SPR1 | SPR0
  x = SPSR;
  x = SPDR;
}

/*
   spi_wait
   wait for SPI transfer to complete
*/
void spi_wait (void) {
  debug("spi_wait");
  do {
  }
  while (!(SPSR & (1 << SPIF)));
}

/*
   spi_send
   send a byte via SPI, wait for the transfer.
*/
uint8_t spi_send (uint8_t b) {
  uint8_t reply;
  SPDR = b;
  spi_wait();
  reply = SPDR;
  return reply;
}

 
/*
   Functions specific to ISP programming of an AVR
*/

/*
   target_identify
   read the signature bytes (if possible) and check whether it's
   a legal value (atmega8, atmega168, atmega328)
*/

boolean target_identify ()
{
  boolean result;
  target_type = 0;
  fp("\nReading signature:");
  target_type = read_signature();
  if (target_type == 0 || target_type == 0xFFFF) {
    fp(" Bad value: ");
    result = false;
  }
  else {
    result = true;
  }
  Serial.println(target_type, HEX);
  if (target_type == 0) {
    fp("  (no target attached?)\n");
  }
  return result;
}

unsigned long spi_transaction (uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
  uint8_t n, m;
  spi_send(a);
  n = spi_send(b);
  //if (n != a) error = -1;
  m = spi_send(c);
  return 0xFFFFFF & ((((uint32_t)n) << 16) + (m << 8) + spi_send(d));
}

uint16_t start_pmode () {
  uint16_t result;

  pinMode(13, INPUT); // restore to default
  spi_init();
  debug("...spi_init done");
  // following delays may not work on all targets...
  pinMode(RESET, OUTPUT);
  digitalWrite(RESET, HIGH);
  pinMode(SCK, OUTPUT);
  digitalWrite(SCK, LOW);
  delay(50);
  digitalWrite(RESET, LOW);
  delay(50);
  pinMode(MISO, INPUT);
  pinMode(MOSI, OUTPUT);
  debug("...spi_transaction");
  result = spi_transaction(0xAC, 0x53, 0x00, 0x00);
  debug("...Done");
  pmode = 1;
  return result;
}

void end_pmode (void) {
  SPCR = 0; 				/* reset SPI */
  digitalWrite(MISO, 0); 		/* Make sure pullups are off too */
  pinMode(MISO, INPUT);
  digitalWrite(MOSI, 0);
  pinMode(MOSI, INPUT);
  digitalWrite(SCK, 0);
  pinMode(SCK, INPUT);
  digitalWrite(RESET, 0);
  pinMode(RESET, INPUT);
  pmode = 0;
}
 
/*
   read_image

   Read an intel hex image from a string in pgm memory.
   We assume that the image does not exceed the 512 bytes that we have
   allowed for it to have.  that would be bad.
   Also read other data from the image, such as fuse and protecttion byte
   values during programming, and for after we're done.
*/
void read_image (const image_t *ip)
{
  uint16_t len, totlen = 0, addr;
  const char *hextext = &ip->image_hexcode[0];
  target_startaddr = 0;
  target_pagesize = pgm_read_byte(&ip->image_pagesize);
  uint8_t b, cksum = 0;

  while (1) {
    if (pgm_read_byte(hextext++) != ':') {
      error("No colon");
      break;
    }
    len = hexton(pgm_read_byte(hextext++));
    len = (len << 4) + hexton(pgm_read_byte(hextext++));
    cksum = len;

    b = hexton(pgm_read_byte(hextext++)); /* record type */
    b = (b << 4) + hexton(pgm_read_byte(hextext++));
    cksum += b;
    addr = b;
    b = hexton(pgm_read_byte(hextext++)); /* record type */
    b = (b << 4) + hexton(pgm_read_byte(hextext++));
    cksum += b;
    addr = (addr << 8) + b;
    if (target_startaddr == 0) {
      target_startaddr = addr;
      fp("  Start address at ");
      Serial.println(addr, HEX);
    }
    else if (addr == 0) {
      break;
    }

    b = hexton(pgm_read_byte(hextext++)); /* record type */
    b = (b << 4) + hexton(pgm_read_byte(hextext++));
    cksum += b;

    for (uint8_t i = 0; i < len; i++) {
      b = hexton(pgm_read_byte(hextext++));
      b = (b << 4) + hexton(pgm_read_byte(hextext++));
      if (addr - target_startaddr >= sizeof(target_code)) {
        error("Code extends beyond allowed range");
        break;
      }
      target_code[addr++ - target_startaddr] = b;
      cksum += b;
#if VERBOSE
      Serial.print(b, HEX);
      Serial.write(' ');
#endif
      totlen++;
      if (totlen >= sizeof(target_code)) {
        error("Too much code");
        break;
      }
    }
    b = hexton(pgm_read_byte(hextext++)); /* checksum */
    b = (b << 4) + hexton(pgm_read_byte(hextext++));
    cksum += b;
    if (cksum != 0) {
      error("Bad checksum: ");
      Serial.print(cksum, HEX);
    }
    if (pgm_read_byte(hextext++) != '\n') {
      error("No end of line");
      break;
    }
#if VERBOSE
    Serial.println();
#endif
  }
  fp("  Total bytes read: ");
  Serial.println(totlen);
}
 
/*
   target_findimage

   given target_type loaded with the relevant part of the device signature,
   search the hex images that we have programmed in flash, looking for one
   that matches.
*/

boolean target_findimage ()
{
  const image_t *ip;
  fp("Searching for image...\n");
  /*
     Search through our table of chip aliases first
  */
  for (uint8_t i = 0; i < sizeof(aliases) / sizeof(aliases[0]); i++) {
    const alias_t *a = &aliases[i];
    if (a->real_chipsig == target_type) {
      fp("  Compatible bootloader for ");
      Serial.println(a->alias_chipname);
      target_type = a->alias_chipsig;  /* Overwrite chip signature */
      break;
    }
  }
  /*
     Search through our table of self-contained images.
  */
  for (uint8_t i = 0; i < sizeof(images) / sizeof(images[0]); i++) {
    target_flashptr = ip = images[i];
    if (ip && (pgm_read_word(&ip->image_chipsig) == target_type)) {
      fp("  Found \"");
      flashprint(&ip->image_name[0]);
      fp("\" for ");
      flashprint(&ip->image_chipname[0]);
      fp("\n");
      read_image(ip);
      return true;
    }
  }
  fp(" Not Found\n");
  return (false);
}

/*
   target_progfuses
   given initialized target image data, re-program the fuses to allow
   the optiboot image to be programmed.
*/

boolean target_progfuses ()
{
  uint8_t f;
  fp("\nSetting fuses for programming");

  f = pgm_read_byte(&target_flashptr->image_progfuses[FUSE_PROT]);
  if (f) {
    fp("\n  Lock: ");
    Serial.print(f, HEX);
    fp(" ");
    Serial.print(spi_transaction(0xAC, 0xE0, 0x00, f), HEX);
  }
  f = pgm_read_byte(&target_flashptr->image_progfuses[FUSE_LOW]);
  if (f) {
    fp("  Low: ");
    Serial.print(f, HEX);
    fp(" ");
    Serial.print(spi_transaction(0xAC, 0xA0, 0x00, f), HEX);
  }
  f = pgm_read_byte(&target_flashptr->image_progfuses[FUSE_HIGH]);
  if (f) {
    fp("  High: ");
    Serial.print(f, HEX);
    fp(" ");
    Serial.print(spi_transaction(0xAC, 0xA8, 0x00, f), HEX);
  }
  f = pgm_read_byte(&target_flashptr->image_progfuses[FUSE_EXT]);
  if (f) {
    fp("  Ext: ");
    Serial.print(f, HEX);
    fp(" ");
    Serial.print(spi_transaction(0xAC, 0xA4, 0x00, f), HEX);
  }
  Serial.println();
  return true; 			/* */
}

/*
   target_program
   Actually program the image into the target chip
*/

boolean target_program ()
{
  int l; 				/* actual length */

  fp("\nProgramming bootloader: ");
  here = target_startaddr >> 1; 		/* word address */
  buff = target_code;
  l = 512;
  Serial.print(l, DEC);
  fp(" bytes at 0x");
  Serial.println(here, HEX);

  spi_transaction(0xAC, 0x80, 0, 0); 	/* chip erase */
  delay(1000);
  if (write_flash(l) != STK_OK) {
    error("\nFlash Write Failed");
    return false;
  }
  return true; 			/*  */
}

/*
   target_normfuses
   reprogram the fuses to the state they should be in for bootloader
   based programming
*/
boolean target_normfuses ()
{
  uint8_t f;
  fp("\nRestoring normal fuses");

  f = pgm_read_byte(&target_flashptr->image_normfuses[FUSE_PROT]);
  if (f) {
    fp("\n  Lock: ");
    Serial.print(f, HEX);
    fp(" ");
    Serial.print(spi_transaction(0xAC, 0xE0, 0x00, f), HEX);
  }
  f = pgm_read_byte(&target_flashptr->image_normfuses[FUSE_LOW]);
  if (f) {
    fp("  Low: ");
    Serial.print(f, HEX);
    fp(" ");
    Serial.print(spi_transaction(0xAC, 0xA0, 0x00, f), HEX);
  }
  f = pgm_read_byte(&target_flashptr->image_normfuses[FUSE_HIGH]);
  if (f) {
    fp("  High: ");
    Serial.print(f, HEX);
    fp(" ");
    Serial.print(spi_transaction(0xAC, 0xA8, 0x00, f), HEX);
  }
  f = pgm_read_byte(&target_flashptr->image_normfuses[FUSE_EXT]);
  if (f) {
    fp("  Ext: ");
    Serial.print(f, HEX);
    fp(" ");
    Serial.print(spi_transaction(0xAC, 0xA4, 0x00, f), HEX);
  }
  Serial.println();
  return true; 			/* */
}

/*
   target_poweron
   Turn on power to the target chip (assuming that it is powered through
   the relevant IO pin of THIS arduino.)
*/
boolean target_poweron ()
{
  uint16_t result;

  fp("Target power on! ...");
  digitalWrite(POWER, LOW);
  pinMode(POWER, OUTPUT);
  digitalWrite(POWER, HIGH);
  digitalWrite(RESET, LOW);  // reset it right away.
  pinMode(RESET, OUTPUT);
  /*
     Check if the target is pulling RESET HIGH by reverting to input
  */
  delay(5);
  pinMode(RESET, INPUT);
  delay(1);
  if (digitalRead(RESET) != HIGH) {
    fp("No RESET pullup detected! - no target?");
    return false;
  }
  pinMode(RESET, OUTPUT);

  delay(200);
  fp("\nStarting Program Mode");
  result = start_pmode();
  if ((result & 0xFF00) != 0x5300) {
    fp(" - Failed, result = 0x");
    Serial.print(result, HEX);
    return false;
  }
  fp(" [OK]\n");
  return true;
}

boolean target_poweroff ()
{
  end_pmode();
  digitalWrite(POWER, LOW);
  delay(200);
  pinMode(POWER, INPUT);
  fp("\nTarget power OFF!\n");
  return true;
}

void flash (uint8_t hilo, int addr, uint8_t data) {
#if VERBOSE
  Serial.print(data, HEX);
  fp(":");
  Serial.print(spi_transaction(0x40 + 8 * hilo,
                               addr >> 8 & 0xFF,
                               addr & 0xFF,
                               data), HEX);
  fp(" ");
#else
  (void) spi_transaction(0x40 + 8 * hilo,
                         addr >> 8 & 0xFF,
                         addr & 0xFF,
                         data);
#endif
}

void commit (int addr) {
  fp("  Commit Page: ");
  Serial.print(addr, HEX);
  fp(":");
  Serial.println(spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0), HEX);
  delay(100);
}

//#define _current_page(x) (here & 0xFFFFE0)
int current_page (int addr) {
  if (target_pagesize == 32) return here & 0xFFFFFFF0;
  if (target_pagesize == 64) return here & 0xFFFFFFE0;
  if (target_pagesize == 128) return here & 0xFFFFFFC0;
  return here;
}

uint8_t write_flash (int length) {
  if (target_pagesize < 1) return STK_FAILED;
  //if (target_pagesize != 64) return STK_FAILED;
  int page = current_page(here);
  int x = 0;
  while (x < length) {
    if (page != current_page(here)) {
      commit(page);
      page = current_page(here);
    }
    flash(LOW, here, buff[x]);
    flash(HIGH, here, buff[x + 1]);
    x += 2;
    here++;
  }

  commit(page);

  return STK_OK;
}

uint16_t read_signature () {
  uint8_t sig_middle = spi_transaction(0x30, 0x00, 0x01, 0x00);
  uint8_t sig_low = spi_transaction(0x30, 0x00, 0x02, 0x00);
  return ((sig_middle << 8) + sig_low);
}
 
/*
   Bootload images.
   These are the intel Hex files produced by the optiboot makefile,
   with a small amount of automatic editing to turn them into C strings,
   and a header attched to identify them

   Emacs keyboard macro:

      4*SPC			;; self-insert-command
      "			;; self-insert-command
      C-e			;; move-end-of-line
      \			;; self-insert-command
      n"			;; self-insert-command * 2
      C-n			;; next-line
      C-a			;; move-beginning-of-line

*/


const image_t PROGMEM image_328 = {
  {
    "optiboot_atmega328.hex"
  }
  ,
  {
    "atmega328"
  }
  ,
  0x9514,				/* Signature bytes for 328 (non-P) */
  {
    0x3F, 0xFF, 0xDE, 0x05, 0
  }
  ,
  {
    0x2F, 0, 0, 0, 0
  }
  ,
  128,
  {
    ":107E0000112484B714BE81FFF0D085E080938100F7\n"
    ":107E100082E08093C00088E18093C10086E0809377\n"
    ":107E2000C20080E18093C4008EE0C9D0259A86E02C\n"
    ":107E300020E33CEF91E0309385002093840096BBD3\n"
    ":107E4000B09BFECF1D9AA8958150A9F7CC24DD24C4\n"
    ":107E500088248394B5E0AB2EA1E19A2EF3E0BF2EE7\n"
    ":107E6000A2D0813461F49FD0082FAFD0023811F036\n"
    ":107E7000013811F484E001C083E08DD089C08234E0\n"
    ":107E800011F484E103C0853419F485E0A6D080C0E4\n"
    ":107E9000853579F488D0E82EFF2485D0082F10E0AE\n"
    ":107EA000102F00270E291F29000F111F8ED06801E7\n"
    ":107EB0006FC0863521F484E090D080E0DECF843638\n"
    ":107EC00009F040C070D06FD0082F6DD080E0C81688\n"
    ":107ED00080E7D80618F4F601B7BEE895C0E0D1E017\n"
    ":107EE00062D089930C17E1F7F0E0CF16F0E7DF06D8\n"
    ":107EF00018F0F601B7BEE89568D007B600FCFDCFD4\n"
    ":107F0000A601A0E0B1E02C9130E011968C91119780\n"
    ":107F100090E0982F8827822B932B1296FA010C0160\n"
    ":107F200087BEE89511244E5F5F4FF1E0A038BF0790\n"
    ":107F300051F7F601A7BEE89507B600FCFDCF97BE46\n"
    ":107F4000E89526C08437B1F42ED02DD0F82E2BD052\n"
    ":107F50003CD0F601EF2C8F010F5F1F4F84911BD097\n"
    ":107F6000EA94F801C1F70894C11CD11CFA94CF0C13\n"
    ":107F7000D11C0EC0853739F428D08EE10CD085E9AC\n"
    ":107F80000AD08FE07ACF813511F488E018D01DD067\n"
    ":107F900080E101D065CF982F8091C00085FFFCCF94\n"
    ":107FA0009093C60008958091C00087FFFCCF809118\n"
    ":107FB000C00084FD01C0A8958091C6000895E0E648\n"
    ":107FC000F0E098E1908380830895EDDF803219F02E\n"
    ":107FD00088E0F5DFFFCF84E1DECF1F93182FE3DFCA\n"
    ":107FE0001150E9F7F2DF1F91089580E0E8DFEE27F6\n"
    ":047FF000FF270994CA\n"
    ":027FFE00040479\n"
    ":0400000300007E007B\n"
    ":00000001FF\n"
  }
};

const image_t PROGMEM image_328p = {
  {
    "optiboot_atmega328.hex"
  }
  ,
  {
    "atmega328P"
  }
  ,
  0x950F,				/* Signature bytes for 328P */
  {
    0x3F, 0xFF, 0xDE, 0x05, 0
  }
  ,
  {
    0x2F, 0, 0, 0, 0
  }
  ,
  128,
  {
    ":107E0000112484B714BE81FFF0D085E080938100F7\n"
    ":107E100082E08093C00088E18093C10086E0809377\n"
    ":107E2000C20080E18093C4008EE0C9D0259A86E02C\n"
    ":107E300020E33CEF91E0309385002093840096BBD3\n"
    ":107E4000B09BFECF1D9AA8958150A9F7CC24DD24C4\n"
    ":107E500088248394B5E0AB2EA1E19A2EF3E0BF2EE7\n"
    ":107E6000A2D0813461F49FD0082FAFD0023811F036\n"
    ":107E7000013811F484E001C083E08DD089C08234E0\n"
    ":107E800011F484E103C0853419F485E0A6D080C0E4\n"
    ":107E9000853579F488D0E82EFF2485D0082F10E0AE\n"
    ":107EA000102F00270E291F29000F111F8ED06801E7\n"
    ":107EB0006FC0863521F484E090D080E0DECF843638\n"
    ":107EC00009F040C070D06FD0082F6DD080E0C81688\n"
    ":107ED00080E7D80618F4F601B7BEE895C0E0D1E017\n"
    ":107EE00062D089930C17E1F7F0E0CF16F0E7DF06D8\n"
    ":107EF00018F0F601B7BEE89568D007B600FCFDCFD4\n"
    ":107F0000A601A0E0B1E02C9130E011968C91119780\n"
    ":107F100090E0982F8827822B932B1296FA010C0160\n"
    ":107F200087BEE89511244E5F5F4FF1E0A038BF0790\n"
    ":107F300051F7F601A7BEE89507B600FCFDCF97BE46\n"
    ":107F4000E89526C08437B1F42ED02DD0F82E2BD052\n"
    ":107F50003CD0F601EF2C8F010F5F1F4F84911BD097\n"
    ":107F6000EA94F801C1F70894C11CD11CFA94CF0C13\n"
    ":107F7000D11C0EC0853739F428D08EE10CD085E9AC\n"
    ":107F80000AD08FE07ACF813511F488E018D01DD067\n"
    ":107F900080E101D065CF982F8091C00085FFFCCF94\n"
    ":107FA0009093C60008958091C00087FFFCCF809118\n"
    ":107FB000C00084FD01C0A8958091C6000895E0E648\n"
    ":107FC000F0E098E1908380830895EDDF803219F02E\n"
    ":107FD00088E0F5DFFFCF84E1DECF1F93182FE3DFCA\n"
    ":107FE0001150E9F7F2DF1F91089580E0E8DFEE27F6\n"
    ":047FF000FF270994CA\n"
    ":027FFE00040479\n"
    ":0400000300007E007B\n"
    ":00000001FF\n"
  }
};
 
const image_t PROGMEM image_168 = {
  {
    "optiboot_atmega168.hex"
  }
  ,
  {
    "atmega168"
  }
  ,
  0x9406,				/* Signature bytes for 168 */
  {
    0x3F, 0xC6, 0xDD, 0x04
  }
  ,
  {
    0x2F, 0, 0, 0, 0
  }
  ,
  128,
  {
    ":103E0000112484B714BE81FFF0D085E08093810037\n"
    ":103E100082E08093C00088E18093C10086E08093B7\n"
    ":103E2000C20080E18093C4008EE0C9D0259A86E06C\n"
    ":103E300020E33CEF91E0309385002093840096BB13\n"
    ":103E4000B09BFECF1D9AA8958150A9F7CC24DD2404\n"
    ":103E500088248394B5E0AB2EA1E19A2EF3E0BF2E27\n"
    ":103E6000A2D0813461F49FD0082FAFD0023811F076\n"
    ":103E7000013811F484E001C083E08DD089C0823420\n"
    ":103E800011F484E103C0853419F485E0A6D080C024\n"
    ":103E9000853579F488D0E82EFF2485D0082F10E0EE\n"
    ":103EA000102F00270E291F29000F111F8ED0680127\n"
    ":103EB0006FC0863521F484E090D080E0DECF843678\n"
    ":103EC00009F040C070D06FD0082F6DD080E0C816C8\n"
    ":103ED00088E3D80618F4F601B7BEE895C0E0D1E053\n"
    ":103EE00062D089930C17E1F7F0E0CF16F8E3DF0614\n"
    ":103EF00018F0F601B7BEE89568D007B600FCFDCF14\n"
    ":103F0000A601A0E0B1E02C9130E011968C911197C0\n"
    ":103F100090E0982F8827822B932B1296FA010C01A0\n"
    ":103F200087BEE89511244E5F5F4FF1E0A038BF07D0\n"
    ":103F300051F7F601A7BEE89507B600FCFDCF97BE86\n"
    ":103F4000E89526C08437B1F42ED02DD0F82E2BD092\n"
    ":103F50003CD0F601EF2C8F010F5F1F4F84911BD0D7\n"
    ":103F6000EA94F801C1F70894C11CD11CFA94CF0C53\n"
    ":103F7000D11C0EC0853739F428D08EE10CD084E9ED\n"
    ":103F80000AD086E07ACF813511F488E018D01DD0B0\n"
    ":103F900080E101D065CF982F8091C00085FFFCCFD4\n"
    ":103FA0009093C60008958091C00087FFFCCF809158\n"
    ":103FB000C00084FD01C0A8958091C6000895E0E688\n"
    ":103FC000F0E098E1908380830895EDDF803219F06E\n"
    ":103FD00088E0F5DFFFCF84E1DECF1F93182FE3DF0A\n"
    ":103FE0001150E9F7F2DF1F91089580E0E8DFEE2736\n"
    ":043FF000FF2709940A\n"
    ":023FFE000404B9\n"
    ":0400000300003E00BB\n"
    ":00000001FF\n"
  }
};
 
const image_t PROGMEM image_8 = {
  {
    "optiboot_atmega8.hex"
  }
  ,
  {
    "atmega8"
  }
  ,
  0x9307,				/* Signature bytes for 8 */
  {
    0x3F, 0xBF, 0xCC, 0, 0
  }
  ,
  {
    0x2F, 0xBF, 0xCC, 0, 0
  }
  ,
  64,
  {
    ":101E000011248FE594E09EBF8DBF84B714BE81FF7F\n"
    ":101E1000E2D085E08EBD82E08BB988E18AB986E8A0\n"
    ":101E200080BD80E189B98EE0C2D0BD9A96E020E302\n"
    ":101E30003CEF54E040E23DBD2CBD58BF08B602FE69\n"
    ":101E4000FDCF88B3842788BBA8959150A1F7CC24F7\n"
    ":101E5000DD2488248394B5E0AB2EA1E19A2EF3E033\n"
    ":101E6000BF2E9ED0813461F49BD0082FA4D00238BD\n"
    ":101E700011F0013811F484E001C083E08DD089C0F5\n"
    ":101E8000823411F484E103C0853419F485E09BD0D9\n"
    ":101E900080C0853579F484D0E82EFF2481D0082FC6\n"
    ":101EA00010E0102F00270E291F29000F111F83D0CB\n"
    ":101EB00068016FC0863521F484E085D080E0DECFF4\n"
    ":101EC000843609F040C06CD06BD0082F69D080E018\n"
    ":101ED000C81688E1D80618F4F601B7BEE895C0E048\n"
    ":101EE000D1E05ED089930C17E1F7F0E0CF16F8E16E\n"
    ":101EF000DF0618F0F601B7BEE8955DD007B600FC26\n"
    ":101F0000FDCFA601A0E0B1E02C9130E011968C91BC\n"
    ":101F1000119790E0982F8827822B932B1296FA0125\n"
    ":101F20000C0187BEE89511244E5F5F4FF1E0A034AD\n"
    ":101F3000BF0751F7F601A7BEE89507B600FCFDCF35\n"
    ":101F400097BEE89526C08437B1F42AD029D0F82E60\n"
    ":101F500027D031D0F601EF2C8F010F5F1F4F8491F6\n"
    ":101F60001BD0EA94F801C1F70894C11CD11CFA9463\n"
    ":101F7000CF0CD11C0EC0853739F41DD08EE10CD0AA\n"
    ":101F800083E90AD087E07ACF813511F488E00FD059\n"
    ":101F900012D080E101D065CF5D9BFECF8CB9089552\n"
    ":101FA0005F9BFECF5C9901C0A8958CB1089598E124\n"
    ":101FB00091BD81BD0895F4DF803219F088E0F7DF2C\n"
    ":101FC000FFCF84E1E9CF1F93182FEADF1150E9F723\n"
    ":101FD000F2DF1F91089580E0EADFEE27FF270994E2\n"
    ":021FFE000404D9\n"
    ":0400000300001E00DB\n"
    ":00000001FF\n"
  }
};
const image_t PROGMEM image_64 = {
  {
    "optiboot_atmega64.hex"
  }
  ,
  {
    "atmega64"
  }
  ,
  0x1E9602,        /* Signature bytes for ATmega64 */
  {
    0xFF, 0xDC, 0xC0, 0, 0    /* Example low, high, and extended fuse settings */
  }
  ,
  {
    0xEF, 0xDF, 0xC0, 0, 0    /* Example extended fuse settings */
  }
  ,
  64,    /* Bootloader size in bytes */
  {
":200000000C94A6000C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B80032\n"
":200020000C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B80000\n"
":200040000C9498010C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B800FF\n"
":200060000C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B800C0\n"
":200080000C94B8000C94B8000C94B80000003A0037003400310022006100640000003B0060\n"
":2000A000380035003200230062006500050505050505050502020202020202020707040469\n"
":2000C0000404040404040707030303030303030307010101010101010106060606060606A9\n"
":2000E0000601020408102040800102040810204080081001020408102040800102010204DB\n"
":20010000081020408004804020100804020101020408102040800000000A0B0C00000000C4\n"
":200120000000010405060000000000000000000000000000000000000000000000000000AF\n"
":2001400000000000000000000000000011241FBECFEFD0E1DEBFCDBF21E0A0E0B1E001C022\n"
":200160001D92A630B207E1F70E94DF010C9442020C940000EEE3F1E02491E9E0F1E03491AD\n"
":20018000E4EDF0E09491992359F12223C1F021502C30A8F4E22FF0E0E053FF4F0C942D0203\n"
":2001A00009010901DF00DC00F100F400F700DF00DF00FB00010105012FB52F772FBDE92F45\n"
":2001C000F0E0EE0FFF1FE456FF4FA591B4919FB7F894EC91811121C030953E233C939FBF0C\n"
":2001E00008952FB52F7DEACF2FB5277FE7CF25B52F7D25BDE4CF20918B002F7720938B009E\n"
":20020000DECF20918B002F7DF9CF20918B00277FF5CF23B72F7D23BFD2CF3E2BDFCFCF925A\n"
":20022000DF92EF92FF926FB7F8948091020190910301A0910401B09105015091010122B717\n"
":2002400036B7432F417030FF04C041E02F3F09F440E06FBF6C017D0137E0CC0CDD1CEE1CE4\n"
":20026000FF1C3A95D1F7C50ED11CE11CF11CC81AD90AEA0AFB0A880F991FAA1FBB1FC81A70\n"
":20028000D90AEA0AFB0A63E0CC0CDD1CEE1CFF1C6A95D1F730E0A9ECB5E00E943302672FDB\n"
":2002A000782F892F99276C0D7D1D8E1D9F1D442321F067537A4F8F4F9F4FFF90EF90DF9061\n"
":2002C000CF9008958F929F92AF92BF92CF92DF92EF92FF920E940F014B015C0188EEC82E93\n"
":2002E00083E0D82EE12CF12C0E940F01681979098A099B09683E734081059105A8F321E06E\n"
":20030000C21AD108E108F10888EE880E83E0981EA11CB11CC114D104E104F10429F7FF9064\n"
":20032000EF90DF90CF90BF90AF909F908F9008951F920F920FB60F9211244F935F936F9334\n"
":200340007F938F939F934091020150910301609104017091050180910101909100019A3181\n"
":2003600019F51092000190910001953008F1845C8D3700F18D574E5F5F4F6F4F7F4F809379\n"
":200380000101409302015093030160930401709305019F918F917F916F915F914F910F90CE\n"
":2003A0000FBE0F901F9018959F5F90930001DBCF835CDECF4F5F5F4F6F4F7F4FE0CF78947A\n"
":2003C00083B78C6483BF87B7816087BF82E08EBD8EB581608EBD8FB581608FBD85B58460A1\n"
":2003E00085BD85B5806485BD80918A00836080938A0080918B00816080938B0086E886B978\n"
":200400001AB8E9E0F1E02491E4EDF0E08491882399F090E0880F991FFC01E457FF4FA59156\n"
":20042000B491FC01E456FF4F859194918FB7F894EC91E22BEC938FBFC0E0D0E081E00E943B\n"
":20044000BA000E94620180E00E94BA000E9462012097A1F30E940000F1CFEE0FFF1F0590BF\n"
":20046000F491E02D0994A29FB001B39FC001A39F700D811D1124911DB29F700D811D112467\n"
":08048000911D0895F894FFCFCF\n"
":00000001FF\n"


  }
};

This was the hex file that I read with another programmer that after downloading the program, it was not completely downloaded, which means that the hex file was not completely downloaded and it is different from the hex file that I put in the program.:200020000C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B80000 :200040000C9498010C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B800FF :200060000C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B8000C94B800C0 :200080000C94B8000C94B8000C94B80000003A0037003400310022006100640000003B0060 :2000A000380035003200230062006500050505050505050502020202020202020707040469 :2000C0000404040404040707030303030303030307010101010101010106060606060606A9 :2000E0000601020408102040800102040810204080081001020408102040800102010204DB :20010000081020408004804020100804020101020408102040800000000A0B0C00000000C4 :200120000000010405060000000000000000000000000000000000000000000000000000AF :2001400000000000000000000000000011241FBECFEFD0E1DEBFCDBF21E0A0E0B1E001C022 :200160001D92A630B207E1F70E94DF010C9442020C940000EEE3F1E02491E9E0F1E03491AD :20018000E4EDF0E09491992359F12223C1F021502C30A8F4E22FF0E0E053FF4F0C942D0203 :2001A00009010901DF00DC00F100F400F700DF00DF00FB00010105012FB52F772FBDE92F45 :2001C000F0E0EE0FFF1FE456FF4FA591B4919FB7F894EC91811121C030953E233C939FBF0C :2001E00008952FB52F7DEACF2FB5277FE7CF25B52F7D25BDE4CF20918B002F7720938B009E :20020000DE0000000000000000000000000000000000000000000000000000000000000000 :00000001FF

Do not cross-post; it wastes people's time. Your recent topics have been merged.

Do not post in "Uncategorized".

uint8_t target_code[512]; /* The whole code */

Optiloader won't support bootloaders longer than 512bytes without additional modifications. It looks like your bootloader is about 1200 bytes.

You MIGHT get away with changing that to:

uint8_t target_code[1200];	       /* The whole code */

And also changing the text size in "optiboot.h":

   char image_hexcode[3000];        /* intel hex format image (text) */

At this point, though, you might start running into memory usage problems (if you're running on an Uno.)

This is also wrong:

That number is the chip "page size" in bytes, which I think needs to be 256 for an ATmega64. Except it looks like optiloader might not support a page size of 256:

int current_page (int addr) {
  if (target_pagesize == 32) return here & 0xFFFFFFF0;
  if (target_pagesize == 64) return here & 0xFFFFFFE0;
  if (target_pagesize == 128) return here & 0xFFFFFFC0;
  return here;
}

Why do you want to use optiloader? It was pretty much a single-purpose program designed to "upgrade" old Arduinos to the new Uno bootloader (optiboot) written back when the Uno came out.

You might have better luck with one of the more complete programs that it "inspired":

Is there a way to put the hex file on the microatmega 64 cam program with Arduino Nano and the hex file in the Arduino program instead of putting the bootloader directly?

I want to program the following hex file using Arduino Nano on micro atmega 64 in such a way that this hex file is in the Arduino program and program it by pressing the key, and it is only necessary to put the same program on the Arduino and then to the laptop I don't connect the top and only connect it to the laptop once to put this program on the radio. Please, if anyone knows, write me the program because I don't know.

:100000003FC04EC04DC04CC04BC04AC049C048C0A4
:1000100047C0D3C045C044C043C042C041C040C037
:100020003FC03EC03DC0000000003700340031003A
:100030000000000038003500320004040404040409
:100040000404020202020202030303030303020286
:10005000030102040810204080010204081020015E
:100060000204081020408040000000000000000052
:100070000004050700000000000000000000000070
:1000800011241FBECFE5D4E0DEBFCDBF20E0A0E647
:10009000B0E001C01D92A936B207E1F7D8D016C171
:1000A000AFCFE2E7F0E02491EBE5F0E09491E4E4F7
:1000B000F0E0E491EE23E1F0222349F02530C9F08D
:1000C0002730D1F0243019F42FB52F772FBDF0E071
:1000D000EE0FFF1FE05DFF4FA591B4912FB7F8948D
:1000E00081110EC08C91E92FE095E823EC932FBF8E
:1000F00008952FB52F7DEACF25B52F7D25BDE7CFFC
:10010000EC91E92BF3CF3FB7F89480916500909183
:100110006600A0916700B091680022B708B600FEA3
:1001200005C02F3F19F00196A11DB11D3FBFBA2F89
:10013000A92F982F8827BC01CD01620F711D811D49
:10014000911D42E0660F771F881F991F4A95D1F7CE
:1001500008958F929F92AF92BF92CF92DF92EF92CB
:10016000FF92D1DF4B015C0188EEC82E83E0D82ED0
:10017000E12CF12CC8DF681979098A099B09683ECE
:10018000734081059105B0F321E0C21AD108E1085E
:10019000F10888EE880E83E0981EA11CB11CC114E2
:1001A000D104E104F10431F7FF90EF90DF90CF909C
:1001B000BF90AF909F908F9008951F920F920FB6AF
:1001C0000F9211242F933F938F939F93AF93BF93DD
:1001D0008091610090916200A0916300B0916400F1
:1001E0003091600023E0230F2D3768F126E8230FBC
:1001F0000296A11DB11D2093600080936100909331
:100200006200A0936300B0936400809165009091B8
:100210006600A0916700B09168000196A11DB11D14
:100220008093650090936600A0936700B093680088
:10023000BF91AF919F918F913F912F910F900FBEE2
:100240000F901F9018950196A11DB11DD4CF7894E1
:1002500083B7836083BF89B7816089BF82E08EBD29
:100260008EB581608EBD8FB581608FBD85B5846090
:1002700085BD85B5806485BD87E886B91AB8EBE58C
:10028000F0E02491E4E4F0E08491882399F090E098
:10029000880F991FFC01EA5DFF4FA591B491FC0105
:1002A000E05DFF4F859194918FB7F894EC91E22B2C
:1002B000EC938FBFC0E0D0E081E0F3DE4ADF80E066
:1002C000F0DE47DF2097C1F39BDEF6CFF894FFCF37
:00000001FF

I have merged your cross-posts @amir11228.

Cross-posting is against the Arduino forum rules. The reason is that duplicate posts can waste the time of the people trying to help. Someone might spend a lot of time investigating and writing a detailed answer on one topic, without knowing that someone else already did the same in the other topic.

You have already been asked multiple times to stop cross-posting. Since you don't respond to polite requests, we'll have to try a short account suspension. If you continue to cross-post after this, we will be forced to take stronger measures.

In the future, please only create one topic for each distinct subject matter. This is basic forum etiquette, as explained in the "How to get the best out of this forum" guide. It contains a lot of other useful information. Please read it.

Thanks in advance for your cooperation.

Unfortunately @amir11228 continued their pattern of bad behavior by creating a new account to circumvent the suspension, and using that account to create yet another cross-post. For this reason, they have been permanently suspended and so I am closing this topic as there is no reason to continue the discussion..