|
| 1 | +/* |
| 2 | + Written by rmick (www.bushandbeyond.com.au) Oct 2017 |
| 3 | + |
| 4 | + LTTO means Lazer Tag Team Ops. It is a brand of Lazertag that started life in 2004, from a toy dev company called 'Shoot The Moon'. |
| 5 | + It was was originally sold under the Tiger brand, then later under Nerf and Hasbro. |
| 6 | + |
| 7 | + The range of taggers supported by this library includes; |
| 8 | + LTTO/Deluxe |
| 9 | + IRT-2X drone |
| 10 | + LTX/Phoenix |
| 11 | + TMB |
| 12 | + LTAR |
| 13 | + |
| 14 | + The protocol uses a 38kHz carrier with a 1mS Mark and 2mS Space bits. The Header consists of a 3mS Mark, followed by a 3mS or 6mS Space. |
| 15 | + |
| 16 | + This decoder would not have been possible without the help of many people, inlcuding Riley McArdle, TagFerret & Ryan Bales. |
| 17 | + |
| 18 | + For more information on the protocol and how to use it, please visit |
| 19 | + |
| 20 | + https://wiki.lazerswarm.com/wiki/Main_Page |
| 21 | + |
| 22 | + or ask to join the Lazertag Modders group on Facebook. |
| 23 | + https://www.facebook.com/groups/LazerTagModders/ |
| 24 | +*/ |
| 25 | + |
| 26 | +#include "IRremote.h" |
| 27 | +#include "IRremoteInt.h" |
| 28 | + |
| 29 | +//============================================================================== |
| 30 | +// L TTTTT TTTTT OOO |
| 31 | +// L T T O O |
| 32 | +// L T T O O |
| 33 | +// L T T O O |
| 34 | +// LLLLL T T OOO |
| 35 | +//============================================================================== |
| 36 | + |
| 37 | +#define BITS 32 // The number of bits in the command |
| 38 | + |
| 39 | +#define HDR_MARK 3000 // The length of the Header:Mark |
| 40 | +#define HDR_SPACE 6000 // The length of the Header:Space |
| 41 | +#define TAG_SYNC 3000 // The lenght of the Sync signal for a Tag:Mark |
| 42 | +#define BEACON_SYNC 6000 // The length of the Sync signal for a Beacon:Mark |
| 43 | + |
| 44 | +#define ZERO_BIT 1000 // The length of a Bit:Mark for 0's |
| 45 | +#define ONE_BIT 2000 // The length of a Bit:Mark for 1's |
| 46 | +#define BIT_SPACE 2000 // The length of a Bit:Space |
| 47 | +#define LONG_PAUSE 25000 // The length between packets. |
| 48 | + |
| 49 | +//+============================================================================= |
| 50 | +// |
| 51 | +#if SEND_LTTO |
| 52 | +void IRsend::sendLTTO (unsigned long data, int nbits, bool beacon) |
| 53 | +{ |
| 54 | + // Set IR carrier frequency |
| 55 | + enableIROut(38); |
| 56 | + |
| 57 | + // Header |
| 58 | + mark (HDR_MARK); //PreSync |
| 59 | + space(HDR_SPACE); //PreSync Pause |
| 60 | + |
| 61 | + //Sync |
| 62 | + if (beacon) mark(BEACON_SYNC); |
| 63 | + else mark(TAG_SYNC); |
| 64 | + |
| 65 | + // Data |
| 66 | + for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) { |
| 67 | + if (data & mask) { |
| 68 | + space(BIT_SPACE); |
| 69 | + mark (ONE_BIT); |
| 70 | + } else { |
| 71 | + space(BIT_SPACE); |
| 72 | + mark (ZERO_BIT); |
| 73 | + } |
| 74 | + } |
| 75 | + |
| 76 | + // Footer |
| 77 | + space(LONG_PAUSE); |
| 78 | + space(0); // Always end with the LED off |
| 79 | +} |
| 80 | +#endif |
| 81 | + |
| 82 | +//+============================================================================= |
| 83 | +// |
| 84 | +#if DECODE_LTTO |
| 85 | +bool IRrecv::decodeLTTO(decode_results *results) |
| 86 | +{ |
| 87 | + unsigned long data = 0; // Somewhere to build our code |
| 88 | + int offset = 0; // The IF(_GAP) statement sets the Skip the Gap reading |
| 89 | + int headerSize = 2; // Number of bits for the header, altered by IF(_GAP) to 4 |
| 90 | + int tagLength = 16; |
| 91 | + int beaconLength = 12; |
| 92 | + results->bits = 0; |
| 93 | + // Check initial Mark+Space match |
| 94 | + if (_GAP > 7000) |
| 95 | + { |
| 96 | + // The library default for _GAP is 5000, which means the 6000uS Space is seen as a new packet, |
| 97 | + // therefore the initial 3000uS Mark gets lost, so ignore it unless _GAP > 7000. |
| 98 | + headerSize = 4; // allow for the 2 extra bits in the packet. |
| 99 | + tagLength = 18; // allow for the 2 extra bits in the packet. |
| 100 | + beaconLength = 14; // allow for the 2 extra bits in the packet. |
| 101 | + offset++; // Skip the Gap reading |
| 102 | + if (!MATCH_MARK(results->rawbuf[offset++], HDR_MARK)) return false; |
| 103 | + } |
| 104 | + if (!MATCH_SPACE(results->rawbuf[offset++], HDR_SPACE)) return false ; |
| 105 | + |
| 106 | + |
| 107 | + // Check the Sync Type |
| 108 | + if (MATCH_MARK(results->rawbuf[offset], TAG_SYNC)) |
| 109 | + { |
| 110 | + if (results->rawlen < tagLength) return false; |
| 111 | + results->address = 3000; //TYPE_LAZERTAG_TAG; |
| 112 | + } |
| 113 | + else if (MATCH_MARK(results->rawbuf[offset], BEACON_SYNC)) |
| 114 | + { |
| 115 | + if (results->rawlen < beaconLength) return false; |
| 116 | + results->address = 6000; //TYPE_LAZERTAG_BEACON; |
| 117 | + } |
| 118 | + else return false; |
| 119 | + offset++; |
| 120 | + |
| 121 | + // Read the bits in |
| 122 | + for (int i = 0; i < ((results->rawlen-headerSize)/2); i++) |
| 123 | + { |
| 124 | + // Each bit looks like: SPACE + MARK_1 -> 1 |
| 125 | + // or : SPACE + MARK_0 -> 0 |
| 126 | + |
| 127 | + if (!MATCH_SPACE(results->rawbuf[offset++], BIT_SPACE)) return false; |
| 128 | + |
| 129 | + // IR data is big-endian, so we shuffle it in from the right: |
| 130 | + if (MATCH_MARK(results->rawbuf[offset], ONE_BIT)) |
| 131 | + { |
| 132 | + data = (data << 1) | 1; |
| 133 | + results->bits++; |
| 134 | + } |
| 135 | + else if (MATCH_MARK(results->rawbuf[offset], ZERO_BIT)) |
| 136 | + { |
| 137 | + data = (data << 1) | 0; |
| 138 | + results->bits++; |
| 139 | + } |
| 140 | + offset++; |
| 141 | + } |
| 142 | + |
| 143 | + // Success |
| 144 | + results->value = data; |
| 145 | + results->decode_type = LTTO; |
| 146 | + |
| 147 | + //Serial.print("\n\nSuccess = LTTO"); |
| 148 | + |
| 149 | + return true; |
| 150 | +} |
| 151 | +#endif |
0 commit comments