1 package net.sf.mbus4j.encoder;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 import java.util.Arrays;
31 import java.util.Calendar;
32 import java.util.logging.Logger;
33 import net.sf.mbus4j.MBusUtils;
34
35 import net.sf.mbus4j.dataframes.ApplicationReset;
36 import net.sf.mbus4j.dataframes.ControlFrame;
37 import net.sf.mbus4j.dataframes.Frame;
38 import net.sf.mbus4j.dataframes.GeneralApplicationError;
39 import net.sf.mbus4j.dataframes.LongFrame;
40 import net.sf.mbus4j.dataframes.PrimaryAddress;
41 import net.sf.mbus4j.dataframes.RequestClassXData;
42 import net.sf.mbus4j.dataframes.SelectionOfSlaves;
43 import net.sf.mbus4j.dataframes.SendUserData;
44 import net.sf.mbus4j.dataframes.SetBaudrate;
45 import net.sf.mbus4j.dataframes.ShortFrame;
46 import net.sf.mbus4j.dataframes.SingleCharFrame;
47 import net.sf.mbus4j.dataframes.SynchronizeAction;
48 import net.sf.mbus4j.dataframes.UserDataResponse;
49 import net.sf.mbus4j.dataframes.UserDataResponse.StatusCode;
50 import net.sf.mbus4j.dataframes.datablocks.BcdValue;
51 import net.sf.mbus4j.dataframes.datablocks.ByteDataBlock;
52 import net.sf.mbus4j.dataframes.datablocks.DataBlock;
53 import net.sf.mbus4j.dataframes.datablocks.DateAndTimeDataBlock;
54 import net.sf.mbus4j.dataframes.datablocks.DateDataBlock;
55 import net.sf.mbus4j.dataframes.datablocks.EnhancedIdentificationDataBlock;
56 import net.sf.mbus4j.dataframes.datablocks.IntegerDataBlock;
57 import net.sf.mbus4j.dataframes.datablocks.LongDataBlock;
58 import net.sf.mbus4j.dataframes.datablocks.RawDataBlock;
59 import net.sf.mbus4j.dataframes.datablocks.RealDataBlock;
60 import net.sf.mbus4j.dataframes.datablocks.ShortDataBlock;
61 import net.sf.mbus4j.dataframes.datablocks.StringDataBlock;
62 import net.sf.mbus4j.dataframes.datablocks.vif.VifAscii;
63 import net.sf.mbus4j.dataframes.datablocks.vif.VifManufacturerSpecific;
64 import net.sf.mbus4j.dataframes.datablocks.vif.VifFB;
65 import net.sf.mbus4j.dataframes.datablocks.vif.VifeFC;
66 import net.sf.mbus4j.dataframes.datablocks.vif.VifFD;
67 import net.sf.mbus4j.dataframes.datablocks.vif.VifPrimary;
68 import net.sf.mbus4j.dataframes.datablocks.vif.VifeError;
69 import net.sf.mbus4j.dataframes.datablocks.vif.VifeManufacturerSpecific;
70 import net.sf.mbus4j.dataframes.datablocks.vif.VifePrimary;
71 import net.sf.mbus4j.decoder.Decoder;
72 import net.sf.mbus4j.log.LogUtils;
73
74
75
76
77
78
79 public class Encoder {
80
81 private byte[] data;
82 private int currentPos;
83 private static Logger log = LogUtils.getEncoderLogger();
84
85 public byte[] encode(Frame frame) {
86 if (frame instanceof SingleCharFrame) {
87 return encodeFrame((SingleCharFrame) frame);
88 } else if (frame instanceof ShortFrame) {
89 return encodeFrame((ShortFrame) frame);
90 } else if (frame instanceof ControlFrame) {
91 return encodeFrame((ControlFrame) frame);
92 } else if (frame instanceof LongFrame) {
93 return encodeFrame((LongFrame) frame);
94 } else {
95 return null;
96 }
97 }
98
99 public byte[] encodeFrame(ControlFrame frame) {
100 initFrame(frame);
101 pushCField(frame);
102 pushAField(frame);
103 pushCIField(frame);
104 writeChecksumAndStop(4, 7);
105 return data;
106 }
107
108 public byte[] encodeFrame(LongFrame frame) {
109 initFrame(frame);
110 pushCField(frame);
111 pushAField(frame);
112 pushCIField(frame);
113 if (frame instanceof ApplicationReset) {
114 pushApplicationResetData((ApplicationReset) frame);
115 } else if (frame instanceof GeneralApplicationError) {
116 pushGeneralApplicationError((GeneralApplicationError) frame);
117 } else if (frame instanceof UserDataResponse) {
118 pushVariableDataStructure((UserDataResponse) frame);
119 } else if (frame instanceof SelectionOfSlaves) {
120 pushSelectionOfSlavesDataHeader((SelectionOfSlaves) frame);
121 pushVariableDataBlocks(frame);
122 } else if (frame instanceof SendUserData) {
123 pushVariableDataBlocks(frame);
124 } else {
125 throw new RuntimeException("encode long frame" + frame.getClass().getName());
126 }
127 writeLenght((byte) (currentPos - 4));
128 writeChecksumAndStop(4, currentPos);
129 return data;
130 }
131
132 public byte[] encodeFrame(ShortFrame frame) {
133 initFrame(frame);
134 pushCField(frame);
135 pushAField(frame);
136 writeChecksumAndStop(1, 3);
137 return data;
138 }
139
140 public byte[] encodeFrame(SingleCharFrame frame) {
141 initFrame(frame);
142 return data;
143 }
144
145 private void initFrame(Frame frame) {
146 if (frame instanceof SingleCharFrame) {
147 data = new byte[]{(byte) 0xe5};
148 currentPos = -1;
149 } else if (frame instanceof ShortFrame) {
150 data = new byte[5];
151 data[0] = 0x10;
152 currentPos = 1;
153 } else if (frame instanceof ControlFrame) {
154 data = new byte[9];
155 data[0] = 0x68;
156 data[1] = 0x03;
157 data[2] = 0x03;
158 data[3] = 0x68;
159 currentPos = 4;
160 } else if (frame instanceof LongFrame) {
161 data = new byte[0xFF];
162 data[0] = 0x68;
163 data[3] = 0x68;
164 currentPos = 4;
165 } else {
166 throw new RuntimeException("Unknown frame");
167 }
168 }
169
170 private boolean needDIFE(DataBlock db, int index) {
171 return ((db.getStorageNumber() >> (1 + index * 4)) > 0x00)
172 || (((db.getTariff() >> (index * 2)) << 0x04) > 0x00)
173 || ((db.getSubUnit() >> index) > 0x00);
174 }
175
176 private boolean needVIFE(DataBlock db, int index) {
177 if (db.getVifes().length == 0) {
178 return db.getAction() == null ? false : index == 0;
179 } else {
180 return db.getVifes().length > index;
181 }
182 }
183
184 private void pushAField(PrimaryAddress address) {
185 data[currentPos++] = address.getAddress();
186 }
187
188 private void pushApplicationResetData(ApplicationReset applicationReset) {
189 data[currentPos++] = (byte) (applicationReset.getTelegramType().id | applicationReset.getSubTelegram());
190 }
191
192
193 public int fromLcdDigit(char lcdDigit) {
194 switch (lcdDigit) {
195 case '0':
196 return 0x00;
197 case '1':
198 return 0x01;
199 case '2':
200 return 0x02;
201 case '3':
202 return 0x03;
203 case '4':
204 return 0x04;
205 case '5':
206 return 0x05;
207 case '6':
208 return 0x06;
209 case '7':
210 return 0x07;
211 case '8':
212 return 0x08;
213 case '9':
214 return 0x09;
215 case 'a':
216 case 'A':
217 return 0x0A;
218 case 'b':
219 case 'B':
220 return 0x0B;
221 case 'c':
222 case 'C':
223 return 0x0C;
224 case ' ':
225 case 'd':
226 case 'D':
227 return 0x0D;
228 case 'e':
229 case 'E':
230 return 0x0E;
231 case '-':
232 case 'f':
233 case 'F':
234 return 0x0F;
235 default:
236 throw new RuntimeException("Should never ever happend!");
237 }
238
239 }
240
241 private void pushBcdError(String value) {
242 for (int i = value.length() - 1; i >= 0; i -= 2) {
243 int v = fromLcdDigit(value.charAt(i)) | fromLcdDigit(value.charAt(i - 1)) << 4;
244 data[currentPos++] = (byte) v;
245 }
246 }
247
248 private void pushBcd(long value, int bcdDigits) {
249 final boolean isNegative = value < 0;
250 if (isNegative) {
251 value = -value;
252 }
253 for (int i = bcdDigits / 2; i > 0; i--) {
254 data[currentPos] = (byte) (value % 10);
255 value /= 10;
256 if ((i == 1) && (isNegative)) {
257 data[currentPos++] |= (byte) (0xF0);
258 } else {
259 data[currentPos++] |= (byte) ((value % 10) << 4);
260 }
261 value /= 10;
262 }
263 }
264
265 private void pushBytes(byte[] value) {
266 if (value != null) {
267 for (byte b : value) {
268 pushInteger(b, 1);
269 }
270 }
271 }
272
273 private void pushCField(Frame frame) {
274 switch (frame.getControlCode()) {
275 case SND_NKE:
276 data[currentPos] = 0x40;
277 break;
278 case SND_UD:
279 if (frame instanceof SynchronizeAction) {
280 data[currentPos] = (byte) (0x53 + (((SynchronizeAction) frame).isFcb() ? 0x20 : 0));
281 } else if (frame instanceof ApplicationReset) {
282 data[currentPos] = (byte) (0x53 + (((ApplicationReset) frame).isFcb() ? 0x20 : 0));
283 } else if (frame instanceof SetBaudrate) {
284 data[currentPos] = (byte) (0x53 + (((SetBaudrate) frame).isFcb() ? 0x20 : 0));
285 } else if (frame instanceof SendUserData) {
286 data[currentPos] = (byte) (0x53 + (((SendUserData) frame).isFcb() ? 0x20 : 0));
287 } else if (frame instanceof SelectionOfSlaves) {
288 data[currentPos] = (byte) (0x53 + (((SelectionOfSlaves) frame).isFcb() ? 0x20 : 0));
289 }
290
291 break;
292 case REQ_UD2:
293 RequestClassXData req = (RequestClassXData) frame;
294 data[currentPos] = (byte) (0x4B | (req.isFcb() ? 0x20 : 0) | (req.isFcv() ? 0x10 : 0));
295 break;
296 case REQ_UD1:
297 req = (RequestClassXData) frame;
298 data[currentPos] = (byte) (0x4A | (req.isFcb() ? 0x20 : 0) | (req.isFcv() ? 0x10 : 0));
299 break;
300 case RSP_UD:
301 if (frame instanceof UserDataResponse) {
302 final UserDataResponse resp = (UserDataResponse) frame;
303 data[currentPos] = (byte) (0x08 | (resp.isAcd() ? 0x20 : 0) | (resp.isDfc() ? 0x10 : 0));
304 } else if (frame instanceof GeneralApplicationError) {
305 final GeneralApplicationError gae = (GeneralApplicationError) frame;
306 data[currentPos] = (byte) (0x08 | (gae.isAcd() ? 0x20 : 0) | (gae.isDfc() ? 0x10 : 0));
307 }
308 break;
309 default:
310
311 }
312 currentPos++;
313 }
314
315 private void pushCIField(ControlFrame frame) {
316 if (frame instanceof SetBaudrate) {
317 final SetBaudrate sb = (SetBaudrate) frame;
318 switch (sb.getBaudrate()) {
319 case 300:
320 data[currentPos] = (byte) 0xB8;
321 ;
322 break;
323 case 600:
324 data[currentPos] = (byte) 0xB9;
325 break;
326 case 1200:
327 data[currentPos] = (byte) 0xBA;
328 break;
329 case 2400:
330 data[currentPos] = (byte) 0xBB;
331 break;
332 case 4800:
333 data[currentPos] = (byte) 0xBC;
334 break;
335 case 9600:
336 data[currentPos] = (byte) 0xBD;
337 break;
338 case 19200:
339 data[currentPos] = (byte) 0xBE;
340 break;
341 case 38400:
342 data[currentPos] = (byte) 0xBF;
343 break;
344
345 }
346 } else if (frame instanceof SynchronizeAction) {
347 data[currentPos] = 0x54;
348 }
349 currentPos++;
350 }
351
352 private void pushCIField(LongFrame frame) {
353 if (frame instanceof ApplicationReset) {
354 data[currentPos] = 0x50;
355 } else if (frame instanceof SendUserData) {
356 data[currentPos] = 0x51;
357 } else if (frame instanceof SelectionOfSlaves) {
358 data[currentPos] = 0x52;
359 } else if (frame instanceof GeneralApplicationError) {
360 data[currentPos] = 0x70;
361 } else if (frame instanceof UserDataResponse) {
362 data[currentPos] = 0x72;
363 }
364 currentPos++;
365 }
366
367 private void pushData(DataBlock db) {
368 switch (db.getDataFieldCode()) {
369 case NO_DATA:
370 break;
371 case _8_BIT_INTEGER:
372 pushInteger(((ByteDataBlock) db).getValue(), 1);
373 break;
374 case _16_BIT_INTEGER:
375 if (db instanceof DateDataBlock) {
376 pushDate((DateDataBlock) db);
377 } else {
378 pushInteger(((ShortDataBlock) db).getValue(), 2);
379 }
380 break;
381 case _24_BIT_INTEGER:
382 pushInteger(((IntegerDataBlock) db).getValue(), 3);
383 break;
384 case _32_BIT_INTEGER:
385 if (db instanceof DateAndTimeDataBlock) {
386 pushTimeStamp((DateAndTimeDataBlock) db);
387 } else {
388 pushInteger(((IntegerDataBlock) db).getValue(), 4);
389 }
390 break;
391 case _32_BIT_REAL:
392 pushInteger(Float.floatToIntBits(((RealDataBlock) db).getValue()), 4);
393 break;
394 case _48_BIT_INTEGER:
395 pushInteger(((LongDataBlock) db).getValue(), 6);
396 break;
397 case _64_BIT_INTEGER:
398 if (db instanceof EnhancedIdentificationDataBlock) {
399 pushEnhancedIdentificationDataBlockLong((EnhancedIdentificationDataBlock) db, currentPos);
400 } else {
401 pushInteger(((LongDataBlock) db).getValue(), 8);
402 }
403 break;
404 case SELECTION_FOR_READOUT:
405 break;
406 case _2_DIGIT_BCD:
407 if (((ByteDataBlock) db).isBcdError()) {
408 pushBcdError(((BcdValue) db).getBcdError());
409 } else {
410 pushBcd(((ByteDataBlock) db).getValue(), 2);
411 }
412 break;
413 case _4_DIGIT_BCD:
414 if (((ShortDataBlock) db).isBcdError()) {
415 pushBcdError(((BcdValue) db).getBcdError());
416 } else {
417 pushBcd(((ShortDataBlock) db).getValue(), 4);
418 }
419 break;
420 case _6_DIGIT_BCD:
421 if (((IntegerDataBlock) db).isBcdError()) {
422 pushBcdError(((BcdValue) db).getBcdError());
423 } else {
424 pushBcd(((IntegerDataBlock) db).getValue(), 6);
425 }
426 break;
427 case _8_DIGIT_BCD:
428 if (db instanceof EnhancedIdentificationDataBlock) {
429 pushEnhancedIdentificationDataBlockShort((EnhancedIdentificationDataBlock) db);
430 } else {
431 if (((IntegerDataBlock) db).isBcdError()) {
432 pushBcdError(((BcdValue) db).getBcdError());
433 } else {
434 pushBcd(((IntegerDataBlock) db).getValue(), 8);
435 }
436 }
437 break;
438 case VARIABLE_LENGTH:
439 if (db instanceof StringDataBlock) {
440 pushString(((StringDataBlock) db).getValue());
441 } else {
442
443 throw new RuntimeException("pushData variable length " + db.getClass().getName());
444 }
445 break;
446 case _12_DIGIT_BCD:
447 if (((LongDataBlock) db).isBcdError()) {
448 pushBcdError(((BcdValue) db).getBcdError());
449 } else {
450 pushBcd(((LongDataBlock) db).getValue(), 12);
451 }
452 break;
453 case SPECIAL_FUNCTION_GLOBAL_READOUT_REQUEST:
454 break;
455 case SPECIAL_FUNCTION_IDLE_FILLER:
456 break;
457 case SPECIAL_FUNCTION_MAN_SPEC_DATA_LAST_PACKET:
458 case SPECIAL_FUNCTION_MAN_SPEC_DATA_PACKETS_FOLLOWS:
459 pushBytes(((RawDataBlock) db).getValue());
460 break;
461 default:
462 throw new RuntimeException("push Data " + db.getDataFieldCode());
463 }
464 }
465
466 private void pushDataInformationBlock(DataBlock db) {
467 pushDIF(db);
468 for (int i = 0; i < 10; i++) {
469 if (!needDIFE(db, i)) {
470 break;
471 }
472 pushDIFE(db, i);
473 }
474 }
475
476 private void pushDataRecordHeader(DataBlock db) {
477 pushDataInformationBlock(db);
478 pushValueInformationBlock(db);
479 }
480
481 private void pushDate(DateDataBlock dateDataBlock) {
482 Calendar cal = Calendar.getInstance();
483 cal.setTime(dateDataBlock.getValue());
484 int val = cal.get(Calendar.DAY_OF_MONTH);
485 val |= (((cal.get(Calendar.YEAR) - 2000) & 0x07) << 5);
486 val |= (((cal.get(Calendar.YEAR) - 2000) & 0x78) << 9);
487 val |= ((cal.get(Calendar.MONTH) + 1) << 8);
488 pushInteger(val, 2);
489 }
490
491 private void pushDIF(DataBlock db) {
492 data[currentPos] = db.getDataFieldCode().code;
493 switch (db.getDataFieldCode()) {
494 case SPECIAL_FUNCTION_MAN_SPEC_DATA_LAST_PACKET:
495 data[currentPos++] = 0x0F;
496 break;
497 case SPECIAL_FUNCTION_MAN_SPEC_DATA_PACKETS_FOLLOWS:
498 data[currentPos++] = 0x1F;
499 break;
500 case SPECIAL_FUNCTION_IDLE_FILLER:
501 data[currentPos++] = 0x2F;
502 break;
503 case SPECIAL_FUNCTION_GLOBAL_READOUT_REQUEST:
504 data[currentPos++] = 0x7F;
505 return;
506 default:
507 data[currentPos] |= needDIFE(db, 0) ? Decoder.EXTENTION_BIT : 0x00;
508 if (db.getFunctionField() != null) {
509 data[currentPos] |= db.getFunctionField().code;
510 }
511 data[currentPos++] |= (db.getStorageNumber() & 0x01) << 6;
512 }
513 }
514
515 private void pushDIFE(DataBlock db, int index) {
516 data[currentPos] = needDIFE(db, index + 1) ? Decoder.EXTENTION_BIT : 0x00;
517 data[currentPos] |= (db.getStorageNumber() >> (1 + index * 4)) & 0x0F;
518 data[currentPos] |= ((db.getTariff() >> (index * 2)) << 0x04) & 0x30;
519 data[currentPos++] |= ((db.getSubUnit() >> index) << 0x06) & 0x40;
520 }
521
522 private void pushEnhancedIdentificationDataBlockLong(EnhancedIdentificationDataBlock db, int currentPos) {
523 pushBcd(db.getId(), 8);
524 pushManufacturer(db.getMan());
525 pushInteger(db.getVersion(), 1);
526 pushInteger(db.getMedium().getId(), 1);
527 }
528
529 private void pushEnhancedIdentificationDataBlockShort(EnhancedIdentificationDataBlock db) {
530 pushBcd(db.getId(), 8);
531 }
532
533 private void pushFixedDataHeader(UserDataResponse frame) {
534 pushBcd(frame.getIdentNumber(), 8);
535 pushManufacturer(frame.getManufacturer());
536 data[currentPos++] = frame.getVersion();
537 data[currentPos++] = (byte) frame.getMedium().getId();
538 data[currentPos++] = (byte) frame.getAccessNumber();
539 data[currentPos++] = StatusCode.toId(frame.getStatus());
540 pushInteger(frame.getSignature(), 2);
541 }
542
543 private void pushGeneralApplicationError(GeneralApplicationError generalApplicationError) {
544 data[currentPos++] = generalApplicationError.getError().id;
545 }
546
547 private void pushInteger(long value, int bytes) {
548 for (int i = bytes - 1; i >= 0; i--) {
549 data[currentPos++] = (byte) (value & 0xFF);
550 value >>= 8;
551 }
552 }
553
554 private void pushManufacturer(String man) {
555 pushInteger(MBusUtils.man2Short(man), 2);
556 }
557
558 private void pushObjectAction(DataBlock db) {
559 pushInteger(db.getAction().id, 1);
560 }
561
562 private void pushSelectionOfSlavesDataHeader(SelectionOfSlaves frame) {
563 pushInteger(frame.getBcdMaskedId(), 4);
564 pushInteger(frame.getMaskedMan(), 2);
565 data[currentPos++] = (byte) frame.getMaskedVersion();
566 data[currentPos++] = (byte) frame.getMaskedMedium();
567 }
568
569 private void pushString(String value) {
570 pushInteger(value.length(), 1);
571 for (int i = value.length() - 1; i >= 0; i--) {
572 pushInteger((byte) value.charAt(i), 1);
573 }
574 }
575
576 private void pushTimeStamp(DateAndTimeDataBlock dateAndTimeDataBlock) {
577 Calendar cal = Calendar.getInstance();
578 cal.setTime(dateAndTimeDataBlock.getValue());
579 int val = dateAndTimeDataBlock.isValid() ? 0x00 : 0x80;
580 val |= dateAndTimeDataBlock.isSummerTime() ? 0x8000 : 0x00;
581 val |= dateAndTimeDataBlock.isRes1() ? 0x40 : 0x00;
582 val |= dateAndTimeDataBlock.isRes2() ? 0x4000 : 0x00;
583 val |= dateAndTimeDataBlock.isRes3() ? 0x2000 : 0x00;
584 val |= cal.get(Calendar.MINUTE);
585 val |= cal.get(Calendar.HOUR_OF_DAY) << 8;
586 val |= cal.get(Calendar.DAY_OF_MONTH) << 16;
587 val |= (cal.get(Calendar.MONTH) + 1) << 24;
588 val |= (((cal.get(Calendar.YEAR) - 2000) & 0x07) << 21) + (((cal.get(Calendar.YEAR) - 2000) & 0x78) << 25);
589 pushInteger(val, 4);
590 }
591
592 private void pushValueInformationBlock(DataBlock db) {
593 pushVIF(db);
594 if (db.getAction() != null) {
595 pushObjectAction(db);
596 } else {
597 for (int i = 0; i < 10; i++) {
598 if (!needVIFE(db, i)) {
599 break;
600 }
601 pushVIFE(db, i);
602 }
603 }
604 }
605
606 private void pushVariableDataBlock(DataBlock db) {
607 pushDataRecordHeader(db);
608 pushData(db);
609 }
610
611 private void pushVariableDataBlocks(LongFrame frame) {
612 for (DataBlock db : frame) {
613 pushVariableDataBlock(db);
614 }
615 }
616
617 private void pushVariableDataStructure(UserDataResponse frame) {
618 pushFixedDataHeader(frame);
619 pushVariableDataBlocks(frame);
620 }
621
622 private void pushVIF(DataBlock db) {
623 if (db.getVif() == null) {
624 } else if (db.getVif() instanceof VifPrimary) {
625 data[currentPos] = needVIFE(db, 0) ? Decoder.EXTENTION_BIT : 0x00;
626 data[currentPos++] |= ((VifPrimary) db.getVif()).getTableIndex();
627 } else if (db.getVif() instanceof VifFB) {
628 data[currentPos++] = (byte) 0xFB;
629 data[currentPos] = needVIFE(db, 0) ? Decoder.EXTENTION_BIT : 0x00;
630 data[currentPos++] |= ((VifFB) db.getVif()).getTableIndex();
631 } else if (db.getVif() instanceof VifFD) {
632 data[currentPos++] = (byte) 0xFD;
633 data[currentPos] = needVIFE(db, 0) ? Decoder.EXTENTION_BIT : 0x00;
634 data[currentPos++] |= ((VifFD) db.getVif()).getTableIndex();
635 } else if (db.getVif() instanceof VifAscii) {
636 data[currentPos++] = (byte) (needVIFE(db, 0) ? 0xFC : 0x7C);
637 pushString(((VifAscii) db.getVif()).getValue());
638 } else if (db.getVif() instanceof VifManufacturerSpecific) {
639 data[currentPos] = needVIFE(db, 0) ? Decoder.EXTENTION_BIT : 0x00;
640 data[currentPos++] |= 0x7F;
641 } else {
642 throw new RuntimeException("Unknown vif " + db.getVif());
643 }
644 }
645
646 private void pushVIFE(DataBlock db, int index) {
647 data[currentPos] = needVIFE(db, index + 1) ? Decoder.EXTENTION_BIT : 0x00;
648 if (db.getVifes()[index] instanceof VifePrimary) {
649 data[currentPos++] |= ((VifePrimary) db.getVifes()[index]).getTableIndex();
650 } else if (db.getVifes()[index] instanceof VifeError) {
651 data[currentPos++] |= ((VifeError) db.getVifes()[index]).getTableIndex();
652 } else if (db.getVifes()[index] instanceof VifeManufacturerSpecific) {
653 data[currentPos++] |= ((VifeManufacturerSpecific) db.getVifes()[index]).getVifeValue();
654
655
656 }
657 }
658
659 private void writeChecksumAndStop(int start, int chIndex) {
660 data[chIndex] = 0;
661 for (int i = start; i < chIndex; i++) {
662 data[chIndex] += data[i];
663 }
664 data[chIndex + 1] = 0x16;
665 data = Arrays.copyOf(data, chIndex + 2);
666 }
667
668 private void writeLenght(byte i) {
669 data[1] = i;
670 data[2] = i;
671 }
672 }