Subversion Repositories Projects

Rev

Rev 1562 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1539 - 1
package dongfang.mkt.serial;
2
 
3
import java.io.IOException;
4
import java.io.InputStream;
5
import java.io.OutputStream;
6
 
1564 - 7
import dongfang.mkt.datatype.GPSBearingAndRange;
8
import dongfang.mkt.datatype.GPSPosition;
1539 - 9
import dongfang.mkt.frames.AllDisplaysResponseFrame;
10
import dongfang.mkt.frames.AnalogDebugLabelResponseFrame;
11
import dongfang.mkt.frames.AttitudeDataResponseFrame;
12
import dongfang.mkt.frames.ChangeParameterSetResponseFrame;
1562 - 13
import dongfang.mkt.frames.CompassHeadingResponseFrame;
1539 - 14
import dongfang.mkt.frames.ConfirmFrame;
15
import dongfang.mkt.frames.DebugResponseFrame;
16
import dongfang.mkt.frames.MotorTestResponseFrame;
1559 - 17
import dongfang.mkt.frames.OSDDataResponseFrame;
18
import dongfang.mkt.frames.ReadExternalControlResponseFrame;
1539 - 19
import dongfang.mkt.frames.ResponseFrame;
20
import dongfang.mkt.frames.SetCompassHeadingResponseFrame;
21
import dongfang.mkt.frames.UniversalReadParamSetResponseFrame;
22
import dongfang.mkt.frames.UniversalWriteParamSetResponseFrame;
23
import dongfang.mkt.frames.VariablesResponseFrame;
24
import dongfang.mkt.frames.VersionResponseFrame;
25
 
