Subversion Repositories Projects

Rev

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

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