/** * Intel HEX Format Parser * Converts Intel HEX format to Uint8Array for AVR8 program memory * * Intel HEX format: * :LLAAAATT[DD...]CC * * LL = byte count * AAAA = address * TT = record type (00=data, 01=EOF) * DD = data bytes * CC = checksum */ export function hexToUint8Array(hexContent: string): Uint8Array { const lines = hexContent.split('\n').filter(line => line.trim().startsWith(':')); // Determine max address to size the array let maxAddress = 0; const dataRecords: Array<{ address: number; data: number[] }> = []; for (const line of lines) { const trimmed = line.trim(); if (!trimmed.startsWith(':')) continue; // Remove ':' and parse const bytes = trimmed.substring(1); // Parse record const byteCount = parseInt(bytes.substring(0, 2), 16); const address = parseInt(bytes.substring(2, 6), 16); const recordType = parseInt(bytes.substring(6, 8), 16); // Type 00 = data record if (recordType === 0x00) { const data: number[] = []; for (let i = 0; i < byteCount; i++) { const dataByte = parseInt(bytes.substring(8 + i * 2, 10 + i * 2), 16); data.push(dataByte); } dataRecords.push({ address, data }); maxAddress = Math.max(maxAddress, address + byteCount); } // Type 01 = end of file else if (recordType === 0x01) { break; } } // Create array with enough space const result = new Uint8Array(maxAddress); // Fill with data for (const record of dataRecords) { for (let i = 0; i < record.data.length; i++) { result[record.address + i] = record.data[i]; } } return result; } /** * Verify Intel HEX checksum */ export function verifyHexChecksum(line: string): boolean { if (!line.startsWith(':')) return false; const bytes = line.substring(1); let sum = 0; // Sum all bytes except checksum for (let i = 0; i < bytes.length - 2; i += 2) { sum += parseInt(bytes.substring(i, i + 2), 16); } // Get checksum const checksum = parseInt(bytes.substring(bytes.length - 2), 16); // Checksum = two's complement of sum return ((sum + checksum) & 0xFF) === 0; }