001package jmri.jmrix.sprog;
002
003import java.util.Arrays;
004import jmri.DccLocoAddress;
005import jmri.SpeedStepMode;
006import jmri.NmraPacket;
007import org.slf4j.Logger;
008import org.slf4j.LoggerFactory;
009
010/**
011 * Represent information for a DCC Command Station Queue entry where each entry
012 * is a DCC packet to be transmitted to the rails.
013 * <p>
014 * A SlotListener can be registered to hear of changes in this slot. All changes
015 * in values will result in notification.
016 * <p>
017 * Updated by Andrew Crosland February 2012 to allow slots to hold 28 step speed
018 * packets
019 *
020 * @author Andrew Crosland Copyright (C) 2006, 2012
021 * @author Andrew Berridge 2010
022 */
023public class SprogSlot {
024
025    private boolean speedPacket = false;
026    private SpeedStepMode speedMode = SpeedStepMode.NMRA_DCC_128;
027
028    public SprogSlot(int num) {
029        payload = new byte[SprogConstants.MAX_PACKET_LENGTH];
030        payload[0] = 0;
031        payload[1] = 0;
032        payload[2] = 0;
033        f0to4Packet = false;
034        f5to8Packet = false;
035        f9to12Packet = false;
036        f13to20Packet = false;
037        f21to28Packet = false;
038        f29to36Packet = false;
039        f37to44Packet = false;
040        f45to52Packet = false;
041        f53to60Packet = false;
042        f61to68Packet = false;
043        repeat = -1;
044        addr = 0;
045        isLong = false;
046        spd = 0;
047        forward = true;
048        status = SprogConstants.SLOT_FREE;
049        slot = num;
050        opsPkt = false;
051    }
052
053    private byte[] payload;
054    // repeat of -1 is a persistent entry, ie a loco slot
055    private int repeat;
056    private int addr;
057    private boolean isLong;
058    private int spd;
059    private boolean forward;
060    private int status;
061    private final int slot;
062    private boolean opsPkt;
063
064    private boolean f0to4Packet;
065    private boolean f5to8Packet;
066    private boolean f9to12Packet;
067    private boolean f13to20Packet;
068    private boolean f21to28Packet;
069    private boolean f29to36Packet;
070    private boolean f37to44Packet;
071    private boolean f45to52Packet;
072    private boolean f53to60Packet;
073    private boolean f61to68Packet;
074
075    public boolean isF0to4Packet() {
076        return f0to4Packet;
077    }
078
079    public boolean isF5to8Packet() {
080        return f5to8Packet;
081    }
082
083    public boolean isF9to12Packet() {
084        return f9to12Packet;
085    }
086
087    public boolean isF13to20Packet() {
088        return f13to20Packet;
089    }
090
091    public boolean isF21to28Packet() {
092        return f21to28Packet;
093    }
094
095    public boolean isF29to36Packet() {
096        return f29to36Packet;
097    }
098
099    public boolean isF37to44Packet() {
100        return f37to44Packet;
101    }
102
103    public boolean isF45to52Packet() {
104        return f45to52Packet;
105    }
106
107    public boolean isF53to60Packet() {
108        return f53to60Packet;
109    }
110
111    public boolean isF61to68Packet() {
112        return f61to68Packet;
113    }
114
115    private boolean repeatF0 = false;
116    private boolean repeatF1 = false;
117    private boolean repeatF2 = false;
118    private boolean repeatF3 = false;
119    private boolean repeatF4 = false;
120    private boolean repeatF5 = false;
121    private boolean repeatF6 = false;
122    private boolean repeatF7 = false;
123    private boolean repeatF8 = false;
124    private boolean repeatF9 = false;
125    private boolean repeatF10 = false;
126    private boolean repeatF11 = false;
127    private boolean repeatF12 = false;
128    private boolean repeatF13 = false;
129    private boolean repeatF14 = false;
130    private boolean repeatF15 = false;
131    private boolean repeatF16 = false;
132    private boolean repeatF17 = false;
133    private boolean repeatF18 = false;
134    private boolean repeatF19 = false;
135    private boolean repeatF20 = false;
136    private boolean repeatF21 = false;
137    private boolean repeatF22 = false;
138    private boolean repeatF23 = false;
139    private boolean repeatF24 = false;
140    private boolean repeatF25 = false;
141    private boolean repeatF26 = false;
142    private boolean repeatF27 = false;
143    private boolean repeatF28 = false;
144    private boolean repeatF29 = false;
145    private boolean repeatF30 = false;
146    private boolean repeatF31 = false;
147    private boolean repeatF32 = false;
148    private boolean repeatF33 = false;
149    private boolean repeatF34 = false;
150    private boolean repeatF35 = false;
151    private boolean repeatF36 = false;
152    private boolean repeatF37 = false;
153    private boolean repeatF38 = false;
154    private boolean repeatF39 = false;
155    private boolean repeatF40 = false;
156    private boolean repeatF41 = false;
157    private boolean repeatF42 = false;
158    private boolean repeatF43 = false;
159    private boolean repeatF44 = false;
160    private boolean repeatF45 = false;
161    private boolean repeatF46 = false;
162    private boolean repeatF47 = false;
163    private boolean repeatF48 = false;
164    private boolean repeatF49 = false;
165    private boolean repeatF50 = false;
166    private boolean repeatF51 = false;
167    private boolean repeatF52 = false;
168    private boolean repeatF53 = false;
169    private boolean repeatF54 = false;
170    private boolean repeatF55 = false;
171    private boolean repeatF56 = false;
172    private boolean repeatF57 = false;
173    private boolean repeatF58 = false;
174    private boolean repeatF59 = false;
175    private boolean repeatF60 = false;
176    private boolean repeatF61 = false;
177    private boolean repeatF62 = false;
178    private boolean repeatF63 = false;
179    private boolean repeatF64 = false;
180    private boolean repeatF65 = false;
181    private boolean repeatF66 = false;
182    private boolean repeatF67 = false;
183    private boolean repeatF68 = false;
184
185    /**
186     * Set the contents of the slot. Intended for accessory packets.
187     *
188     * @param address int
189     * @param payload byte[]
190     * @param repeat  int
191     */
192    public void set(int address, byte[] payload, int repeat) {
193        addr = address;
194
195        Arrays.copyOf(payload, payload.length);
196
197        this.setRepeat(repeat);
198        status = SprogConstants.SLOT_IN_USE;
199    }
200
201    public void setAccessoryPacket(int address, boolean closed, int repeats) {
202        this.payload = NmraPacket.accDecoderPkt(address, closed);
203        this.addr = address + 10000;
204        this.repeat = repeats;
205        status = SprogConstants.SLOT_IN_USE;
206    }
207
208    public boolean isSpeedPacket() {
209        return speedPacket;
210    }
211
212    public void setSpeed(SpeedStepMode mode, int address, boolean isLongAddress, int speed, boolean forward) {
213        addr = address;
214        isLong = isLongAddress;
215        spd = speed;
216        this.speedPacket = true;
217        this.speedMode = mode;
218        this.f0to4Packet = false;
219        this.f5to8Packet = false;
220        this.f9to12Packet = false;
221        this.f13to20Packet = false;
222        this.f21to28Packet = false;
223        this.f29to36Packet = false;
224        this.f37to44Packet = false;
225        this.f45to52Packet = false;
226        this.f53to60Packet = false;
227        this.f61to68Packet = false;
228        this.forward = forward;
229        if (mode == SpeedStepMode.NMRA_DCC_28) {
230            this.payload = jmri.NmraPacket.speedStep28Packet(true, addr,
231                    isLong, spd, forward);
232        } else {
233            this.payload = jmri.NmraPacket.speedStep128Packet(addr,
234                    isLong, spd, forward);
235        }
236        status = SprogConstants.SLOT_IN_USE;
237    }
238
239    public void setOps(int address, boolean longAddr, int cv, int val) {
240        payload = NmraPacket.opsCvWriteByte(address, longAddr, cv, val);
241        this.repeat = SprogConstants.OPS_REPEATS;
242        this.opsPkt = true;
243        status = SprogConstants.SLOT_IN_USE;
244    }
245
246    public void f5to8packet(int address, boolean isLongAddress,
247            boolean f5, boolean f5Momentary,
248            boolean f6, boolean f6Momentary,
249            boolean f7, boolean f7Momentary,
250            boolean f8, boolean f8Momentary) {
251
252        this.f5to8Packet = true;
253        this.addr = address;
254        this.isLong = isLongAddress;
255
256        //Were we repeating any functions which we are now not?
257        if ((this.repeatF5 && !f5)
258                || (this.repeatF6 && !f6)
259                || (this.repeatF7 && !f7)
260                || (this.repeatF8 && !f8)) {
261            this.repeat = 3; //Then repeat 3 times
262        }
263
264        this.repeatF5 = !f5Momentary && f5;
265        this.repeatF6 = !f6Momentary && f6;
266        this.repeatF7 = !f7Momentary && f7;
267        this.repeatF8 = !f8Momentary && f8;
268
269        this.payload = jmri.NmraPacket.function5Through8Packet(address,
270                isLongAddress,
271                f5, f6, f7, f8);
272        this.status = SprogConstants.SLOT_IN_USE;
273
274    }
275
276    public void f9to12packet(int address, boolean isLongAddress,
277            boolean f9, boolean f9Momentary,
278            boolean f10, boolean f10Momentary,
279            boolean f11, boolean f11Momentary,
280            boolean f12, boolean f12Momentary) {
281
282        this.f9to12Packet = true;
283        this.addr = address;
284        this.isLong = isLongAddress;
285
286        //Were we repeating any functions which we are now not?
287        if ((this.repeatF9 && !f9)
288                || (this.repeatF10 && !f10)
289                || (this.repeatF11 && !f11)
290                || (this.repeatF12 && !f12)) {
291            this.repeat = 3; //Then repeat 3 times
292        }
293
294        this.repeatF9 = !f9Momentary && f9;
295        this.repeatF10 = !f10Momentary && f10;
296        this.repeatF11 = !f11Momentary && f11;
297        this.repeatF12 = !f12Momentary && f12;
298
299        this.payload = jmri.NmraPacket.function9Through12Packet(address,
300                isLongAddress,
301                f9, f10, f11, f12);
302        this.status = SprogConstants.SLOT_IN_USE;
303
304    }
305
306    public void f13to20packet(int address, boolean isLongAddress,
307            boolean f13, boolean f13Momentary,
308            boolean f14, boolean f14Momentary,
309            boolean f15, boolean f15Momentary,
310            boolean f16, boolean f16Momentary,
311            boolean f17, boolean f17Momentary,
312            boolean f18, boolean f18Momentary,
313            boolean f19, boolean f19Momentary,
314            boolean f20, boolean f20Momentary) {
315
316        this.f13to20Packet = true;
317        this.addr = address;
318        this.isLong = isLongAddress;
319
320        //Were we repeating any functions which we are now not?
321        if ((this.repeatF13 && !f13)
322                || (this.repeatF14 && !f14)
323                || (this.repeatF15 && !f15)
324                || (this.repeatF16 && !f16)
325                || (this.repeatF17 && !f17)
326                || (this.repeatF18 && !f18)
327                || (this.repeatF19 && !f19)
328                || (this.repeatF20 && !f20)) {
329            this.repeat = 3; //Then repeat 3 times
330        }
331
332        this.repeatF13 = !f13Momentary && f13;
333        this.repeatF14 = !f14Momentary && f14;
334        this.repeatF15 = !f15Momentary && f15;
335        this.repeatF16 = !f16Momentary && f16;
336        this.repeatF17 = !f17Momentary && f17;
337        this.repeatF18 = !f18Momentary && f18;
338        this.repeatF19 = !f19Momentary && f19;
339        this.repeatF20 = !f20Momentary && f20;
340
341        this.payload = jmri.NmraPacket.function13Through20Packet(address,
342                isLongAddress,
343                f13, f14, f15, f16,
344                f17, f18, f19, f20);
345        this.status = SprogConstants.SLOT_IN_USE;
346    }
347
348    public void f21to28packet(int address, boolean isLongAddress,
349            boolean f21, boolean f21Momentary,
350            boolean f22, boolean f22Momentary,
351            boolean f23, boolean f23Momentary,
352            boolean f24, boolean f24Momentary,
353            boolean f25, boolean f25Momentary,
354            boolean f26, boolean f26Momentary,
355            boolean f27, boolean f27Momentary,
356            boolean f28, boolean f28Momentary) {
357
358        this.f21to28Packet = true;
359        this.addr = address;
360        this.isLong = isLongAddress;
361
362        //Were we repeating any functions which we are now not?
363        if ((this.repeatF21 && !f21)
364                || (this.repeatF22 && !f22)
365                || (this.repeatF23 && !f23)
366                || (this.repeatF24 && !f24)
367                || (this.repeatF25 && !f25)
368                || (this.repeatF26 && !f26)
369                || (this.repeatF27 && !f27)
370                || (this.repeatF28 && !f28)) {
371            this.repeat = 3; //Then repeat 3 times
372        }
373
374        this.repeatF21 = !f21Momentary && f21;
375        this.repeatF22 = !f22Momentary && f22;
376        this.repeatF23 = !f23Momentary && f23;
377        this.repeatF24 = !f24Momentary && f24;
378        this.repeatF25 = !f25Momentary && f25;
379        this.repeatF26 = !f26Momentary && f26;
380        this.repeatF27 = !f27Momentary && f27;
381        this.repeatF28 = !f28Momentary && f28;
382
383        this.payload = jmri.NmraPacket.function21Through28Packet(address,
384                isLongAddress,
385                f21, f22, f23, f24,
386                f25, f26, f27, f28);
387        this.status = SprogConstants.SLOT_IN_USE;
388    }
389
390    public void f29to36packet(int address, boolean isLongAddress,
391            boolean f29, boolean f29Momentary,
392            boolean f30, boolean f30Momentary,
393            boolean f31, boolean f31Momentary,
394            boolean f32, boolean f32Momentary,
395            boolean f33, boolean f33Momentary,
396            boolean f34, boolean f34Momentary,
397            boolean f35, boolean f35Momentary,
398            boolean f36, boolean f36Momentary) {
399
400        this.f29to36Packet = true;
401        this.addr = address;
402        this.isLong = isLongAddress;
403
404        //Were we repeating any functions which we are now not?
405        if ((this.repeatF29 && !f29)
406                || (this.repeatF30 && !f30)
407                || (this.repeatF31 && !f31)
408                || (this.repeatF32 && !f32)
409                || (this.repeatF33 && !f33)
410                || (this.repeatF34 && !f34)
411                || (this.repeatF35 && !f35)
412                || (this.repeatF36 && !f36)) {
413            this.repeat = 3; //Then repeat 3 times
414        }
415
416        this.repeatF29 = !f29Momentary && f29;
417        this.repeatF30 = !f30Momentary && f30;
418        this.repeatF31 = !f31Momentary && f31;
419        this.repeatF32 = !f32Momentary && f32;
420        this.repeatF33 = !f33Momentary && f33;
421        this.repeatF34 = !f34Momentary && f34;
422        this.repeatF35 = !f35Momentary && f35;
423        this.repeatF36 = !f36Momentary && f36;
424
425        this.payload = jmri.NmraPacket.function29Through36Packet(address,
426                isLongAddress,
427                f29, f30, f31, f32,
428                f33, f34, f35, f36);
429        this.status = SprogConstants.SLOT_IN_USE;
430    }
431
432    public void f37to44packet(int address, boolean isLongAddress,
433            boolean f37, boolean f37Momentary,
434            boolean f38, boolean f38Momentary,
435            boolean f39, boolean f39Momentary,
436            boolean f40, boolean f40Momentary,
437            boolean f41, boolean f41Momentary,
438            boolean f42, boolean f42Momentary,
439            boolean f43, boolean f43Momentary,
440            boolean f44, boolean f44Momentary) {
441
442        this.f37to44Packet = true;
443        this.addr = address;
444        this.isLong = isLongAddress;
445
446        //Were we repeating any functions which we are now not?
447        if ((this.repeatF37 && !f37)
448                || (this.repeatF38 && !f38)
449                || (this.repeatF39 && !f39)
450                || (this.repeatF40 && !f40)
451                || (this.repeatF41 && !f41)
452                || (this.repeatF42 && !f42)
453                || (this.repeatF43 && !f43)
454                || (this.repeatF44 && !f44)) {
455            this.repeat = 3; //Then repeat 3 times
456        }
457
458        this.repeatF37 = !f37Momentary && f37;
459        this.repeatF38 = !f38Momentary && f38;
460        this.repeatF39 = !f39Momentary && f39;
461        this.repeatF40 = !f40Momentary && f40;
462        this.repeatF41 = !f41Momentary && f41;
463        this.repeatF42 = !f42Momentary && f42;
464        this.repeatF43 = !f43Momentary && f43;
465        this.repeatF44 = !f44Momentary && f44;
466
467        this.payload = jmri.NmraPacket.function37Through44Packet(address,
468                isLongAddress,
469                f37, f38, f39, f40,
470                f41, f42, f43, f44);
471        this.status = SprogConstants.SLOT_IN_USE;
472    }
473
474    public void f45to52packet(int address, boolean isLongAddress,
475            boolean f45, boolean f45Momentary,
476            boolean f46, boolean f46Momentary,
477            boolean f47, boolean f47Momentary,
478            boolean f48, boolean f48Momentary,
479            boolean f49, boolean f49Momentary,
480            boolean f50, boolean f50Momentary,
481            boolean f51, boolean f51Momentary,
482            boolean f52, boolean f52Momentary) {
483
484        this.f45to52Packet = true;
485        this.addr = address;
486        this.isLong = isLongAddress;
487
488        //Were we repeating any functions which we are now not?
489        if ((this.repeatF45 && !f45)
490                || (this.repeatF46 && !f46)
491                || (this.repeatF47 && !f47)
492                || (this.repeatF48 && !f48)
493                || (this.repeatF49 && !f49)
494                || (this.repeatF50&& !f50)
495                || (this.repeatF51 && !f51)
496                || (this.repeatF52 && !f52)) {
497            this.repeat = 3; //Then repeat 3 times
498        }
499
500        this.repeatF45 = !f45Momentary && f45;
501        this.repeatF46 = !f46Momentary && f46;
502        this.repeatF47 = !f47Momentary && f47;
503        this.repeatF48 = !f48Momentary && f48;
504        this.repeatF49 = !f49Momentary && f49;
505        this.repeatF50 = !f50Momentary && f50;
506        this.repeatF51 = !f51Momentary && f51;
507        this.repeatF52 = !f52Momentary && f52;
508
509        this.payload = jmri.NmraPacket.function45Through52Packet(address,
510                isLongAddress,
511                f45, f46, f47, f48,
512                f49, f50, f51, f52);
513        this.status = SprogConstants.SLOT_IN_USE;
514    }
515
516    public void f53to60packet(int address, boolean isLongAddress,
517            boolean f53, boolean f53Momentary,
518            boolean f54, boolean f54Momentary,
519            boolean f55, boolean f55Momentary,
520            boolean f56, boolean f56Momentary,
521            boolean f57, boolean f57Momentary,
522            boolean f58, boolean f58Momentary,
523            boolean f59, boolean f59Momentary,
524            boolean f60, boolean f60Momentary) {
525
526        this.f53to60Packet = true;
527        this.addr = address;
528        this.isLong = isLongAddress;
529
530        //Were we repeating any functions which we are now not?
531        if ((this.repeatF53 && !f53)
532                || (this.repeatF54 && !f54)
533                || (this.repeatF55 && !f55)
534                || (this.repeatF56 && !f56)
535                || (this.repeatF57 && !f57)
536                || (this.repeatF58&& !f59)
537                || (this.repeatF59 && !f59)
538                || (this.repeatF60 && !f60)) {
539            this.repeat = 3; //Then repeat 3 times
540        }
541
542        this.repeatF53 = !f53Momentary && f53;
543        this.repeatF54 = !f54Momentary && f54;
544        this.repeatF55 = !f55Momentary && f55;
545        this.repeatF56 = !f56Momentary && f56;
546        this.repeatF57 = !f57Momentary && f57;
547        this.repeatF58 = !f58Momentary && f58;
548        this.repeatF59 = !f59Momentary && f59;
549        this.repeatF60 = !f60Momentary && f60;
550
551        this.payload = jmri.NmraPacket.function53Through60Packet(address,
552                isLongAddress,
553                f53, f54, f55, f56,
554                f57, f58, f59, f60);
555        this.status = SprogConstants.SLOT_IN_USE;
556    }
557
558    public void f61to68packet(int address, boolean isLongAddress,
559            boolean f61, boolean f61Momentary,
560            boolean f62, boolean f62Momentary,
561            boolean f63, boolean f63Momentary,
562            boolean f64, boolean f64Momentary,
563            boolean f65, boolean f65Momentary,
564            boolean f66, boolean f66Momentary,
565            boolean f67, boolean f67Momentary,
566            boolean f68, boolean f68Momentary) {
567
568        this.f61to68Packet = true;
569        this.addr = address;
570        this.isLong = isLongAddress;
571
572        //Were we repeating any functions which we are now not?
573        if ((this.repeatF61 && !f61)
574                || (this.repeatF62 && !f62)
575                || (this.repeatF63 && !f63)
576                || (this.repeatF64 && !f64)
577                || (this.repeatF65 && !f65)
578                || (this.repeatF66&& !f66)
579                || (this.repeatF67 && !f67)
580                || (this.repeatF68 && !f68)) {
581            this.repeat = 3; //Then repeat 3 times
582        }
583
584        this.repeatF61 = !f61Momentary && f61;
585        this.repeatF62 = !f62Momentary && f62;
586        this.repeatF63 = !f63Momentary && f63;
587        this.repeatF64 = !f64Momentary && f64;
588        this.repeatF65 = !f65Momentary && f65;
589        this.repeatF66 = !f66Momentary && f66;
590        this.repeatF67 = !f67Momentary && f67;
591        this.repeatF68 = !f68Momentary && f68;
592
593        this.payload = jmri.NmraPacket.function61Through68Packet(address,
594                isLongAddress,
595                f61, f62, f63, f64,
596                f65, f66, f67, f68);
597        this.status = SprogConstants.SLOT_IN_USE;
598    }
599
600    public void f0to4packet(int address, boolean isLongAddress,
601            boolean f0, boolean f0Momentary,
602            boolean f1, boolean f1Momentary,
603            boolean f2, boolean f2Momentary,
604            boolean f3, boolean f3Momentary,
605            boolean f4, boolean f4Momentary) {
606
607        this.f0to4Packet = true;
608        this.addr = address;
609        this.isLong = isLongAddress;
610
611        //Were we repeating any functions which we are now not?
612        if ((this.repeatF0 && !f0)
613                || (this.repeatF1 && !f1)
614                || (this.repeatF2 && !f2)
615                || (this.repeatF3 && !f3)
616                || (this.repeatF4 && !f4)) {
617            this.repeat = 3; //Then repeat 3 times
618        }
619
620        this.repeatF0 = !f0Momentary && f0;
621        this.repeatF1 = !f1Momentary && f1;
622        this.repeatF2 = !f2Momentary && f2;
623        this.repeatF3 = !f3Momentary && f3;
624        this.repeatF4 = !f4Momentary && f4;
625        
626        this.payload = jmri.NmraPacket.function0Through4Packet(address,
627                isLongAddress,
628                f0, f1, f2, f3, f4);
629        this.status = SprogConstants.SLOT_IN_USE;
630
631    }
632
633    public boolean isFinished() {
634        if (this.isF0to4Packet()) {
635            if ((this.repeatF0 || this.repeatF1 || this.repeatF2 || this.repeatF3 || this.repeatF4)) {
636                return false;
637            }
638        }
639        if (this.isF5to8Packet()) {
640            if ((this.repeatF5 || this.repeatF6 || this.repeatF7 || this.repeatF8)) {
641                return false;
642            }
643        }
644        if (this.isF9to12Packet()) {
645            if ((this.repeatF9 || this.repeatF10 || this.repeatF11 || this.repeatF12)) {
646                return false;
647            }
648        }
649        if (this.isF13to20Packet()) {
650            if ((this.repeatF13 || this.repeatF14 || this.repeatF15 || this.repeatF16)
651                    || (this.repeatF17 || this.repeatF18 || this.repeatF19 || this.repeatF20)) {
652                return false;
653            }
654        }
655        if (this.isF21to28Packet()) {
656            if ((this.repeatF21 || this.repeatF22 || this.repeatF23 || this.repeatF24)
657                    || (this.repeatF25 || this.repeatF26 || this.repeatF27 || this.repeatF28)) {
658                return false;
659            }
660        }
661        if (this.isSpeedPacket() && this.status == SprogConstants.SLOT_IN_USE) {
662            return false;
663        }
664        if (this.repeat > 0 && this.status == SprogConstants.SLOT_IN_USE) {
665            return false;
666        }
667        /* Finished - clear and return true */
668        this.clear();
669        return true;
670    }
671
672    public void eStop() {
673        this.setSpeed(this.speedMode, this.addr, this.isLong, 1, this.forward);
674    }
675
676    // Access methods
677
678    public void clear() {
679        status = SprogConstants.SLOT_FREE;
680        addr = 0;
681        spd = 0;
682        speedPacket = false;
683        f0to4Packet = false;
684        f5to8Packet = false;
685        f9to12Packet = false;
686        f13to20Packet = false;
687        f21to28Packet = false;
688        f29to36Packet = false;
689        f37to44Packet = false;
690        f45to52Packet = false;
691        f53to60Packet = false;
692        f61to68Packet = false;
693        if (payload != null) {
694            payload[0] = 0;
695            payload[1] = 0;
696            payload[2] = 0;
697        }
698        opsPkt = false;
699    }
700
701    public boolean isLongAddress() {
702        return isLong;
703    }
704
705    public boolean isFree() {
706        return (status == SprogConstants.SLOT_FREE);
707    }
708
709    public int slotStatus() {
710        return status;
711    }
712
713    public int getRepeat() {
714        return repeat;
715    }
716
717    public void setRepeat(int r) {
718        repeat = r;
719    }
720
721    private int doRepeat() {
722        if (repeat > 0) {
723            log.debug("Slot {} repeats", slot);
724            repeat--;
725            if (repeat == 0) {
726                log.debug("Clear slot {} due to repeats exhausted", slot);
727                this.clear();
728            }
729        }
730        return repeat;
731    }
732
733    public int speed() {
734        return spd;
735    }
736
737    public int locoAddr() {
738        return addr;
739    }
740
741    public int getAddr() {
742        if (opsPkt == false) {
743            return addr;
744        } else {
745            return addressFromPacket();
746        }
747    }
748
749    public void setAddr(int a) {
750        addr = a;
751    }
752
753    public boolean getIsLong() {
754        if (opsPkt == false) {
755            return isLong;
756        } else {
757            return ((payload[0] & 0xC0) >= 0xC0);
758        }
759    }
760
761    public void setIsLong(boolean a) {
762        isLong = a;
763    }
764
765    public boolean isForward() {
766        return forward;
767    }
768
769    public boolean isOpsPkt() {
770        return opsPkt;
771    }
772
773    public boolean isActiveAddressMatch(DccLocoAddress address) {
774        return ( status == SprogConstants.SLOT_IN_USE && getAddr() == address.getNumber() && getIsLong() == address.isLongAddress() );
775    }
776
777    /**
778     * Get the payload of this slot. Note - if this slot has a number of
779     * repeats, calling this method will also decrement the internal repeat
780     * counter.
781     *
782     * @return a byte array containing the payload of this slot
783     */
784    public byte[] getPayload() {
785
786        byte[] p;
787        if (payload != null) {
788            p = Arrays.copyOf(payload, getPayloadLength());//, a Java 1.6 construct
789        } else {
790            p = new byte[0];
791        }
792        /*byte [] p = new byte[getPayloadLength()];
793         for (int i = 0; i<getPayloadLength(); i++) p[i] = payload[i];*/
794
795        //decrement repeat counter if appropriate
796        doRepeat();
797        return p;
798
799    }
800
801    public int getSlotNumber() {
802        return slot;
803    }
804
805    private int getPayloadLength() {
806        return this.payload.length;
807    }
808
809    private long lastUpdateTime; // Time of last update for detecting stale slots
810
811    public long getLastUpdateTime() {
812        return lastUpdateTime;
813    }
814
815    /**
816     * Get the address from the packet.
817     *
818     * @return int address from payload
819     */
820    private int addressFromPacket() {
821        if (isFree()) {
822            return -1;
823        }
824        // First deal with possible extended address
825        if ((payload[0] & 0xC0) == 0xC0) {
826            return ((payload[0] & 0x3F) << 8 | (payload[1] & 0xFF));
827        }
828        return payload[0];
829    }
830
831    private final static Logger log = LoggerFactory.getLogger(SprogSlot.class);
832}