Subversion Repositories svn.mios

Rev

Rev 693 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 693 Rev 721
1
/*
1
/*
2
 * @(#)HexFileUpload.java   beta8   2006/04/23
2
 * @(#)HexFileUpload.java   beta8   2006/04/23
3
 *
3
 *
4
 * Copyright (C) 2008    Adam King (adamjking@optusnet.com.au)
4
 * Copyright (C) 2008    Adam King (adamjking@optusnet.com.au)
5
 *
5
 *
6
 * This application is free software; you can redistribute it and/or modify
6
 * This application is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
9
 * (at your option) any later version.
10
 *
10
 *
11
 * This application is distributed in the hope that it will be useful,
11
 * This application is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
14
 * GNU General Public License for more details.
15
 *
15
 *
16
 * You should have received a copy of the GNU General Public License
16
 * You should have received a copy of the GNU General Public License
17
 * along with this application; if not, write to the Free Software
17
 * along with this application; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
19
 */
20
20
21
package org.midibox.mios;
21
package org.midibox.mios;
22
22
23
import java.io.File;
23
import java.io.File;
24
24
25
import javax.sound.midi.InvalidMidiDataException;
25
import javax.sound.midi.InvalidMidiDataException;
26
import javax.sound.midi.Receiver;
26
import javax.sound.midi.Receiver;
27
import javax.sound.midi.SysexMessage;
27
import javax.sound.midi.SysexMessage;
28
28
29
import org.midibox.utils.Utils;
29
import org.midibox.utils.Utils;
30
30
31
public class HexFileUpload extends MIOSSysexSendReceive {
31
public class HexFileUpload extends MIOSSysexSendReceive {
32
32
33
    public final static Object FILE = new Object();
33
    public final static Object FILE = new Object();
34
-
 
35
    public final static Object BANKSTICK_NO = new Object();
-
 
36
34
37
    public final static Object UPLOAD_MODE = new Object();
35
    public final static Object UPLOAD_MODE = new Object();
38
36
39
    public final static Object WAIT_FOR_UPLOAD = new Object();
37
    public final static Object WAIT_FOR_UPLOAD = new Object();
40
38
41
    public final static Object DELAY_TIME = new Object();
39
    public final static Object DELAY_TIME = new Object();
42
   
40
   
43
    public final static String REBOOT = "REBOOT";
41
    public final static String REBOOT = "REBOOT";
44
42
45
    public final static int SMART_MODE = 0;
43
    public final static int SMART_MODE = 0;
46
44
47
    public final static int DUMB_MODE = 1;
45
    public final static int DUMB_MODE = 1;
48
46
49
    private File file;
47
    private File file;
50
48
51
    private int bankstickNo;
49
    //private int bankstickNo;
52
50
53
    private int uploadMode;
51
    private int uploadMode;
54
52
55
    private boolean waitForUploadRequest;
53
    private boolean waitForUploadRequest;
56
54
57
    private int delayTime;
55
    private int delayTime;
58
56
59
    private long fileLastModified;
57
    private long fileLastModified;
60
58
61
    private boolean fileLastMIOS32_Mode;
59
    private boolean fileLastMIOS32_Mode;
62
60
63
    private HexFile hexFile;
61
    private HexFile hexFile;
64
62
65
    private int currentBlock;
63
    private int currentBlock;
66
64
67
    private int totalBlocks;
65
    private int totalBlocks;
68
66
69
    private boolean expectUploadRequest = false;
67
    private boolean expectUploadRequest = false;
70
68
71
    private boolean expectQueryReply = false;
69
    private boolean expectQueryReply = false;
72
70
73
    private byte expectQueryReplyNumber = 0;
71
    private byte expectQueryReplyNumber = 0;
74
72
75
    private boolean expectDummyError = false;
73
    private boolean expectDummyError = false;
76
74
77
    private boolean gotGoodAck = false;
75
    private boolean gotGoodAck = false;
78
76
79
    private int uploadAttempt = 0;
77
    private int uploadAttempt = 0;
80
78
81
    private int currentChecksum;
79
    private int currentChecksum;
82
80
83
    private int nUploadCase;
81
    private int nUploadCase;
84
82
85
    public HexFileUpload(Receiver receiver) {
83
    public HexFileUpload(Receiver receiver) {
86
        super(receiver);
84
        super(receiver);
87
-
 
88
        this.bankstickNo = 0;
-
 
89
-
 
90
        this.deviceID = 0;
-
 
91
85
92
        this.waitForUploadRequest = false;
86
        this.waitForUploadRequest = false;
93
87
94
        this.uploadMode = 0;
88
        this.uploadMode = 0;
95
89
96
        this.delayTime = 300;
90
        this.delayTime = 300;
97
    }
91
    }
98
92
99
    public File getFile() {
93
    public File getFile() {
100
        return file;
94
        return file;
101
    }
95
    }
102
96
103
    public boolean fileChanged() {
97
    public boolean fileChanged() {
104
        return file.lastModified() != fileLastModified;
98
        return file.lastModified() != fileLastModified;
105
    }
99
    }
106
100
107
    public void setFile(File file) {
101
    public void setFile(File file) {
108
        this.file = file;
102
        this.file = file;
109
        fileLastModified = file.lastModified();
103
        fileLastModified = file.lastModified();
110
104
111
        readHexFile();
105
        readHexFile();
112
106
113
        setChanged();
107
        setChanged();
114
        notifyObservers(FILE);
108
        notifyObservers(FILE);
115
        clearChanged();
109
        clearChanged();
116
    }
110
    }
117
111
118
    public void readHexFile() {
112
    public void readHexFile() {
119
        hexFile = new HexFile();
113
        hexFile = new HexFile();
120
        fileLastMIOS32_Mode = getMIOS32_Mode();
114
        fileLastMIOS32_Mode = isMIOS32Mode();
121
        if (!hexFile.read(file.getPath(), fileLastMIOS32_Mode)) {
115
        if (!hexFile.read(file.getPath(), fileLastMIOS32_Mode)) {
122
            // TODO
116
            // TODO
123
        }
117
        }
124
    }
118
    }
125
119
126
    public int getBankstickNo() {
-
 
127
        return bankstickNo;
-
 
128
    }
-
 
129
-
 
130
    public void setBankstickNo(int bankstickNo) {
-
 
131
        this.bankstickNo = bankstickNo;
-
 
132
-
 
133
        setChanged();
-
 
134
        notifyObservers(BANKSTICK_NO);
-
 
135
        clearChanged();
-
 
136
    }
-
 
137
120
138
    public int getDelayTime() {
121
    public int getDelayTime() {
139
        return delayTime;
122
        return delayTime;
140
    }
123
    }
141
124
142
    public void setDelayTime(int delayTime) {
125
    public void setDelayTime(int delayTime) {
143
        this.delayTime = delayTime;
126
        this.delayTime = delayTime;
144
127
145
        setChanged();
128
        setChanged();
146
        notifyObservers(DELAY_TIME);
129
        notifyObservers(DELAY_TIME);
147
        clearChanged();
130
        clearChanged();
148
    }
131
    }
149
132
150
    public int getUploadMode() {
133
    public int getUploadMode() {
151
        return uploadMode;
134
        return uploadMode;
152
    }
135
    }
153
136
154
    public void setUploadMode(int uploadMode) {
137
    public void setUploadMode(int uploadMode) {
155
        this.uploadMode = uploadMode;
138
        this.uploadMode = uploadMode;
156
139
157
        setChanged();
140
        setChanged();
158
        notifyObservers(UPLOAD_MODE);
141
        notifyObservers(UPLOAD_MODE);
159
        clearChanged();
142
        clearChanged();
160
    }
143
    }
161
144
162
    public boolean isWaitForUploadRequest() {
145
    public boolean isWaitForUploadRequest() {
163
        return waitForUploadRequest;
146
        return waitForUploadRequest;
164
    }
147
    }
165
148
166
    public void setWaitForUploadRequest(boolean waitForUploadRequest) {
149
    public void setWaitForUploadRequest(boolean waitForUploadRequest) {
167
        this.waitForUploadRequest = waitForUploadRequest;
150
        this.waitForUploadRequest = waitForUploadRequest;
168
151
169
        setChanged();
152
        setChanged();
170
        notifyObservers(WAIT_FOR_UPLOAD);
153
        notifyObservers(WAIT_FOR_UPLOAD);
171
        clearChanged();
154
        clearChanged();
172
    }
155
    }
173
156
174
    public void createUpload() {
157
    public void createUpload() {
175
158
176
        expectQueryReply = false;
159
        expectQueryReply = false;
177
        cancelled = false;
160
        cancelled = false;
178
        done = false;
161
        done = false;
179
162
180
        setChanged();
163
        setChanged();
181
        notifyObservers(WORKER);
164
        notifyObservers(WORKER);
182
        clearChanged();
165
        clearChanged();
183
166
184
        nUploadCase = 0;
167
        nUploadCase = 0;
185
       
168
       
186
        synchronized (this) {
169
        synchronized (this) {
187
170
188
            addMessage("Starting upload of " + file.getName());
171
            addMessage("Starting upload of " + file.getName());
189
172
190
            if (fileLastMIOS32_Mode != getMIOS32_Mode()) {
173
            if (fileLastMIOS32_Mode != isMIOS32Mode()) {
191
                addMessage("MIOS version has been changed - reloading file");
174
                addMessage("MIOS version has been changed - reloading file");
192
                readHexFile();
175
                readHexFile();
193
            }
176
            }
194
177
195
            // TK: determine .hex file type, we have three cases:
178
            // TK: determine .hex file type, we have three cases:
196
            // (only relevant for PIC MIOS, not for MIOS32)
179
            // (only relevant for PIC MIOS, not for MIOS32)
197
            // (1) .hex file contains code between 0x0400-0x2fff: MIOS
180
            // (1) .hex file contains code between 0x0400-0x2fff: MIOS
198
            // range, upload via bootloader
181
            // range, upload via bootloader
199
            // (0x000-0x3ff for downward compatibility with MIOS V1.8 and
182
            // (0x000-0x3ff for downward compatibility with MIOS V1.8 and
200
            // lower)
183
            // lower)
201
            // (2) .hex file contains code between 0x3000 and 0x30ff: start
184
            // (2) .hex file contains code between 0x3000 and 0x30ff: start
202
            // vector of application, upload via MIOS
185
            // vector of application, upload via MIOS
203
            // (0) .hex file contains flash data >= 0x3100 (no special
186
            // (0) .hex file contains flash data >= 0x3100 (no special
204
            // measure), EEPROM or BankStick data
187
            // measure), EEPROM or BankStick data
205
188
206
            // in case (1) we force a reboot and always wait for an upload
189
            // in case (1) we force a reboot and always wait for an upload
207
            // request
190
            // request
208
            // in case (1) we upload a stall code to 0x400 in order to
191
            // in case (1) we upload a stall code to 0x400 in order to
209
            // ensure, that the new code
192
            // ensure, that the new code
210
            // won't be started before the upload is completely passed
193
            // won't be started before the upload is completely passed
211
            // in case (2) we upload a stall code to 0x3000
194
            // in case (2) we upload a stall code to 0x3000
212
195
213
            // in case (1) and (2) we upload the first block (0x400 or
196
            // in case (1) and (2) we upload the first block (0x400 or
214
            // 0x3000) at the end!
197
            // 0x3000) at the end!
215
198
216
            expectUploadRequest = false;
199
            expectUploadRequest = false;
217
            expectDummyError = false;
200
            expectDummyError = false;
218
            boolean forceRebootReq = false;
201
            boolean forceRebootReq = false;
219
202
220
            if (!getMIOS32_Mode()) {
203
            if (!isMIOS32Mode()) {
221
                for (int i = 0; i < hexFile.getBlockCount(); ++i) {
204
                for (int i = 0; i < hexFile.getBlockCount(); ++i) {
222
                    Block block = hexFile.getBlock(i);
205
                    Block block = hexFile.getBlock(i);
223
                    long lAddressMapped = block.lAddressMapped;
206
                    long lAddressMapped = block.lAddressMapped;
224
                    if (lAddressMapped >= 0x0000 && lAddressMapped <= 0x2fff) {
207
                    if (lAddressMapped >= 0x0000 && lAddressMapped <= 0x2fff) {
225
                        nUploadCase = 1;
208
                        nUploadCase = 1;
226
                    } else if (nUploadCase != 1 && lAddressMapped >= 0x3000
209
                    } else if (nUploadCase != 1 && lAddressMapped >= 0x3000
227
                            && lAddressMapped <= 0x30ff) {
210
                            && lAddressMapped <= 0x30ff) {
228
                        nUploadCase = 2;
211
                        nUploadCase = 2;
229
                    }
212
                    }
230
                }
213
                }
231
214
232
                if (uploadMode == 0 && nUploadCase == 1) {
215
                if (uploadMode == 0 && nUploadCase == 1) {
233
                    expectUploadRequest = true;
216
                    expectUploadRequest = true;
234
                }
217
                }
235
218
236
                if (nUploadCase == 1) {
219
                if (nUploadCase == 1) {
237
                    addMessage("Hex file contains code in MIOS range, forcing reboot for upload via 1st level bootloader!\nThe reboot request will lead to an error acknowledge, please ignore!");
220
                    addMessage("Hex file contains code in MIOS range, forcing reboot for upload via 1st level bootloader!\nThe reboot request will lead to an error acknowledge, please ignore!");
238
                    forceRebootReq = true;
221
                    forceRebootReq = true;
239
                }
222
                }
240
223
241
            } else {
224
            } else {
242
                nUploadCase = 1; // MIOS32 - always request reset
225
                nUploadCase = 1; // MIOS32 - always request reset
243
226
244
                expectUploadRequest = true;
227
                expectUploadRequest = true;
245
                forceRebootReq = true;
228
                forceRebootReq = true;
246
229
247
                addMessage("Requesting reboot...");
230
                addMessage("Requesting reboot...");
248
            }
231
            }
249
232
250
            totalBlocks = hexFile.getBlockCount();
233
            totalBlocks = hexFile.getBlockCount();
251
            if (totalBlocks == 0) {
234
            if (totalBlocks == 0) {
252
                done = true;
235
                done = true;
253
                addMessage("Hex file is empty, or wrong MIOS version selected (e.g. check for MIOS32)");
236
                addMessage("Hex file is empty, or wrong MIOS version selected (e.g. check for MIOS32)");
254
                return;
237
                return;
255
            }
238
            }
256
239
257
            // "wait until upload request" goes here.
240
            // "wait until upload request" goes here.
258
            if (waitForUploadRequest) {
241
            if (waitForUploadRequest) {
259
                expectUploadRequest = true;
242
                expectUploadRequest = true;
260
            }
243
            }
261
244
262
            if (expectUploadRequest) {
245
            if (expectUploadRequest) {
263
                addMessage("Waiting for upload request...");
246
                addMessage("Waiting for upload request...");
264
            }
247
            }
265
248
266
            while (expectUploadRequest && !cancelled) {
249
            while (expectUploadRequest && !cancelled) {
267
                if (forceRebootReq) { // TK: ensure that expectUploadRequest
250
                if (forceRebootReq) { // TK: ensure that expectUploadRequest
268
                    // is set before message will be sent
251
                    // is set before message will be sent
269
                    // (race condition)
252
                    // (race condition)
270
                    forceRebootReq = false;
253
                    forceRebootReq = false;
271
                    forceReboot();
254
                    forceReboot();
272
                }
255
                }
273
256
274
                try {
257
                try {
275
                    wait();
258
                    wait();
276
259
277
                    // receivedRead routine sets expectUploadRequest to
260
                    // receivedRead routine sets expectUploadRequest to
278
                    // false once it has been received
261
                    // false once it has been received
279
                    if (!expectUploadRequest) {
262
                    if (!expectUploadRequest) {
280
                        // Thread.sleep(1500);
263
                        // Thread.sleep(1500);
281
                    }
264
                    }
282
                } catch (Exception e) {
265
                } catch (Exception e) {
283
                    addMessage("Error: Cannot wait for upload request");
266
                    addMessage("Error: Cannot wait for upload request");
284
                }
267
                }
285
            }
268
            }
286
269
287
            // don't move the variable initialisation at this location!!!
270
            // don't move the variable initialisation at this location!!!
288
            // it can happen, that a MIDIbox has been powered off during upload
271
            // it can happen, that a MIDIbox has been powered off during upload
289
            // - in this case,
272
            // - in this case,
290
            // the previous attempt to upload a code block can get stucked
273
            // the previous attempt to upload a code block can get stucked
291
            // setting currentBlock to 0 at this location ensures, that we are
274
            // setting currentBlock to 0 at this location ensures, that we are
292
            // starting with the first block!
275
            // starting with the first block!
293
            long timeUploadBegin = System.currentTimeMillis();
276
            long timeUploadBegin = System.currentTimeMillis();
294
            currentBlock = 0;
277
            currentBlock = 0;
295
            uploadAttempt = 0;
278
            uploadAttempt = 0;
296
279
297
            while (!cancelled && !done) {
280
            while (!cancelled && !done) {
298
281
299
                // This ensures _bDone is set correctly.
282
                // This ensures _bDone is set correctly.
300
                if (currentBlock >= totalBlocks) {
283
                if (currentBlock >= totalBlocks) {
301
                    done = true;
284
                    done = true;
302
                    long timeUploadEnd = System.currentTimeMillis();
285
                    long timeUploadEnd = System.currentTimeMillis();
303
                    float timeUpload = (float) (timeUploadEnd - timeUploadBegin) / 1000;
286
                    float timeUpload = (float) (timeUploadEnd - timeUploadBegin) / 1000;
304
                    float transferRateKb = ((totalBlocks * 256) / timeUpload) / 1024;
287
                    float transferRateKb = ((totalBlocks * 256) / timeUpload) / 1024;
305
                   
288
                   
306
                    addMessage("Upload of " + (totalBlocks * 256)
289
                    addMessage("Upload of " + (totalBlocks * 256)
307
                            + " bytes completed after " + timeUpload + "s ("
290
                            + " bytes completed after " + timeUpload + "s ("
308
                            + transferRateKb + " kb/s)");
291
                            + transferRateKb + " kb/s)");
309
292
310
                    // reboot BSL in MIOS32 mode
293
                    // reboot BSL in MIOS32 mode
311
                    if (getMIOS32_Mode()) {
294
                    if (isMIOS32Mode()) {
312
                        forceReboot();
295
                        forceReboot();
313
                    } else {
296
                    } else {
314
                       
297
                       
315
                        setChanged();
298
                        setChanged();
316
                        notifyObservers(REBOOT);
299
                        notifyObservers(REBOOT);
317
                        clearChanged();    
300
                        clearChanged();    
318
                    }                  
301
                    }                  
319
                   
302
                   
320
                    break;
303
                    break;
321
                }
304
                }
322
305
323
                Block block = hexFile.getBlock(currentBlock);
306
                Block block = hexFile.getBlock(currentBlock);
324
                long lAddress = block.lAddress;
307
                long lAddress = block.lAddress;
325
                long lAddressMapped = block.lAddressMapped;
308
                long lAddressMapped = block.lAddressMapped;
326
309
327
                byte[] axDumpData = Utils.convertTo7Bit(block.axData);
310
                byte[] axDumpData = Utils.convertTo7Bit(block.axData);
328
311
329
                long lAddressExtension = 0x00;
312
                long lAddressExtension = 0x00;
330
                byte[] axAddress;
313
                byte[] axAddress;
331
314
332
                if (!getMIOS32_Mode()) {
315
                if (!isMIOS32Mode()) {
333
                    // build address/len field of MIOS SysEx message
316
                    // build address/len field of MIOS SysEx message
334
317
335
                    if (lAddress >= HexFile.HEX_FILE_FLASH_ADDRESS_START
318
                    if (lAddress >= HexFile.HEX_FILE_FLASH_ADDRESS_START
336
                            && lAddress <= HexFile.HEX_FILE_FLASH_ADDRESS_END) {
319
                            && lAddress <= HexFile.HEX_FILE_FLASH_ADDRESS_END) {
337
                        lAddressExtension = (lAddress >> 15) & 0x07;
320
                        lAddressExtension = (lAddress >> 15) & 0x07;
338
                        lAddressMapped &= 0x7fff;
321
                        lAddressMapped &= 0x7fff;
339
                        // System.out.println("Flash");
322
                        // System.out.println("Flash");
340
                    } else if (lAddress >= HexFile.HEX_FILE_EEPROM_ADDRESS_START
323
                    } else if (lAddress >= HexFile.HEX_FILE_EEPROM_ADDRESS_START
341
                            && lAddress <= HexFile.HEX_FILE_EEPROM_ADDRESS_END) {
324
                            && lAddress <= HexFile.HEX_FILE_EEPROM_ADDRESS_END) {
342
                        // System.out.println("EEPROM");
325
                        // System.out.println("EEPROM");
343
                    } else if (lAddress >= HexFile.HEX_FILE_BANKSTICK_ADDRESS_START
326
                    } else if (lAddress >= HexFile.HEX_FILE_BANKSTICK_ADDRESS_START
344
                            && lAddress <= HexFile.HEX_FILE_BANKSTICK_ADDRESS_END) {
327
                            && lAddress <= HexFile.HEX_FILE_BANKSTICK_ADDRESS_END) {
345
                        // System.out.println("Bankstick");
328
                        // System.out.println("Bankstick");
346
                        lAddressExtension = (lAddress >> 16) & 0x07;
329
                        lAddressExtension = (lAddress >> 16) & 0x07;
347
                        lAddressMapped = (lAddressMapped & 0xffff) | 0x10000;
330
                        lAddressMapped = (lAddressMapped & 0xffff) | 0x10000;
348
                    }
331
                    }
349
332
350
                    else {
333
                    else {
351
                        // Invalid range, do nothing.
334
                        // Invalid range, do nothing.
352
                        System.out.println("invalid");
335
                        System.out.println("invalid");
353
                        currentBlock++;
336
                        currentBlock++;
354
                        continue;
337
                        continue;
355
                    }
338
                    }
356
339
357
                    axAddress = new byte[4];
340
                    axAddress = new byte[4];
358
                    axAddress[0] = (byte) ((lAddressMapped >> 10) & 0x7F);
341
                    axAddress[0] = (byte) ((lAddressMapped >> 10) & 0x7F);
359
                    axAddress[1] = (byte) ((lAddressMapped >> 3) & 0x7F);
342
                    axAddress[1] = (byte) ((lAddressMapped >> 3) & 0x7F);
360
                    axAddress[2] = (byte) ((block.axData.length >> 10) & 0x7F);
343
                    axAddress[2] = (byte) ((block.axData.length >> 10) & 0x7F);
361
                    axAddress[3] = (byte) ((block.axData.length >> 3) & 0x7F);
344
                    axAddress[3] = (byte) ((block.axData.length >> 3) & 0x7F);
362
345
363
                } else {
346
                } else {
364
                    // build address/len field of MIOS32 SysEx message
347
                    // build address/len field of MIOS32 SysEx message
365
348
366
                    axAddress = new byte[8];
349
                    axAddress = new byte[8];
367
                    axAddress[0] = (byte) ((lAddressMapped >> 25) & 0x7F);
350
                    axAddress[0] = (byte) ((lAddressMapped >> 25) & 0x7F);
368
                    axAddress[1] = (byte) ((lAddressMapped >> 18) & 0x7F);
351
                    axAddress[1] = (byte) ((lAddressMapped >> 18) & 0x7F);
369
                    axAddress[2] = (byte) ((lAddressMapped >> 11) & 0x7F);
352
                    axAddress[2] = (byte) ((lAddressMapped >> 11) & 0x7F);
370
                    axAddress[3] = (byte) ((lAddressMapped >> 4) & 0x7F);
353
                    axAddress[3] = (byte) ((lAddressMapped >> 4) & 0x7F);
371
                    axAddress[4] = (byte) ((block.axData.length >> 25) & 0x7F);
354
                    axAddress[4] = (byte) ((block.axData.length >> 25) & 0x7F);
372
                    axAddress[5] = (byte) ((block.axData.length >> 18) & 0x7F);
355
                    axAddress[5] = (byte) ((block.axData.length >> 18) & 0x7F);
373
                    axAddress[6] = (byte) ((block.axData.length >> 11) & 0x7F);
356
                    axAddress[6] = (byte) ((block.axData.length >> 11) & 0x7F);
374
                    axAddress[7] = (byte) ((block.axData.length >> 4) & 0x7F);
357
                    axAddress[7] = (byte) ((block.axData.length >> 4) & 0x7F);
375
                }
358
                }
376
359
377
                currentChecksum = Utils
360
                currentChecksum = Utils
378
                        .calculateChecksum(axAddress, axDumpData);
361
                        .calculateChecksum(axAddress, axDumpData);
379
362
380
                byte[] axSysExData = new byte[7 + axAddress.length
363
                byte[] axSysExData = new byte[7 + axAddress.length
381
                        + axDumpData.length + 2];
364
                        + axDumpData.length + 2];
382
                axSysExData[0] = (byte) 0xF0;
365
                axSysExData[0] = (byte) 0xF0;
383
                axSysExData[1] = (byte) 0x00;
366
                axSysExData[1] = (byte) 0x00;
384
                axSysExData[2] = (byte) 0x00;
367
                axSysExData[2] = (byte) 0x00;
385
                axSysExData[3] = (byte) 0x7E;
368
                axSysExData[3] = (byte) 0x7E;
386
                axSysExData[4] = getMIOS_SysExId();
369
                axSysExData[4] = getMIOS_SysExId();
387
                axSysExData[5] = (byte) (deviceID & 0x7F);
370
                axSysExData[5] = (byte) (deviceID & 0x7F);
388
                axSysExData[6] = (byte) (0x02 | (lAddressExtension << 4)); // Write
371
                axSysExData[6] = (byte) (0x02 | (lAddressExtension << 4)); // Write
389
372
390
                System
373
                System
391
                        .arraycopy(axAddress, 0, axSysExData, 7,
374
                        .arraycopy(axAddress, 0, axSysExData, 7,
392
                                axAddress.length); // insert address
375
                                axAddress.length); // insert address
393
                System.arraycopy(axDumpData, 0, axSysExData,
376
                System.arraycopy(axDumpData, 0, axSysExData,
394
                        7 + axAddress.length, axDumpData.length); // insert
377
                        7 + axAddress.length, axDumpData.length); // insert
395
                // data
378
                // data
396
379
397
                axSysExData[axSysExData.length - 2] = (byte) currentChecksum; // Checksum
380
                axSysExData[axSysExData.length - 2] = (byte) currentChecksum; // Checksum
398
                // is
381
                // is
399
                // second-last
382
                // second-last
400
                axSysExData[axSysExData.length - 1] = (byte) 0xF7; // SysEx
383
                axSysExData[axSysExData.length - 1] = (byte) 0xF7; // SysEx
401
                // status
384
                // status
402
                // byte is
385
                // byte is
403
                // last
386
                // last
404
387
405
                String s = "Sending block #"
388
                String s = "Sending block #"
406
                        + (currentBlock + 1)
389
                        + (currentBlock + 1)
407
                        + " "
390
                        + " "
408
                        + Utils.longToHex(block.lAddress)
391
                        + Utils.longToHex(block.lAddress)
409
                        + "-"
392
                        + "-"
410
                        + Utils.longToHex(block.lAddress + block.axData.length
393
                        + Utils.longToHex(block.lAddress + block.axData.length
411
                                - 1);
394
                                - 1);
412
                // + " (" + Utils.longToHex(lAddressExtension) + ":" +
395
                // + " (" + Utils.longToHex(lAddressExtension) + ":" +
413
                // Utils.longToHex(lAddressMapped) + ")";
396
                // Utils.longToHex(lAddressMapped) + ")";
414
397
415
                addMessage(s);
398
                addMessage(s);
416
399
417
                try {
400
                try {
418
                    gotGoodAck = false;
401
                    gotGoodAck = false;
419
                    SysexMessage sysExMessage = new SysexMessage();
402
                    SysexMessage sysExMessage = new SysexMessage();
420
                    sysExMessage.setMessage(axSysExData, axSysExData.length);
403
                    sysExMessage.setMessage(axSysExData, axSysExData.length);
421
404
422
                    receiver.send(sysExMessage, -1);
405
                    receiver.send(sysExMessage, -1);
423
                    uploadAttempt++;
406
                    uploadAttempt++;
424
                } catch (InvalidMidiDataException ex) {
407
                } catch (InvalidMidiDataException ex) {
425
                    cancelled = true;
408
                    cancelled = true;
426
                    addMessage("Error: " + ex.getMessage());
409
                    addMessage("Error: " + ex.getMessage());
427
                    break;
410
                    break;
428
                }
411
                }
429
412
430
                try {
413
                try {
431
                    if (uploadMode == 0) {
414
                    if (uploadMode == 0) {
432
                        wait();
415
                        wait();
433
                        // TK: ensure that block won't be incremented if we
416
                        // TK: ensure that block won't be incremented if we
434
                        // haven't got an acknowledge
417
                        // haven't got an acknowledge
435
                        if (gotGoodAck)
418
                        if (gotGoodAck)
436
                            currentBlock++;
419
                            currentBlock++;
437
                    } else {
420
                    } else {
438
                        wait(delayTime);
421
                        wait(delayTime);
439
                        currentBlock++;
422
                        currentBlock++;
440
                    }
423
                    }
441
424
442
                } catch (InterruptedException e) {
425
                } catch (InterruptedException e) {
443
                    cancelled = true;
426
                    cancelled = true;
444
                    addMessage("Error: Upload task interrupted");
427
                    addMessage("Error: Upload task interrupted");
445
                    break;
428
                    break;
446
                }
429
                }
447
            }
430
            }
448
        }
431
        }
449
    }
432
    }
450
433
451
    public void createQuery() {
434
    public void createQuery() {
452
435
453
        if (!getMIOS32_Mode()) {
436
        if (!isMIOS32Mode()) {
454
            addMessage("Query is only supported for MIOS32");
437
            addMessage("Query is only supported for MIOS32");
455
            return;
438
            return;
456
        }
439
        }
457
440
458
        expectQueryReply = false;
441
        expectQueryReply = false;
459
        cancelled = false;
442
        cancelled = false;
460
        done = false;
443
        done = false;
461
444
462
        setChanged();
445
        setChanged();
463
        notifyObservers(WORKER);
446
        notifyObservers(WORKER);
464
        clearChanged();
447
        clearChanged();
465
448
466
        synchronized (this) {
449
        synchronized (this) {
467
450
468
            expectQueryReplyNumber = 0x01;
451
            expectQueryReplyNumber = 0x01;
469
452
470
            while (!cancelled && !done) {
453
            while (!cancelled && !done) {
471
454
472
                // build query request
455
                // build query request
473
                byte[] queryCode = new byte[9];
456
                byte[] queryCode = new byte[9];
474
                queryCode[0] = (byte) 0xF0;
457
                queryCode[0] = (byte) 0xF0;
475
                queryCode[1] = (byte) 0x00;
458
                queryCode[1] = (byte) 0x00;
476
                queryCode[2] = (byte) 0x00;
459
                queryCode[2] = (byte) 0x00;
477
                queryCode[3] = (byte) 0x7E;
460
                queryCode[3] = (byte) 0x7E;
478
                queryCode[4] = getMIOS_SysExId();
461
                queryCode[4] = getMIOS_SysExId();
479
                queryCode[5] = (byte) (deviceID & 0x7F); // device-id
462
                queryCode[5] = (byte) (deviceID & 0x7F); // device-id
480
                queryCode[6] = (byte) 0x00; // query command
463
                queryCode[6] = (byte) 0x00; // query command
481
                queryCode[7] = (byte) expectQueryReplyNumber;
464
                queryCode[7] = (byte) expectQueryReplyNumber;
482
                queryCode[8] = (byte) 0xF7;
465
                queryCode[8] = (byte) 0xF7;
483
466
484
                try {
467
                try {
485
                    SysexMessage sysExMessage = new SysexMessage();
468
                    SysexMessage sysExMessage = new SysexMessage();
486
                    sysExMessage.setMessage(queryCode, queryCode.length);
469
                    sysExMessage.setMessage(queryCode, queryCode.length);
487
                    receiver.send(sysExMessage, -1);
470
                    receiver.send(sysExMessage, -1);
488
                } catch (InvalidMidiDataException ex) {
471
                } catch (InvalidMidiDataException ex) {
489
                    cancelled = true;
472
                    cancelled = true;
490
                    addMessage("Error: " + ex.getMessage());
473
                    addMessage("Error: " + ex.getMessage());
491
                    break;
474
                    break;
492
                }
475
                }
493
476
494
                expectQueryReply = true;
477
                expectQueryReply = true;
495
                while (!cancelled && expectQueryReply) {
478
                while (!cancelled && expectQueryReply) {
496
                    try {
479
                    try {
497
                        wait();
480
                        wait();
498
                    } catch (Exception e) {
481
                    } catch (Exception e) {
499
                        addMessage("Error: Cannot wait for query reply");
482
                        addMessage("Error: Cannot wait for query reply");
500
                    }
483
                    }
501
                }
484
                }
502
485
503
                if (!cancelled) {
486
                if (!cancelled) {
504
                    if (expectQueryReplyNumber < 0x09) {
487
                    if (expectQueryReplyNumber < 0x09) {
505
                        ++expectQueryReplyNumber;
488
                        ++expectQueryReplyNumber;
506
                    } else {
489
                    } else {
507
                        done = true;
490
                        done = true;
508
                        addMessage("All queries done.");
491
                        addMessage("All queries done.");
509
                    }
492
                    }
510
                }
493
                }
511
            }
494
            }
512
        }
495
        }
513
    }
496
    }
514
497
515
    public void forceReboot() {
498
    public void forceReboot() {
516
499
517
        byte[] forceRebootCode;
500
        byte[] forceRebootCode;
518
501
519
        if (getMIOS32_Mode()) {
502
        if (isMIOS32Mode()) {
520
            forceRebootCode = new byte[9];
503
            forceRebootCode = new byte[9];
521
            forceRebootCode[0] = (byte) 0xF0;
504
            forceRebootCode[0] = (byte) 0xF0;
522
            forceRebootCode[1] = (byte) 0x00;
505
            forceRebootCode[1] = (byte) 0x00;
523
            forceRebootCode[2] = (byte) 0x00;
506
            forceRebootCode[2] = (byte) 0x00;
524
            forceRebootCode[3] = (byte) 0x7E;
507
            forceRebootCode[3] = (byte) 0x7E;
525
            forceRebootCode[4] = getMIOS_SysExId();
508
            forceRebootCode[4] = getMIOS_SysExId();
526
            forceRebootCode[5] = (byte) (deviceID & 0x7F); // device-id
509
            forceRebootCode[5] = (byte) (deviceID & 0x7F); // device-id
527
            forceRebootCode[6] = (byte) 0x00; // query command
510
            forceRebootCode[6] = (byte) 0x00; // query command
528
            forceRebootCode[7] = (byte) 0x7f; // enter BSL
511
            forceRebootCode[7] = (byte) 0x7f; // enter BSL
529
            forceRebootCode[8] = (byte) 0xF7;
512
            forceRebootCode[8] = (byte) 0xF7;
530
        } else {
513
        } else {
531
            forceRebootCode = new byte[14];
514
            forceRebootCode = new byte[14];
532
515
533
            // dummy write operation, core will return error 01 "less bytes than
516
            // dummy write operation, core will return error 01 "less bytes than
534
            // expected"
517
            // expected"
535
            expectDummyError = true;
518
            expectDummyError = true;
536
519
537
            forceRebootCode[0] = (byte) 0xF0;
520
            forceRebootCode[0] = (byte) 0xF0;
538
            forceRebootCode[1] = (byte) 0x00;
521
            forceRebootCode[1] = (byte) 0x00;
539
            forceRebootCode[2] = (byte) 0x00;
522
            forceRebootCode[2] = (byte) 0x00;
540
            forceRebootCode[3] = (byte) 0x7E;
523
            forceRebootCode[3] = (byte) 0x7E;
541
            forceRebootCode[4] = getMIOS_SysExId();
524
            forceRebootCode[4] = getMIOS_SysExId();
542
            forceRebootCode[5] = (byte) (deviceID & 0x7F); // device-id
525
            forceRebootCode[5] = (byte) (deviceID & 0x7F); // device-id
543
            forceRebootCode[6] = (byte) 0x02; // dummy write
526
            forceRebootCode[6] = (byte) 0x02; // dummy write
544
            forceRebootCode[7] = (byte) 0x00; // dummy address
527
            forceRebootCode[7] = (byte) 0x00; // dummy address
545
            forceRebootCode[8] = (byte) 0x00;
528
            forceRebootCode[8] = (byte) 0x00;
546
            forceRebootCode[9] = (byte) 0x00;
529
            forceRebootCode[9] = (byte) 0x00;
547
            forceRebootCode[10] = (byte) 0x00; // dummy count
530
            forceRebootCode[10] = (byte) 0x00; // dummy count
548
            forceRebootCode[11] = (byte) 0x00;
531
            forceRebootCode[11] = (byte) 0x00;
549
            forceRebootCode[12] = (byte) 0x00; // dummy byte
532
            forceRebootCode[12] = (byte) 0x00; // dummy byte
550
            forceRebootCode[13] = (byte) 0xF7;
533
            forceRebootCode[13] = (byte) 0xF7;
551
        }
534
        }
552
535
553
        try {
536
        try {
554
            SysexMessage sysExMessage = new SysexMessage();
537
            SysexMessage sysExMessage = new SysexMessage();
555
            sysExMessage.setMessage(forceRebootCode, forceRebootCode.length);
538
            sysExMessage.setMessage(forceRebootCode, forceRebootCode.length);
556
            receiver.send(sysExMessage, -1);
539
            receiver.send(sysExMessage, -1);
557
           
540
           
558
            setChanged();
541
            setChanged();
559
            notifyObservers(REBOOT);
542
            notifyObservers(REBOOT);
560
            clearChanged();
543
            clearChanged();
561
           
544
           
562
        } catch (InvalidMidiDataException ex) {
545
        } catch (InvalidMidiDataException ex) {
563
            cancelled = true;
546
            cancelled = true;
564
            addMessage("Error: " + ex.getMessage());
547
            addMessage("Error: " + ex.getMessage());
565
            return;
548
            return;
566
        }
549
        }
567
    }
550
    }
568
551
569
    protected void retryBlock() {
552
    protected void retryBlock() {
570
        if (uploadAttempt > 15) { // TKNEW
553
        if (uploadAttempt > 15) { // TKNEW
571
            cancelled = true;
554
            cancelled = true;
572
            addMessage("Aborting after 16 errors");
555
            addMessage("Aborting after 16 errors");
573
            uploadAttempt = 0; // reset counter
556
            uploadAttempt = 0; // reset counter
574
            gotGoodAck = true;
557
            gotGoodAck = true;
575
        }
558
        }
576
    }
559
    }
577
560
578
    protected void receivedErrorCode(byte[] data) {
561
    protected void receivedErrorCode(byte[] data) {
579
        synchronized (this) {
562
        synchronized (this) {
580
            super.receivedErrorCode(data);
563
            super.receivedErrorCode(data);
581
564
582
            int errorCode = data[6];
565
            int errorCode = data[6];
583
            if (expectDummyError) {
566
            if (expectDummyError) {
584
                expectDummyError = false;
567
                expectDummyError = false;
585
                addMessage("This was an expected error - please ignore!");
568
                addMessage("This was an expected error - please ignore!");
586
            } else if (errorCode == 8) {
569
            } else if (errorCode == 8) {
587
                addMessage("Skipping this code block due to invalid address range!");
570
                addMessage("Skipping this code block due to invalid address range!");
588
                notify();
571
                notify();
589
            } else if (expectQueryReply && errorCode == 13) {
572
            } else if (expectQueryReply && errorCode == 13) {
590
                expectQueryReply = false; // query not supported - skip it
573
                expectQueryReply = false; // query not supported - skip it
591
                addMessage("Query Request #" + expectQueryReplyNumber
574
                addMessage("Query Request #" + expectQueryReplyNumber
592
                        + " not supported by core!");
575
                        + " not supported by core!");
593
                notify();
576
                notify();
594
            } else if (uploadMode == 0) {
577
            } else if (uploadMode == 0) {
595
                retryBlock();
578
                retryBlock();
596
                notify();
579
                notify();
597
            }
580
            }
598
        }
581
        }
599
    }
582
    }
600
583
601
    protected void receivedReturnValues(byte[] data) {
584
    protected void receivedReturnValues(byte[] data) {
602
        synchronized (this) {
585
        synchronized (this) {
603
            StringBuffer buffer = new StringBuffer();
586
            StringBuffer buffer = new StringBuffer();
604
587
605
            if (expectQueryReply) {
588
            if (expectQueryReply) {
606
                int i;
589
                int i;
607
                String str = "";
590
                String str = "";
608
                for (i = 6; i < data.length - 1; ++i) {
591
                for (i = 6; i < data.length - 1; ++i) {
609
                    str += (char) data[i];
592
                    str += (char) data[i];
610
                }
593
                }
611
594
612
                switch (expectQueryReplyNumber) {
595
                switch (expectQueryReplyNumber) {
613
                case 0x01:
596
                case 0x01:
614
                    buffer.append("Operating System: " + str);
597
                    buffer.append("Operating System: " + str);
615
                    break;
598
                    break;
616
                case 0x02:
599
                case 0x02:
617
                    buffer.append("Board: " + str);
600
                    buffer.append("Board: " + str);
618
                    break;
601
                    break;
619
                case 0x03:
602
                case 0x03:
620
                    buffer.append("Core Family: " + str);
603
                    buffer.append("Core Family: " + str);
621
                    break;
604
                    break;
622
                case 0x04:
605
                case 0x04:
623
                    buffer.append("Chip ID: 0x" + str);
606
                    buffer.append("Chip ID: 0x" + str);
624
                    break;
607
                    break;
625
                case 0x05:
608
                case 0x05:
626
                    buffer.append("Serial Number: #" + str);
609
                    buffer.append("Serial Number: #" + str);
627
                    break;
610
                    break;
628
                case 0x06:
611
                case 0x06:
629
                    buffer.append("Flash Memory Size: " + str + " bytes");
612
                    buffer.append("Flash Memory Size: " + str + " bytes");
630
                    break;
613
                    break;
631
                case 0x07:
614
                case 0x07:
632
                    buffer.append("RAM Size: " + str + " bytes");
615
                    buffer.append("RAM Size: " + str + " bytes");
633
                    break;
616
                    break;
634
                case 0x08: // Application First Line
617
                case 0x08: // Application First Line
635
                case 0x09: // Application Second Line
618
                case 0x09: // Application Second Line
636
                    buffer.append(str);
619
                    buffer.append(str);
637
                    break;
620
                    break;
638
                default:
621
                default:
639
                    buffer.append("Query #" + expectQueryReplyNumber + ": "
622
                    buffer.append("Query #" + expectQueryReplyNumber + ": "
640
                            + str);
623
                            + str);
641
                }
624
                }
642
                expectQueryReply = false;
625
                expectQueryReply = false;
643
626
644
            } else if (uploadMode == 0) {
627
            } else if (uploadMode == 0) {
645
628
646
                // TK: FIXME - checksum is located at data[6] ---
629
                // TK: FIXME - checksum is located at data[6] ---
647
                // data[data.length - 2] can fail if more than one message
630
                // data[data.length - 2] can fail if more than one message
648
                // is returned (Java/M-Audio MIDI bug)
631
                // is returned (Java/M-Audio MIDI bug)
649
                // byte checkSum = (byte) data[data.length - 2];
632
                // byte checkSum = (byte) data[data.length - 2];
650
                byte checkSum = (byte) data[6];
633
                byte checkSum = (byte) data[6];
651
634
652
                buffer.append("Received Checksum: ");
635
                buffer.append("Received Checksum: ");
653
                buffer.append(Utils.byteToHex(checkSum));
636
                buffer.append(Utils.byteToHex(checkSum));
654
                if (checkSum == currentChecksum) {
637
                if (checkSum == currentChecksum) {
655
                    buffer.append(" - OK");
638
                    buffer.append(" - OK");
656
                    uploadAttempt = 0;
639
                    uploadAttempt = 0;
657
                    gotGoodAck = true;
640
                    gotGoodAck = true;
658
                } else {
641
                } else {
659
                    buffer.append(" - Error");
642
                    buffer.append(" - Error");
660
                    retryBlock();
643
                    retryBlock();
661
                }
644
                }
662
            } else {
645
            } else {
663
                buffer.append("Received acknowledgement response");
646
                buffer.append("Received acknowledgement response");
664
            }
647
            }
665
            addMessage(buffer.toString());
648
            addMessage(buffer.toString());
666
            if (uploadMode == 0) {
649
            if (uploadMode == 0) {
667
                notify();
650
                notify();
668
            }
651
            }
669
        }
652
        }
670
    }
653
    }
671
654
672
    protected void receivedRead(byte[] data) {
655
    protected void receivedRead(byte[] data) {
673
        synchronized (this) {
656
        synchronized (this) {
674
            if (expectUploadRequest) {
657
            if (expectUploadRequest) {
675
                addMessage("Received Upload Request");
658
                addMessage("Received Upload Request");
676
                expectUploadRequest = false; // must be set to false, so
659
                expectUploadRequest = false; // must be set to false, so
677
                // that wait routine
660
                // that wait routine
678
                // continues
661
                // continues
679
            } else {
662
            } else {
680
                addMessage("Error: Received unexpected Upload Request");
663
                addMessage("Error: Received unexpected Upload Request");
681
            }
664
            }
682
            currentBlock = 0; // in any case: re-starting with first block
665
            currentBlock = 0; // in any case: re-starting with first block
683
            notify(); // TK: notify *after* expectUploadRequest has been
666
            notify(); // TK: notify *after* expectUploadRequest has been
684
            // changed!
667
            // changed!
685
        }
668
        }
686
    }
669
    }
687
}
670
}
688
 
671