summaryrefslogtreecommitdiffstats
path: root/tools/hextosyx.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/hextosyx.cpp')
-rw-r--r--tools/hextosyx.cpp152
1 files changed, 152 insertions, 0 deletions
diff --git a/tools/hextosyx.cpp b/tools/hextosyx.cpp
new file mode 100644
index 0000000..fd761b2
--- /dev/null
+++ b/tools/hextosyx.cpp
@@ -0,0 +1,152 @@
1#include <iostream>
2#include <fstream>
3
4// Ported from the original Delphi version.
5// CLI parameters for ID, ByteWidth and BaseAddress removed for simplicity
6
7#include "intelhex.h"
8
9static const int ByteWidth = 32;
10static const int ID = 0x0051;
11
12static const unsigned char RESET[] = {0xf0, 0x00, 0x20, 0x29, 0x00, 0x71};
13
14// must match unpacking code in the bootloader, obviously
15static void eight_to_seven(unsigned char * Output, const int OOffset,
16 intelhex::hex_data& Input, const unsigned long IOffset)
17{
18 for (int i = 0; i < 7; ++i)
19 {
20 if (!Input.is_set(IOffset + i))
21 {
22 // pad unset addresses
23 Input.set(IOffset + i, 0xff);
24 }
25 }
26
27 // seven bytes of eight-bit data converted to
28 // eight bytes of seven-bit data
29 // render 8-bit words as 16-bit words
30 Output[OOffset+0] = Input[IOffset+0] >> 1;
31 Output[OOffset+1] = (Input[IOffset+0] << 6) + (Input[IOffset+1] >> 2);
32 Output[OOffset+2] = (Input[IOffset+1] << 5) + (Input[IOffset+2] >> 3);
33 Output[OOffset+3] = (Input[IOffset+2] << 4) + (Input[IOffset+3] >> 4);
34 Output[OOffset+4] = (Input[IOffset+3] << 3) + (Input[IOffset+4] >> 5);
35 Output[OOffset+5] = (Input[IOffset+4] << 2) + (Input[IOffset+5] >> 6);
36 Output[OOffset+6] = (Input[IOffset+5] << 1) + (Input[IOffset+6] >> 7);
37 Output[OOffset+7] = (Input[IOffset+6]);
38
39 for (int i = 0; i < 8; ++i)
40 {
41 Output[OOffset+i] &= 0x7f;
42 }
43}
44
45static void write_block(intelhex::hex_data& data, std::ofstream& ofs, const unsigned long addr, const unsigned char type)
46{
47 // packet header
48 ofs.write(reinterpret_cast<const char*>(RESET), 5);
49 ofs.put(type);
50
51 int incount = 0;
52 int outcount = 0;
53 int outn = 1 + (ByteWidth * 8) / 7;
54
55 // payload
56 unsigned char payload[41];
57
58 while (incount < ByteWidth)
59 {
60 eight_to_seven(payload, outcount, data, addr+incount);
61
62 incount += 7;
63 outcount += 8;
64 }
65
66 ofs.write(reinterpret_cast<const char*>(payload), outn);
67 ofs.put(0xf7);
68}
69
70static void write_header(intelhex::hex_data& data, std::ofstream& ofs, size_t BaseAddress)
71{
72 // human-readable version number & header block
73 ofs.write(reinterpret_cast<const char*>(RESET), 6);
74 ofs.put(ID >> 8);
75 ofs.put(ID & 0x7f);
76
77 ofs.put(data[BaseAddress + 0x132] >> 4);
78 ofs.put(data[BaseAddress + 0x132] & 0x0f);
79 ofs.put(data[BaseAddress + 0x131] >> 4);
80 ofs.put(data[BaseAddress + 0x131] & 0x0f);
81 ofs.put(data[BaseAddress + 0x130] >> 4);
82 ofs.put(data[BaseAddress + 0x130] & 0x0f);
83
84 ofs.put(0xf7);
85}
86
87static void write_checksum(intelhex::hex_data& data, std::ofstream& ofs)
88{
89 // device doesn't respect the checksum, but we still need this block!
90 ofs.write(reinterpret_cast<const char*>(RESET), 5);
91 unsigned char payload[19];
92
93 const char *FIRMWARE = "Firmware";
94
95 payload[0] = 0x76;
96 payload[1] = 0x00;
97 for (int i = 0; i < 8; ++i)
98 {
99 payload[i+2] = FIRMWARE[i];
100 }
101 payload[10] = 0x00;
102 payload[11] = 0x00;
103 payload[12] = 0x00;
104 payload[13] = 0x00;
105 payload[14] = 0x00;
106 payload[15] = 0x00;
107 payload[16] = 0x00;
108 payload[17] = 0x00;
109 payload[18] = 0xf7;
110
111 ofs.write(reinterpret_cast<const char*>(payload), 19);
112}
113
114int main(int argc, char *argv[])
115{
116 std::cout << "converting " << argv[1] << " to sysex file: " << argv[2] << std::endl;
117
118 // read the hex file input
119 intelhex::hex_data data;
120 data.load(argv[1]);
121
122 size_t BaseAddress = data.min_address();
123 size_t MaxAddress = data.max_address();
124
125 std::cout << "max addr: " << std::hex << data.max_address() << " min_addr: " << std::hex << data.min_address() << std::endl;
126
127 // create output file
128 std::ofstream ofs(argv[2] , std::ios::out | std::ios::binary);
129 if( !ofs )
130 return -1;
131
132 write_header(data, ofs, BaseAddress);
133
134 // payload blocks...
135 unsigned long i = BaseAddress + ByteWidth;
136
137 while (i < MaxAddress)
138 {
139 write_block(data, ofs, i, 0x72);
140
141 i += ByteWidth;
142 }
143
144 write_block(data, ofs, BaseAddress, 0x73);
145
146 // footer/checksum block
147 write_checksum(data, ofs);
148
149 ofs.close();
150
151 return 0;
152} \ No newline at end of file