2012-02-23 21:38:56 -04:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.IO;
|
|
|
|
|
|
|
|
namespace uploader
|
|
|
|
{
|
|
|
|
public class IHex : SortedList<UInt32, byte[]>
|
|
|
|
{
|
|
|
|
public event ArdupilotMega._3DRradio.LogEventHandler LogEvent;
|
|
|
|
|
|
|
|
public event ArdupilotMega._3DRradio.ProgressEventHandler ProgressEvent;
|
|
|
|
|
|
|
|
private SortedList<UInt32, UInt32> merge_index;
|
|
|
|
|
|
|
|
public IHex ()
|
|
|
|
{
|
|
|
|
merge_index = new SortedList<UInt32, UInt32> ();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void load (string fromPath)
|
|
|
|
{
|
|
|
|
StreamReader sr = new StreamReader (fromPath);
|
|
|
|
UInt32 loadedSize = 0;
|
|
|
|
|
|
|
|
// discard anything we might previous have loaded
|
|
|
|
Clear ();
|
|
|
|
merge_index.Clear ();
|
|
|
|
|
|
|
|
log (string.Format ("reading from {0}\n", Path.GetFileName(fromPath)));
|
|
|
|
|
|
|
|
while (!sr.EndOfStream) {
|
|
|
|
string line = sr.ReadLine ();
|
|
|
|
|
|
|
|
// every line must start with a :
|
|
|
|
if (!line.StartsWith (":"))
|
|
|
|
throw new Exception ("invalid IntelHex file");
|
|
|
|
|
|
|
|
if (ProgressEvent != null)
|
|
|
|
ProgressEvent(sr.BaseStream.Position / (double)sr.BaseStream.Length);
|
|
|
|
|
|
|
|
// parse the record type and data length, assume ihex8
|
|
|
|
// ignore the checksum
|
|
|
|
byte length = Convert.ToByte (line.Substring (1, 2), 16);
|
|
|
|
UInt32 address = Convert.ToUInt32 (line.Substring (3, 4), 16);
|
|
|
|
byte rtype = Convert.ToByte (line.Substring (7, 2), 16);
|
|
|
|
|
|
|
|
// handle type zero (data) records
|
|
|
|
if (rtype == 0) {
|
|
|
|
byte[] b = new byte[length];
|
|
|
|
string hexbytes = line.Substring (9, length * 2);
|
|
|
|
|
|
|
|
// convert hex bytes
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
|
|
b [i] = Convert.ToByte (hexbytes.Substring (i * 2, 2), 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
log (string.Format ("ihex: 0x{0:X}: {1}\n", address, length), 1);
|
|
|
|
loadedSize += length;
|
|
|
|
|
|
|
|
// and add to the list of ranges
|
|
|
|
insert (address, b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (Count < 1)
|
|
|
|
throw new Exception ("no data in IntelHex file");
|
|
|
|
log (string.Format ("read {0} bytes from {1}\n", loadedSize, fromPath));
|
2012-05-11 06:07:52 -03:00
|
|
|
|
|
|
|
sr.Close();
|
2012-02-23 21:38:56 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
private void log (string message, int level = 0)
|
|
|
|
{
|
|
|
|
if (LogEvent != null)
|
|
|
|
LogEvent (message, level);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void idx_record (UInt32 start, byte[] data)
|
|
|
|
{
|
|
|
|
UInt32 len = (UInt32)data.GetLength (0);
|
|
|
|
|
|
|
|
merge_index.Add (start + len, start);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void idx_remove (UInt32 start, byte[] data)
|
|
|
|
{
|
|
|
|
UInt32 len = (UInt32)data.GetLength (0);
|
|
|
|
|
|
|
|
merge_index.Remove (start + len);
|
|
|
|
}
|
|
|
|
|
|
|
|
private bool idx_find (UInt32 start, out UInt32 other)
|
|
|
|
{
|
|
|
|
return merge_index.TryGetValue (start, out other);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void insert (UInt32 key, byte[] data)
|
|
|
|
{
|
|
|
|
UInt32 other;
|
|
|
|
byte[] mergedata;
|
|
|
|
|
|
|
|
// value of the key that would come after this one
|
|
|
|
other = key;
|
|
|
|
other += (UInt32)data.GetLength (0);
|
|
|
|
|
|
|
|
// can we merge with the next block
|
|
|
|
if (TryGetValue (other, out mergedata)) {
|
|
|
|
int oldlen = data.GetLength (0);
|
|
|
|
|
|
|
|
// remove the next entry, we are going to merge with it
|
|
|
|
Remove (other);
|
|
|
|
|
|
|
|
// remove its index entry as well
|
|
|
|
idx_remove (other, mergedata);
|
|
|
|
|
|
|
|
log (string.Format ("ihex: merging {0:X}/{1} with next {2:X}/{3}\n",
|
|
|
|
key, data.GetLength (0),
|
|
|
|
other, mergedata.GetLength (0)), 1);
|
|
|
|
|
|
|
|
// resize the data array and append data from the next block
|
|
|
|
Array.Resize (ref data, data.GetLength (0) + mergedata.GetLength (0));
|
|
|
|
Array.Copy (mergedata, 0, data, oldlen, mergedata.GetLength (0));
|
|
|
|
}
|
|
|
|
|
|
|
|
// look up a possible adjacent preceding block in the merge index
|
|
|
|
if (idx_find (key, out other)) {
|
|
|
|
|
|
|
|
mergedata = this [other];
|
|
|
|
int oldlen = mergedata.GetLength (0);
|
|
|
|
Remove (other);
|
|
|
|
idx_remove (other, mergedata);
|
|
|
|
|
|
|
|
log (string.Format ("ihex: merging {0:X}/{1} with prev {2:X}/{3}\n",
|
|
|
|
key, data.GetLength (0),
|
|
|
|
other, mergedata.GetLength (0)), 1);
|
|
|
|
|
|
|
|
Array.Resize (ref mergedata, data.GetLength (0) + mergedata.GetLength (0));
|
|
|
|
Array.Copy (data, 0, mergedata, oldlen, data.GetLength (0));
|
|
|
|
key = other;
|
|
|
|
data = mergedata;
|
|
|
|
}
|
|
|
|
|
|
|
|
// add the merged block
|
|
|
|
Add (key, data);
|
|
|
|
idx_record (key, data);
|
|
|
|
log (string.Format ("ihex: adding {0:X}/{1}\n", key, data.GetLength (0)), 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|