1564 - 26
/*
1539 - 27
public class MKInputStream extends InputStream {
28
        int readByteCnt;
29
        class MKDataInputStream {
30
                int[] inbuf = new int[4];
31
                int[] outbuf = new int[3];
32
                int outbufptr = outbuf.length; // reset to "buffer empty"
33
 
34
                private boolean decode() throws IOException {
35
                        for (int i = 0; i < 4; i++) {
36
                                int raw = MKInputStream.this.readByte();
37
                                int in = raw - '=';
38
                                if (in < 0 || in > 63)
39
                                        return false;
40
                                        // throw new IOException("Out of range data received where frame data expected. Probably the frame was shorter than expected (" + readByteCnt + ")!");
41
                                inbuf[i] = in;
42
                                readByteCnt++;
43
                        }
44
                        outbuf[0] = (inbuf[0] << 2) | (inbuf[1] >>> 4);
45
                        outbuf[1] = ((inbuf[1] & 0x0f) << 4) | (inbuf[2] >>> 2);
46
                        outbuf[2] = ((inbuf[2] & 0x03) << 6) | inbuf[3];
47
                        outbufptr = 0;
48
                        return true;
49
                }
50
 
51
                public void reset() {
52
                        outbufptr = outbuf.length; // reset to "buffer empty"
53
                }
54
 
55
                public int readByte() throws IOException {
56
                        if (outbufptr > 2 && !decode())
57
                                        throw new IOException("Out of range data received where frame data expected. Probably the frame was shorter than expected (" + readByteCnt + ")!");            
58
                        return outbuf[outbufptr++];
59
                }
60
 
1559 - 61
                public int readSignedByte() throws IOException {
62
                        byte result = (byte)readByte();
63
                        return result;
64
                }
65
 
1539 - 66
                public int readWord() throws IOException {
1559 - 67
                        int byte0 = readByte();
1539 - 68
                        int byte1 = readByte();
1559 - 69
                        return (byte1 << 8) | byte0;
1539 - 70
                }
71
 
72
                public int readSignedWord() throws IOException {
73
                        int word = readWord();
74
                        if (word > 32767)
75
                                word = word - 65536;
76
                        return word;
77
                }
1559 - 78
 
79
                public int readSignedDWord() throws IOException {
80
                        int byte0 = readByte();
81
                        int byte1 = readByte();
82
                        int byte2 = readByte();
83
                        int byte3 = readByte();
84
                        return (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0;
85
                }
1539 - 86
 
87
                public int[] readBytes(int length) throws IOException {
88
                        int[] result = new int[length];
89
                        for (int i = 0; i < length; i++) {
90
                                result[i] = readByte();
91
                        }
92
                        return result;
93
                }
94
 
95
                public int[] readWords(int length) throws IOException {
96
                        int[] result = new int[length];
97
                        for (int i = 0; i < length; i++) {
98
                                result[i] = readWord();
99
                        }
100
                        return result;
101
                }
102
 
1562 - 103
                public int[] readSignedWords(int length) throws IOException {
104
                        int[] result = new int[length];
105
                        for (int i = 0; i < length; i++) {
106
                                result[i] = readSignedWord();
107
                        }
108
                        return result;
109
                }
110
 
1539 - 111
                public char[] readChars(int length) throws IOException {
112
                        char[] result = new char[length];
113
                        for (int i = 0; i < length; i++) {
114
                                // Here, a 1:1 mapping between byte values and char codes is assumed.
115
                                // That means we're assuming ISO-8859-1 (= the first 256 code points
116
                                // of Unicode, which Java uses for chars)
117
                                result[i] = (char) readByte();
118
                        }
119
                        return result;
120
                }
121
        }
122
 
1559 - 123
        MKDataInputStream base64InputStream = new MKDataInputStream();
1539 - 124
        OutputStream nonPacketSpillway = null; //System.err;
125
 
126
        final InputStream is;
127
        int crc;
128
 
129
        public MKInputStream(InputStream is) {
130
                this.is = is;
131
        }
132
 
133
        @Override
134
        public int read() throws IOException {
135
                int i;
136
                while ((i=is.read()) == -1);
137
                // System.out.print("Received: " + i + " (as char: " + (char)i + ")\n");
138
                return i;
139
        }
140
 
141
        public int readByte() throws IOException {
142
                int _byte = read();
143
                if (_byte < 0)
144
                        throw new IOException("End of Stream!");
145
                crc += _byte;
146
                return _byte;
147
        }
148
 
149
        public MKDataInputStream getBase64InputStream() {
1559 - 150
                return base64InputStream;
1539 - 151
        }
152
 
153
        public ResponseFrame getNextFrame() throws IOException {
154
                int c;
155
                while ((c = read()) != '#') {
156
                        // throw it on some scrap-text buffer.
157
                        if (nonPacketSpillway != null)
158
                                nonPacketSpillway.write(c);
159
                }
160
                crc = '#';
1559 - 161
                base64InputStream.reset();
1539 - 162
                int address = readByte() - 'a';
163
                int iid = readByte();
164
                readByteCnt = 0;
165
                //RESPONSE_IDS id = getResponseType(iid);
166
                ResponseFrame result;
1562 - 167
//              System.out.println("Received a: " + (char)iid + " from " + address);
1539 - 168
                switch (iid) {
169
                case 'A': {
170
                        AnalogDebugLabelResponseFrame f = new AnalogDebugLabelResponseFrame(address);
1559 - 171
                        f.setChannel(base64InputStream.readByte());
172
                        f.setLabel(base64InputStream.readChars(16));
1539 - 173
                        result = f;
174
                        break;
175
                }
176
                case 'B': {
177
                        ConfirmFrame f = new ConfirmFrame(address);
1559 - 178
                        f.setFrameNum(base64InputStream.readByte());
1539 - 179
                        result = f;
180
                        break;
181
                }
182
                case 'C': {
183
                        AttitudeDataResponseFrame f = new AttitudeDataResponseFrame(address);
1559 - 184
                        f.setPitch(base64InputStream.readSignedWord());
185
                        f.setRoll(base64InputStream.readSignedWord());
186
                        f.setHeading(base64InputStream.readSignedWord());
187
                        f.setExpansion(base64InputStream.readBytes(8));
1539 - 188
                        result = f;
189
                        break;
190
                }
191
                case 'D': {
192
                        DebugResponseFrame f = new DebugResponseFrame(address);
193
                        for (int i=0; i<2; i++)
1559 - 194
                                f.setDigital(i, base64InputStream.readByte());
1539 - 195
                        for (int i=0; i<32; i++)
1559 - 196
                                f.setAnalog(i, base64InputStream.readSignedWord());
1539 - 197
                        result = f;
198
                        break;
199
                }
200
                case 'F': {
201
                        ChangeParameterSetResponseFrame f = new ChangeParameterSetResponseFrame(address);
1559 - 202
                        f.setParameterSetNumber(base64InputStream.readByte());
1539 - 203
                        result = f;
204
                        break;
205
                }
1559 - 206
                case 'G': {
207
                        ReadExternalControlResponseFrame f = new ReadExternalControlResponseFrame(address);
208
                        f.setDigital(base64InputStream.readBytes(2));
209
                        f.setRemoteButtons(base64InputStream.readByte());
210
                        f.setPitch(base64InputStream.readByte());
211
                        f.setRoll(base64InputStream.readByte());
212
                        f.setYaw(base64InputStream.readByte());
213
                        f.setThrottle(base64InputStream.readByte());
214
                        f.setHeight(base64InputStream.readByte());
215
                        f.setCommand(base64InputStream.readByte());
216
                        f.setFrameNum(base64InputStream.readByte());
217
                        f.setArgument(base64InputStream.readByte());
218
                        result = f;
219
                        break;
220
                }
1539 - 221
                case 'H': {
222
                        AllDisplaysResponseFrame f = new AllDisplaysResponseFrame(address);
1559 - 223
                        f.setLine(base64InputStream.readByte());
1539 - 224
                        //f.setMaxItem(getDataInputStream().readByte());
1559 - 225
                        f.setText(base64InputStream.readChars(20));
1539 - 226
                        result = f;
227
                        break;
228
                }
1562 - 229
                case 'k' : {
230
                        CompassHeadingResponseFrame f = new CompassHeadingResponseFrame(address);
231
                        base64InputStream.readSignedWords(2);
232
                        base64InputStream.readBytes(2);
233
                        base64InputStream.readByte();
234
                        base64InputStream.readByte();
235
                        result = f;
236
                        break;
237
                }
1539 - 238
                case 'L': {
239
                        AllDisplaysResponseFrame f = new AllDisplaysResponseFrame(address);
1559 - 240
                        f.setItem(base64InputStream.readByte());
1539 - 241
                        // f.setMaxItem(getDataInputStream().readByte());
1559 - 242
                        f.setText(base64InputStream.readChars(80));
1539 - 243
                        result = f;
244
                        break;
245
                }
1559 - 246
                case 'O': {
247
                        OSDDataResponseFrame f = new OSDDataResponseFrame(address);
248
                        f.setVersion(base64InputStream.readByte());
249
 
250
                        GPSPosition pos = new GPSPosition();
251
                        pos.setLongitude(base64InputStream.readSignedDWord());
252
                        pos.setLatitude(base64InputStream.readSignedDWord());
253
                        pos.setAltitude(base64InputStream.readSignedDWord());
254
                        pos.setStatus(base64InputStream.readByte());
255
                        f.setCurrentPosition(pos);
256
 
257
                        pos = new GPSPosition();
258
                        pos.setLongitude(base64InputStream.readSignedDWord());
259
                        pos.setLatitude(base64InputStream.readSignedDWord());
260
                        pos.setAltitude(base64InputStream.readSignedDWord());
261
                        pos.setStatus(base64InputStream.readByte());
262
                        f.setTargetPosition(pos);
263
 
1564 - 264
                        GPSBearingAndRange rnb = new GPSBearingAndRange();
1559 - 265
                        rnb.setDistance(base64InputStream.readWord());
266
                        rnb.setBearing(base64InputStream.readSignedWord());
267
                        f.setCurrentToTarget(rnb);
268
 
269
                        pos = new GPSPosition();
270
                        pos.setLongitude(base64InputStream.readSignedDWord());
271
                        pos.setLatitude(base64InputStream.readSignedDWord());
272
                        pos.setAltitude(base64InputStream.readSignedDWord());
273
                        pos.setStatus(base64InputStream.readByte());
274
                        f.setHomePosition(pos);
275
 
1564 - 276
                        rnb = new GPSBearingAndRange();
1559 - 277
                        rnb.setDistance(base64InputStream.readWord());
278
                        rnb.setBearing(base64InputStream.readSignedWord());
279
                        f.setCurrentToHome(rnb);
280
 
281
                        f.setWaypointIndex(base64InputStream.readByte());
282
                        f.setWaypointCount(base64InputStream.readByte());
283
                        f.setNumberOfSatellites(base64InputStream.readByte());
284
 
285
                        f.setHeightByPressure(base64InputStream.readSignedWord());
286
                        f.setVerticalVelocityByPressure(base64InputStream.readSignedWord());
287
                        f.setFlightTime(base64InputStream.readWord());
288
                        f.setBatteryVoltage(base64InputStream.readByte());
289
                        f.setGroundSpeed(base64InputStream.readWord());
290
 
1562 - 291
                        f.setDirectionOfFlight(base64InputStream.readSignedWord());
1559 - 292
                        f.setCompassHeading(base64InputStream.readSignedWord());
293
 
294
                        f.setPitchAngle(base64InputStream.readSignedByte());
295
                        f.setRollAngle(base64InputStream.readSignedByte());
296
 
297
                        f.setRcQuality(base64InputStream.readByte());
298
                        f.setFcFlags(base64InputStream.readByte());
299
                        f.setNcFlags(base64InputStream.readByte());
300
                        f.setErrorCode(base64InputStream.readByte());
301
                        f.setOperatingRadius(base64InputStream.readByte());
302
 
303
                        f.setVerticalVelocityByGPS(base64InputStream.readSignedWord());
304
                        f.setTargetLoiterTime(base64InputStream.readByte());
305
                        f.setFcFlags2(base64InputStream.readByte());
306
                        f.setSetpointForAltitude(base64InputStream.readSignedWord());
307
                        f.setThrottle(base64InputStream.readByte());
308
                        f.setCurrent(base64InputStream.readWord());
309
                        f.setCapacityUsed(base64InputStream.readWord());
310
                        result = f;
311
                        break;
312
}
1539 - 313
                case 'S': {
314
                        UniversalWriteParamSetResponseFrame f = new UniversalWriteParamSetResponseFrame(address);
1559 - 315
                        f.setParameterSetNumber(base64InputStream.readByte());
1539 - 316
                        result = f;
317
                        break;
318
                }
319
                case 'T': {
320
                        MotorTestResponseFrame f = new MotorTestResponseFrame(address);
321
                        result = f;
322
                        break;
323
                }
1564 - 324
                / *
1539 - 325
                 * We have a collision with the 'x' token: Also used for VariablesRequest.
326
                case 'x': {
327
                        LoopbackTestResponseFrame f = new LoopbackTestResponseFrame(address);
328
                        f.setByte(getDataInputStream().readByte());
329
                        f.setWord(getDataInputStream().readWord());
330
                        f.setChararray(getDataInputStream().readChars(8));
331
                        result = f;
332
                        break;
333
                }
1564 - 334
            * /
1539 - 335
                case 'V': {
336
                        VersionResponseFrame f = new VersionResponseFrame(address);
1559 - 337
                        f.setSWMajor(base64InputStream.readByte());
338
                        f.setSWMinor(base64InputStream.readByte());
339
                        f.setProtoMajor(base64InputStream.readByte());
340
                        f.setProtoMinor(base64InputStream.readByte());
341
                        f.setSWPatch(base64InputStream.readByte());
342
                        f.setHardwareErrors(base64InputStream.readBytes(5));
1539 - 343
                        result = f;
344
                        break;
345
                }
346
 
347
                // This is my own creation. The ID collides with the waypoint one of FC.
348
                case 'X': {
349
                        VariablesResponseFrame f = new VariablesResponseFrame(address);
1559 - 350
                        f.setVariables(base64InputStream.readWords(8));
1539 - 351
                        result = f;
352
                        break;
353
                }
354
                case 'w': {
355
                        SetCompassHeadingResponseFrame f = new SetCompassHeadingResponseFrame(address);
356
                        // do stuff.
1564 - 357
                        / *
1539 - 358
                        ToMk3Mag.Attitude[0] = (int16_t)((10 * angle[PITCH]) / GYRO_DEG_FACTOR_PITCHROLL); // approx. 0.1 deg
359
                        ToMk3Mag.Attitude[1] = (int16_t)((10 * angle[ROLL]) / GYRO_DEG_FACTOR_PITCHROLL); // approx. 0.1 deg
360
                        ToMk3Mag.UserParam[0] = dynamicParams.UserParams[0];
361
                        ToMk3Mag.UserParam[1] = dynamicParams.UserParams[1];
362
                        ToMk3Mag.CalState = compassCalState;
1564 - 363
                        * /
1539 - 364
                        // Waste 8 bytes to make CRC match.
1559 - 365
                        base64InputStream.readBytes(8);
1539 - 366
                        result = f;
367
                        break;
368
                }
369
                case 'Q':
370
                        UniversalReadParamSetResponseFrame f = new UniversalReadParamSetResponseFrame(address);
1559 - 371
                        f.setConfigurationSetNumber(base64InputStream.readByte());
372
                        f.setConfigurationVersion(base64InputStream.readByte());
373
                        int length = base64InputStream.readByte();
374
                        f.setData(base64InputStream.readBytes(length));
1539 - 375
                        result = f;
376
                        break;
377
                default:
1562 - 378
                        int b;
379
                        int count = 0;
380
                        while((b=read()) != '\r') {
381
                                count++;
382
                        }
383
                        System.err.println("Unknown frame " + (char)iid + " received from " + address);
384
                        System.err.println("It appears to have " + (count-2) + " data bytes (encoded)");
385
                        System.err.println("(" + (count-2) * 6/8 + " data bytes decoded)");
1539 - 386
                        result = null;
387
                }
388
 
389
                int receivedCRC = (read() - '=') << 6;
390
                receivedCRC += (read() - '=');
391
                crc %= 4096;
392
                if (receivedCRC != crc) {
393
                        /// System.err.println("Expected CRC: " + crc + ", got CRC: " + receivedCRC);
394
                        throw new IOException("CRC mismatch! Calculated crc: " + (int)crc + "; received check crc: " + receivedCRC + ", difference: " + Math.abs(crc - receivedCRC));
395
                }
396
                if (read() != '\r') {
397
                        throw new IOException("CR at end of frame missing");
398
                }
399
 
400
                return result;
401
        }
402
}
1564 - 403
*/