// // srecord - manipulate eprom load files // Copyright (C) 2003, 2006, 2007 Peter Miller // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see // . // #include #include srec_output_file_intel16::srec_output_file_intel16( const std::string &a_file_name) : srec_output_file(a_file_name), address_base(0), pref_block_size(32) { // The address base always has the lower 16 bits set to zero. // By making it be 1, we force the first data record to emit an // address base record first. } srec_output_file_intel16::~srec_output_file_intel16() { if (!data_only_flag) write_inner(1, 0L, 0, 0); } void srec_output_file_intel16::write_inner(int tag, unsigned long address, const void *data, int data_nbytes) { // // Make sure the line is not too long. // if (data_nbytes >= 255*2) fatal_error("data length (%d) too long", data_nbytes); // // Emit the line as hexadecimal text. // put_char(':'); checksum_reset(); put_byte(data_nbytes >> 1); unsigned char tmp[2]; srec_record::encode_big_endian(tmp, address, 2); put_byte(tmp[0]); put_byte(tmp[1]); put_byte(tag); const unsigned char *data_p = (const unsigned char *)data; for (int j = 0; j < data_nbytes; ++j) { // Note: bytes are ordered HI,LO so we invert put_byte(data_p[j ^ 1]); } put_byte(-checksum_get()); put_char('\n'); } void srec_output_file_intel16::write(const srec_record &record) { unsigned char tmp[4]; switch (record.get_type()) { case srec_record::type_header: // // This format can't do header records // break; case srec_record::type_data: if ((record.get_address() & 1) || (record.get_length() & 1)) fatal_alignment_error(2); if ((record.get_address() & 0xFFFE0000) != address_base) { address_base = record.get_address() & 0xFFFE0000; srec_record::encode_big_endian(tmp, record.get_address() >> 17, 2); write_inner(4, 0L, tmp, 2); } write_inner ( 0, (record.get_address() >> 1) & 0x0000FFFF, record.get_data(), record.get_length() ); break; case srec_record::type_data_count: // ignore break; case srec_record::type_start_address: if (data_only_flag) break; if (record.get_address() == 0) break; srec_record::encode_big_endian(tmp, record.get_address() >> 1, 4); write_inner(5, 0L, tmp, 4); break; case srec_record::type_unknown: fatal_error("can't write unknown record type"); break; } } void srec_output_file_intel16::line_length_set(int n) { // // Given the number of characters, figure the maximum number of // data baytes. // n = ((n - 11) / 2) & ~1; // // Constrain based on the file format. // (255*2 is the largest that will fit in the data size field) // if (n < 2) n = 2; else if (n > 255*2) n = 255*2; // // An additional constraint is the size of the srec_record // data buffer. // if (n > (srec_record::max_data_length & ~1)) n = (srec_record::max_data_length & ~1); pref_block_size = n; } void srec_output_file_intel16::address_length_set(int) { // ignore } int srec_output_file_intel16::preferred_block_size_get() const { return pref_block_size; } const char * srec_output_file_intel16::format_name() const { return "Intel-16"; }