1 //
2 // srecord - Manipulate EPROM load files
3 // Copyright (C) 2011 Peter Miller
4 //
5 // This program is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU Lesser General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or (at
8 // your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 //
18
19 #include <cstring>
20
21 #include <srecord/output/file/ppb.h>
22 #include <srecord/record.h>
23
24
~output_file_ppb()25 srecord::output_file_ppb::~output_file_ppb()
26 {
27 if (!seen_some_data)
28 fatal_error("no data records");
29 if (buffer_length > 0)
30 buffer_flush();
31 packet(0, 0, 0);
32 }
33
34
output_file_ppb(const std::string & a_file_name)35 srecord::output_file_ppb::output_file_ppb(
36 const std::string &a_file_name
37 ) :
38 srecord::output_file(a_file_name),
39 address(-1uL),
40 buffer_length(0),
41 seen_some_data(false)
42 {
43 }
44
45
46 srecord::output::pointer
create(const std::string & a_file_name)47 srecord::output_file_ppb::create(const std::string &a_file_name)
48 {
49 return pointer(new srecord::output_file_ppb(a_file_name));
50 }
51
52
53 void
write(const srecord::record & record)54 srecord::output_file_ppb::write(const srecord::record &record)
55 {
56 switch (record.get_type())
57 {
58 default:
59 // ignore
60 break;
61
62 case srecord::record::type_header:
63 // ignore
64 break;
65
66 case srecord::record::type_data:
67 for (size_t j = 0; j < record.get_length(); ++j)
68 {
69 unsigned char data = record.get_data(j);
70 unsigned long data_address = record.get_address() + j;
71
72 if (data_address != address)
73 {
74 buffer_flush();
75 address = data_address;
76 }
77 buffer[buffer_length++] = data;
78 ++address;
79 if (buffer_length >= sizeof(buffer))
80 buffer_flush();
81 seen_some_data = true;
82 }
83 break;
84
85 case srecord::record::type_execution_start_address:
86 // ignore
87 break;
88 }
89 }
90
91
92 void
line_length_set(int)93 srecord::output_file_ppb::line_length_set(int)
94 {
95 // Ignore.
96 }
97
98
99 bool
preferred_block_size_set(int nbytes)100 srecord::output_file_ppb::preferred_block_size_set(int nbytes)
101 {
102 return (nbytes >= 2 && nbytes <= record::max_data_length);
103 }
104
105
106 void
address_length_set(int)107 srecord::output_file_ppb::address_length_set(int)
108 {
109 // Ignore
110 }
111
112
113 int
preferred_block_size_get(void) const114 srecord::output_file_ppb::preferred_block_size_get(void)
115 const
116 {
117 // Use the largest we can get.
118 return srecord::record::max_data_length;
119 }
120
121
122 const char *
format_name(void) const123 srecord::output_file_ppb::format_name(void)
124 const
125 {
126 return "Stag Prom Programmer Binary";
127 }
128
129
130 void
put_bin_4be(unsigned long value)131 srecord::output_file_ppb::put_bin_4be(unsigned long value)
132 {
133 put_char(value >> 24);
134 put_char(value >> 16);
135 put_char(value >> 8);
136 put_char(value);
137 }
138
139
140 void
packet(unsigned long address,const unsigned char * data,size_t data_size)141 srecord::output_file_ppb::packet(unsigned long address,
142 const unsigned char *data, size_t data_size)
143 {
144 enum { SOH = 1 };
145 enum { CSLEN = 1024 };
146
147 put_char(SOH);
148 put_bin_4be(data_size);
149 put_bin_4be(address);
150 unsigned char chksum = 0;
151 for (size_t j = 0; j < data_size; ++j)
152 {
153 if (j > 0 && (j % CSLEN) == 0)
154 put_char(-chksum);
155 put_char(data[j]);
156 chksum += data[j];
157 }
158 put_char(-chksum);
159 }
160
161
162 void
buffer_flush(void)163 srecord::output_file_ppb::buffer_flush(void)
164 {
165 if (buffer_length > 0)
166 {
167 packet(address - buffer_length, buffer, buffer_length);
168 buffer_length = 0;
169 }
170 }
171
172
173 bool
is_binary(void) const174 srecord::output_file_ppb::is_binary(void)
175 const
176 {
177 return true;
178 }
179
180
181 // vim: set ts=8 sw=4 et :
182