2 ## This file is part of the libsigrokdecode project.
4 ## Copyright (C) 2016 Fabian J. Stumpf <sigrok@fabianstumpf.de>
6 ## This program is free software; you can redistribute it and/or modify
7 ## it under the terms of the GNU General Public License as published by
8 ## the Free Software Foundation; either version 2 of the License, or
9 ## (at your option) any later version.
11 ## This program is distributed in the hope that it will be useful,
12 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ## GNU General Public License for more details.
16 ## You should have received a copy of the GNU General Public License
17 ## along with this program; if not, see <http://www.gnu.org/licenses/>.
20 import sigrokdecode as srd
22 class Decoder(srd.Decoder):
26 longname = 'Digital MultipleX 512'
27 desc = 'Professional lighting control protocol.'
32 {'id': 'dmx', 'name': 'DMX data', 'desc': 'Any DMX data line'},
37 ('mab', 'Mark after break'),
38 ('startbit', 'Start bit'),
39 ('stopbits', 'Stop bit'),
40 ('startcode', 'Start code'),
41 ('channel', 'Channel'),
42 ('interframe', 'Interframe'),
43 ('interpacket', 'Interpacket'),
48 ('name', 'Logical', (1, 2, 5, 6, 7, 8)),
49 ('data', 'Data', (9,)),
50 ('bits', 'Bits', (0, 3, 4)),
51 ('errors', 'Errors', (10,)),
55 self.samplerate = None
56 self.sample_usec = None
59 self.state = 'FIND BREAK'
62 self.out_ann = self.register(srd.OUTPUT_ANN)
64 def metadata(self, key, value):
65 if key == srd.SRD_CONF_SAMPLERATE:
66 self.samplerate = value
67 self.sample_usec = 1 / value * 1000000
68 self.skip_per_bit = int(4 / self.sample_usec)
71 self.put(self.run_start, self.samplenum, self.out_ann, data)
74 if not self.samplerate:
75 raise SamplerateError('Cannot decode without samplerate.')
77 # Seek for an interval with no state change with a length between
78 # 88 and 1000000 us (BREAK).
79 if self.state == 'FIND BREAK':
80 (dmx,) = self.wait({0: 'h' if self.run_bit == 0 else 'l'})
81 runlen = (self.samplenum - self.run_start) * self.sample_usec
82 if runlen > 88 and runlen < 1000000:
83 self.putr([1, ['Break']])
84 self.bit_break = self.run_bit
85 self.state = 'MARK MAB'
87 elif runlen >= 1000000:
89 self.putr([10, ['Invalid break length']])
91 self.run_start = self.samplenum
92 # Directly following the BREAK is the MARK AFTER BREAK.
93 elif self.state == 'MARK MAB':
94 (dmx,) = self.wait({0: 'h' if self.run_bit == 0 else 'l'})
95 self.putr([2, ['MAB']])
96 self.state = 'READ BYTE'
100 self.run_start = self.samplenum
101 # Mark and read a single transmitted byte
102 # (start bit, 8 data bits, 2 stop bits).
103 elif self.state == 'READ BYTE':
104 (dmx,) = self.wait({'skip': 1})
105 self.next_sample = self.run_start + (self.bit + 1) * self.skip_per_bit
107 if self.samplenum != self.next_sample:
109 bit_value = 0 if round(self.aggreg/self.skip_per_bit) == self.bit_break else 1
113 self.putr([3, ['Start bit']])
115 # (Possibly) invalid start bit, mark but don't fail.
116 self.put(self.samplenum, self.samplenum,
117 self.out_ann, [10, ['Invalid start bit']])
119 self.put(self.samplenum - self.skip_per_bit,
120 self.samplenum, self.out_ann, [4, ['Stop bit']])
122 # Invalid stop bit, mark.
123 self.put(self.samplenum, self.samplenum,
124 self.out_ann, [10, ['Invalid stop bit']])
126 # On invalid 2nd stop bit, search for new break.
128 self.state = 'FIND BREAK'
130 # Label and process one bit.
131 self.put(self.samplenum - self.skip_per_bit,
132 self.samplenum, self.out_ann, [0, [str(bit_value)]])
133 self.byte |= bit_value << (self.bit - 1)
135 # Label a complete byte.
137 if self.channel == 0:
138 d = [5, ['Start code']]
140 d = [6, ['Channel ' + str(self.channel)]]
141 self.put(self.run_start, self.next_sample, self.out_ann, d)
142 self.put(self.run_start + self.skip_per_bit,
143 self.next_sample - 2 * self.skip_per_bit,
144 self.out_ann, [9, [str(self.byte) + ' / ' + \
145 str(hex(self.byte))]])
146 # Continue by scanning the IFT.
148 self.run_start = self.samplenum
150 self.state = 'MARK IFT'
154 # Mark the INTERFRAME-TIME between bytes / INTERPACKET-TIME between packets.
155 elif self.state == 'MARK IFT':
156 (dmx,) = self.wait({0: 'h' if self.run_bit == 0 else 'l'})
157 if self.channel > 512:
158 self.putr([8, ['Interpacket']])
159 self.state = 'FIND BREAK'
161 self.run_start = self.samplenum
163 self.putr([7, ['Interframe']])
164 self.state = 'READ BYTE'
166 self.run_start = self.samplenum