libfst 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +11 -0
- data/LICENSE +674 -0
- data/README.md +133 -0
- data/ext/extconf.rb +5 -0
- data/ext/fastlz.c +549 -0
- data/ext/fastlz.h +109 -0
- data/ext/fst_config.h +11 -0
- data/ext/fst_win_unistd.h +52 -0
- data/ext/fstapi.c +7204 -0
- data/ext/fstapi.h +466 -0
- data/ext/libfst_rb.c +2525 -0
- data/ext/lz4.c +2789 -0
- data/ext/lz4.h +868 -0
- data/lib/libfst/reader.rb +345 -0
- data/lib/libfst/tfp.rb +112 -0
- data/lib/libfst/vcd.rb +597 -0
- data/lib/libfst/version.rb +4 -0
- data/lib/libfst/writer.rb +50 -0
- data/lib/libfst.rb +6 -0
- data/libfst.gemspec +50 -0
- data/samples/create_file.rb +69 -0
- data/samples/gtkwave.png +0 -0
- data/samples/out.gtkw +46 -0
- data/samples/read2.rb +8 -0
- data/samples/read_file.rb +8 -0
- data/samples/skinny_rand.fst +0 -0
- data/samples/transaction_filter_process/full_boot.fst +0 -0
- data/samples/transaction_filter_process/full_boot.gtkw +39 -0
- data/samples/transaction_filter_process/sdcard.rb +793 -0
- data/samples/transaction_filter_process/uart.rb +141 -0
- data/samples/vcd/skinny_rand.vcd.xz +0 -0
- data/samples/vcd/vcd_read.rb +34 -0
- metadata +72 -0
@@ -0,0 +1,793 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Copyright (C) 2024 Théotime Bollengier <theotime.bollengier@ensta-bretagne.fr>
|
4
|
+
#
|
5
|
+
# This file is part of libfst.rb <https://gitlab.ensta-bretagne.fr/bollenth/libfst.rb>
|
6
|
+
#
|
7
|
+
# libfst.rb is free software: you can redistribute it and/or modify it
|
8
|
+
# under the terms of the GNU General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License,
|
10
|
+
# or (at your option) any later version.
|
11
|
+
#
|
12
|
+
# libfst.rb is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
15
|
+
# See the GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with libfst.rb. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
require_relative '../../lib/libfst'
|
21
|
+
require 'colorize'
|
22
|
+
|
23
|
+
class SDCardDecoder < GTKWave::TransactionFilter
|
24
|
+
CMDS = [
|
25
|
+
# name, response, abbrev, argument
|
26
|
+
['CMD0', nil, 'GO_IDLE_STATE'],
|
27
|
+
['CMD1', nil, 'RESERVED'],
|
28
|
+
['CMD2', :R2, 'ALL_SEND_CID'],
|
29
|
+
['CMD3', :R6, 'SEND_RELATIVE_ADDR'],
|
30
|
+
['CMD4', nil, 'SET_DSR', { (16..31) => 'DSR' }],
|
31
|
+
['CMD5', nil, 'RESERVED'],
|
32
|
+
['CMD6', :R1, 'SWITCH_FUNCTION', { (0..3) => 'fg1am', (4..7) => 'fg2cs', (8..11) => 'fg3ds', (12..15) => 'fg4pl', (31..31) => 'check or switch function' }],
|
33
|
+
['CMD7', :R1b, 'SELECT/DESELECT_CARD', { (16..31) => 'RCA' }],
|
34
|
+
['CMD8', :R7, 'SEND_IF_COND', { (0..7) => 'check pattern', (8..11) => 'supply voltage (VHS)' }],
|
35
|
+
['CMD9', :R2, 'SEND_CSD', { (16..31) => 'RCA' }],
|
36
|
+
['CMD10', :R2, 'SEND_CID', { (16..31) => 'RCA' }],
|
37
|
+
['CMD11', :R1, 'VOLTAGE_SWITCH'],
|
38
|
+
['CMD12', :R1b, 'STOP_TRANSMISSION'],
|
39
|
+
['CMD13', :R1, 'SEND_STATUS', { (16..31) => 'RCA' }],
|
40
|
+
['CMD14', nil, 'RESERVED'],
|
41
|
+
['CMD15', nil, 'GO_INACTIVE_STATE', { (16..31) => 'RCA' }],
|
42
|
+
['CMD16', :R1, 'SET_BLOCKLEN', { (0..31) => 'block length' }],
|
43
|
+
['CMD17', :R1, 'READ_SINGLE_BLOCK', { (0..31) => 'data address' }],
|
44
|
+
['CMD18', :R1, 'READ_MULTIPLE_BLOCK', { (0..31) => 'data address' }],
|
45
|
+
['CMD19', :R1, 'SEND_TUNING_BLOCK'],
|
46
|
+
['CMD20', :R1b, 'SPEED_CLASS_CONTROL', { (0..27) => 'speed class', (28..31) => 'speed class control' }],
|
47
|
+
['CMD21'],
|
48
|
+
['CMD22', :R1, 'ADDRESS_EXTENSION', { (0..5) => 'extended address' }],
|
49
|
+
['CMD23', :R1, 'SET_BLOCK_COUNT', { (0..31) => 'block count' }],
|
50
|
+
['CMD24', :R1, 'WRITE_BLOCK', { (0..31) => 'data address' }],
|
51
|
+
['CMD25', :R1, 'WRITE_MULTIPLE_BLOCK', { (0..31) => 'data address' }],
|
52
|
+
['CMD26', nil, 'RESERVED'],
|
53
|
+
['CMD27', :R1, 'PROGRAM_CSD'],
|
54
|
+
['CMD28', :R1b, 'SET_WRITE_PROT', { (0..31) => 'data address' }],
|
55
|
+
['CMD29', :R1b, 'CLR_WRITE_PROT', { (0..31) => 'data address' }],
|
56
|
+
['CMD30', :R1, 'SEND_WRITE_PROT', { (0..31) => 'write protect data address' }],
|
57
|
+
['CMD31', nil, 'RESERVED'],
|
58
|
+
['CMD32', :R1, 'ERASE_WR_BLK_START', { (0..31) => 'data address' }],
|
59
|
+
['CMD33', :R1, 'ERASE_WR_BLK_END', { (0..31) => 'data address' }],
|
60
|
+
['CMD34'],
|
61
|
+
['CMD35'],
|
62
|
+
['CMD36'],
|
63
|
+
['CMD37'],
|
64
|
+
['CMD38', :R1b, 'ERASE', { (0..31) => 'erase function' }],
|
65
|
+
['CMD39', :R1b, 'SELECT_CARD_PARTITION', { (24..31) => 'partition ID' }],
|
66
|
+
['CMD40', :R1, 'def_by_dps_spec', { (0..31) => 'def by DPS spec' }],
|
67
|
+
['CMD41', :R3, 'RESERVED'],
|
68
|
+
['CMD42', :R1, 'LOCK_UNLOCK', { (0..31) => 'def by DPS spec' }],
|
69
|
+
['CMD43', :R1b, 'Q_MANAGEMENT', { (0..3) => 'opcode', (16..20) => 'task ID' }],
|
70
|
+
['CMD44', :R1, 'Q_TASK_INFO_A', { (0..15) => 'number of blocks', (16..20) => 'task ID', (23..23) => 'priority', (24..29) => 'extended address', (30..30) => 'direction' }],
|
71
|
+
['CMD45', :R1, 'Q_TASK_INFO_B', { (0..31) => 'start block address' }],
|
72
|
+
['CMD46', :R1, 'Q_RD_TASK', { (16..20) => 'task ID' }],
|
73
|
+
['CMD47', :R1, 'Q_WR_TASK', { (16..20) => 'task ID' }],
|
74
|
+
['CMD48', :R1, 'READ_EXTR_SINGLE', { (0..8) => 'LEN', (9..25) => 'ADDR', (27..30) => 'FNO', (31..31) => 'memory or IO' }],
|
75
|
+
['CMD49', :R1, 'WRITE_EXTR_SINGLE', { (0..8) => 'LEN/MASK', (9..25) => 'ADDR', (27..30) => 'FNO', (31..31) => 'memory or IO' }],
|
76
|
+
['CMD50'],
|
77
|
+
['CMD51', nil, 'RESERVED'],
|
78
|
+
['CMD52'],
|
79
|
+
['CMD53'],
|
80
|
+
['CMD54'],
|
81
|
+
['CMD55', :R1, 'APP_CMD', { (16..31) => 'RCA' }], # next command is a ACMD
|
82
|
+
['CMD56', :R1, 'GEN_CMD', { (0..0) => 'RD/WR' }],
|
83
|
+
['CMD57'],
|
84
|
+
['CMD58', :R1, 'READ_EXTR_MULTI', { (0..8) => 'BUC', (9..25) => 'ADDR', (26..26) => 'BUS', (27..30) => 'FNO', (31..31) => 'memory or IO' }],
|
85
|
+
['CMD59', :R1, 'WRITE_EXTR_MULTI', { (0..8) => 'BUC', (9..25) => 'ADDR', (26..26) => 'BUS', (27..30) => 'FNO', (31..31) => 'memory or IO' }],
|
86
|
+
['CMD60'],
|
87
|
+
['CMD61'],
|
88
|
+
['CMD62'],
|
89
|
+
['CMD63']
|
90
|
+
].freeze
|
91
|
+
|
92
|
+
ACMDS = [
|
93
|
+
['ACMD0'],
|
94
|
+
['ACMD1', nil, 'RESERVED'],
|
95
|
+
['ACMD2', nil, 'RESERVED'],
|
96
|
+
['ACMD3', nil, 'RESERVED'],
|
97
|
+
['ACMD4', nil, 'RESERVED'],
|
98
|
+
['ACMD5', nil, 'RESERVED'],
|
99
|
+
['ACMD6', :R1, 'SET_BUS_WIDTH', { (0..1) => 'bus width' }],
|
100
|
+
['ACMD7', nil, 'RESERVED'],
|
101
|
+
['ACMD8', nil, 'RESERVED'],
|
102
|
+
['ACMD9', nil, 'RESERVED'],
|
103
|
+
['ACMD10', nil, 'RESERVED'],
|
104
|
+
['ACMD11', nil, 'RESERVED'],
|
105
|
+
['ACMD12', nil, 'RESERVED'],
|
106
|
+
['ACMD13', :R1, 'SD_STATUS'],
|
107
|
+
['ACMD14', nil, 'RESERVED'],
|
108
|
+
['ACMD15', nil, 'RESERVED'],
|
109
|
+
['ACMD16', nil, 'RESERVED'],
|
110
|
+
['ACMD17', nil, 'RESERVED'],
|
111
|
+
['ACMD18', nil, 'RESERVED'],
|
112
|
+
['ACMD19', nil, 'RESERVED'],
|
113
|
+
['ACMD20', nil, 'RESERVED'],
|
114
|
+
['ACMD21', nil, 'RESERVED'],
|
115
|
+
['ACMD22', :R1, 'SEND_NUM_WR_BLOCKS'],
|
116
|
+
['ACMD23', :R1, 'SEND_WR_BLK_ERASE_COUNT', { (0..22) => 'number of blocks' }],
|
117
|
+
['ACMD24', nil, 'RESERVED'],
|
118
|
+
['ACMD25', nil, 'RESERVED'],
|
119
|
+
['ACMD26', nil, 'RESERVED'],
|
120
|
+
['ACMD27', nil, 'RESERVED'],
|
121
|
+
['ACMD28', nil, 'RESERVED'],
|
122
|
+
['ACMD29', nil, 'RESERVED'],
|
123
|
+
['ACMD30', nil, 'RESERVED'],
|
124
|
+
['ACMD31', nil, 'RESERVED'],
|
125
|
+
['ACMD32', nil, 'RESERVED'],
|
126
|
+
['ACMD33', nil, 'RESERVED'],
|
127
|
+
['ACMD34', nil, 'RESERVED'],
|
128
|
+
['ACMD35', nil, 'RESERVED'],
|
129
|
+
['ACMD36', nil, 'RESERVED'],
|
130
|
+
['ACMD37', nil, 'RESERVED'],
|
131
|
+
['ACMD38', nil, 'RESERVED'],
|
132
|
+
['ACMD39', nil, 'RESERVED'],
|
133
|
+
['ACMD40', nil, 'RESERVED'],
|
134
|
+
['ACMD41', :R3, 'SD_SEND_OP_COND', { (0..23) => 'VDD voltage window', (24..24) => 'S18R', (28..28) => 'XPC', (30..30) => 'HCS' }],
|
135
|
+
['ACMD42', :R1, 'SET_CLR_CARD_DETECT', { (0..0) => 'set_cd' }],
|
136
|
+
['ACMD43', nil, 'RESERVED'],
|
137
|
+
['ACMD44', nil, 'RESERVED'],
|
138
|
+
['ACMD45', nil, 'RESERVED'],
|
139
|
+
['ACMD46', nil, 'RESERVED'],
|
140
|
+
['ACMD47', nil, 'RESERVED'],
|
141
|
+
['ACMD48', nil, 'RESERVED'],
|
142
|
+
['ACMD49', nil, 'RESERVED'],
|
143
|
+
['ACMD50'],
|
144
|
+
['ACMD51', :R1, 'SEND_SCR'],
|
145
|
+
['ACMD52', nil, 'RESERVED'],
|
146
|
+
['ACMD53', :R1, 'SECURE_RECEIVE', { (0..7) => 'SSSF', (8..15) => 'SPSP0', (16..23) => 'SPSP1', (24..31) => 'Security protocol' }],
|
147
|
+
['ACMD54', :R1, 'SECURE_SEND', { (0..7) => 'SSSF', (8..15) => 'SPSP0', (16..23) => 'SPSP1', (24..31) => 'Security protocol' }],
|
148
|
+
['ACMD55', :R1, 'APP_CMD', { (16..31) => 'RCA' }],
|
149
|
+
['ACMD56', nil, 'RESERVED'],
|
150
|
+
['ACMD57', nil, 'RESERVED'],
|
151
|
+
['ACMD58', nil, 'RESERVED'],
|
152
|
+
['ACMD59', nil, 'RESERVED']
|
153
|
+
].freeze
|
154
|
+
|
155
|
+
|
156
|
+
def initialize
|
157
|
+
super
|
158
|
+
puts ' SD Card Decoder '.center(80, '-')
|
159
|
+
puts "Name: #{@name.inspect}"
|
160
|
+
puts "#{@signames.length} signal#{@signames.length > 1 ? 's' : ''}: #{[@signames[0...-1].join(', '), @signames.last].reject(&:empty?).join(' and ')}"
|
161
|
+
raise "expecting two signals, not #{@ivcd.traces.length}" unless @ivcd.traces.length == 2
|
162
|
+
|
163
|
+
# Try to find the clk and cmd signals
|
164
|
+
@ivcd.traces.each_value do |t|
|
165
|
+
raise "expecting two signals of 1 bit, not #{t.width}-bit wide" unless t.width == 1
|
166
|
+
t.variables.each do |v|
|
167
|
+
if v.name =~ /cl(oc)?k/i then
|
168
|
+
raise 'CLK found twice' if @clk_trace
|
169
|
+
@clk_trace = t
|
170
|
+
break
|
171
|
+
elsif v.name =~ /co?m(man)?d/i then
|
172
|
+
raise 'CMD found twice' if @cmd_trace
|
173
|
+
@cmd_trace = t
|
174
|
+
break
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
raise 'Cannot find a clock signal' unless @clk_trace
|
179
|
+
raise 'Cannot find a command signal' unless @cmd_trace
|
180
|
+
end
|
181
|
+
|
182
|
+
|
183
|
+
def puts(*args)
|
184
|
+
$stderr.puts(*args)
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
def read
|
189
|
+
@cmd = 1
|
190
|
+
@clk = nil
|
191
|
+
@time = nil
|
192
|
+
@state = :wait_host_start_bit
|
193
|
+
@times = [0]
|
194
|
+
@phases = ['']
|
195
|
+
@values = ['']
|
196
|
+
|
197
|
+
@ivcd.read do |trace, value, time|
|
198
|
+
case trace
|
199
|
+
when @clk_trace
|
200
|
+
clock(value, time)
|
201
|
+
when @cmd_trace
|
202
|
+
@cmd = value.to_i
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
|
208
|
+
def write
|
209
|
+
$stdout.write "$name #{@name}\n"
|
210
|
+
$stdout.write "##{@min_time}\n"
|
211
|
+
@times.each_with_index do |t, i|
|
212
|
+
v = @values[i]
|
213
|
+
$stdout.write "##{t}#{v ? " #{v}" : ''}\n"
|
214
|
+
end
|
215
|
+
$stdout.write "$next\n"
|
216
|
+
$stdout.write "$name desc\n"
|
217
|
+
$stdout.write "##{@min_time}\n"
|
218
|
+
@times.each_with_index do |t, i|
|
219
|
+
p = @phases[i]
|
220
|
+
$stdout.write "##{t}#{p ? " #{p}" : ''}\n"
|
221
|
+
end
|
222
|
+
$stdout.write "$finish\n"
|
223
|
+
$stdout.flush
|
224
|
+
puts '-'*80
|
225
|
+
end
|
226
|
+
|
227
|
+
|
228
|
+
private
|
229
|
+
|
230
|
+
|
231
|
+
def clock(value, time)
|
232
|
+
value = value.to_i
|
233
|
+
if value == 1 and @clk == 0 then
|
234
|
+
rising_edge
|
235
|
+
elsif value == 0 and @clk == 1 then
|
236
|
+
falling_edge
|
237
|
+
end
|
238
|
+
@clk = value
|
239
|
+
@time = time
|
240
|
+
end
|
241
|
+
|
242
|
+
=begin
|
243
|
+
def reset_read
|
244
|
+
@read_index = 0
|
245
|
+
end
|
246
|
+
|
247
|
+
def advance
|
248
|
+
@read_index += 1
|
249
|
+
end
|
250
|
+
|
251
|
+
def get_time
|
252
|
+
@times[@read_index]
|
253
|
+
end
|
254
|
+
|
255
|
+
def get_phase_and_value
|
256
|
+
[@phases[@read_index], @values[@read_index]]
|
257
|
+
end
|
258
|
+
=end
|
259
|
+
|
260
|
+
def crc7(str)
|
261
|
+
crc = 0
|
262
|
+
str.each_byte do |b|
|
263
|
+
b = (b == 48 ? 0 : 1)
|
264
|
+
crc = (b ^ crc[6]) | ((crc[2] ^ (b ^ crc[6])) << 3) | ((crc << 1) & 0x76)
|
265
|
+
end
|
266
|
+
crc
|
267
|
+
end
|
268
|
+
|
269
|
+
def card_status_to_string(cs)
|
270
|
+
# page 147
|
271
|
+
a = []
|
272
|
+
a << 'OUT_OF_RANGE' if cs[31] == 1
|
273
|
+
a << 'ADDRESS_ERROR' if cs[30] == 1
|
274
|
+
a << 'BLOCL_LEN_ERROR' if cs[29] == 1
|
275
|
+
a << 'ERASE_SEQ_ERROR' if cs[28] == 1
|
276
|
+
a << 'ERASE_PARAM' if cs[27] == 1
|
277
|
+
a << 'WP_VIOLATION' if cs[26] == 1
|
278
|
+
a << 'CARD_IS_LOCKED' if cs[25] == 1
|
279
|
+
a << 'LOCK_UNLOCK_FAILED' if cs[24] == 1
|
280
|
+
a << 'COM_CRC_ERROR' if cs[23] == 1
|
281
|
+
a << 'ILLEGAL_COMMAND' if cs[22] == 1
|
282
|
+
a << 'CARD_ECC_FAILED' if cs[21] == 1
|
283
|
+
a << 'CC_ERROR' if cs[20] == 1
|
284
|
+
a << 'ERROR' if cs[19] == 1
|
285
|
+
a << 'CSD_OVERWRITE' if cs[16] == 1
|
286
|
+
a << 'WP_ERASE_SKIP' if cs[15] == 1
|
287
|
+
a << 'CARD_ECC_DISABLED' if cs[14] == 1
|
288
|
+
a << 'ERASE_RESET' if cs[13] == 1
|
289
|
+
a << %w[idle ready ident stby tran data rcv prg dis xxx xxx xxx xxx xxx xxx RES][(cs >> 9) & 0x0f]
|
290
|
+
a << 'READY_FOR_DATA' if cs[8] == 1
|
291
|
+
a << 'FX_EVENT' if cs[6] == 1
|
292
|
+
a << 'APP_CMD' if cs[5] == 1
|
293
|
+
a << 'AKE_SEQ_ERROR' if cs[3] == 1
|
294
|
+
a << 'reserved bits set' if (cs & 0x00060097) != 0
|
295
|
+
a.join(', ')
|
296
|
+
end
|
297
|
+
|
298
|
+
|
299
|
+
def MID_to_string(mid)
|
300
|
+
name = {
|
301
|
+
0x01=>'Panasonic',
|
302
|
+
0x02=>'Toshiba',
|
303
|
+
0x03=>'SanDisk',
|
304
|
+
0x1b=>'Samsung',
|
305
|
+
0x1d=>'AData',
|
306
|
+
0x27=>'Phison',
|
307
|
+
0x28=>'Lexar',
|
308
|
+
0x31=>'Silicon Power',
|
309
|
+
0x41=>'Kingston',
|
310
|
+
0x74=>'Transcend',
|
311
|
+
0x76=>'Patriot',
|
312
|
+
0x82=>'Sony'
|
313
|
+
}[mid]
|
314
|
+
return '' unless name
|
315
|
+
" (#{name})"
|
316
|
+
end
|
317
|
+
|
318
|
+
|
319
|
+
def cid_to_s(cid)
|
320
|
+
# page 250
|
321
|
+
cid <<= 8
|
322
|
+
a = []
|
323
|
+
mid = (cid >> 120) & 0xff
|
324
|
+
a << "MID: 0x#{mid.to_s(16).rjust(2,'0')}#{MID_to_string(mid)}"
|
325
|
+
a << "OID: \"#{((cid >> 112) & 0xff).chr}#{((cid >> 104) & 0xff).chr}\""
|
326
|
+
pnm = 5.times.reverse_each.collect { |i| ((cid >> (64 + 8*i)) & 0xff).chr }.join
|
327
|
+
a << "PNM: \"#{pnm}\""
|
328
|
+
a << "PRV: \"#{(cid >> 60) & 0x0f}.#{(cid >> 56) & 0x0f}\""
|
329
|
+
a << "PSN: 0x#{((cid >> 24) & 0xffffffff).to_s(16).rjust(8, '0')}"
|
330
|
+
mdt = (cid >> 8) & 0xfff
|
331
|
+
a << "MDT: #{%w[January February March April May June July August September October November December][(mdt & 0xf) - 1]} #{(mdt >> 4) + 2000}"
|
332
|
+
a.join(', ')
|
333
|
+
end
|
334
|
+
|
335
|
+
|
336
|
+
def rising_edge
|
337
|
+
case @state
|
338
|
+
when :r1_start_bit
|
339
|
+
if @cmd == 0 then
|
340
|
+
@times << @time
|
341
|
+
@phases << '?violet?Start bit'
|
342
|
+
@values << '?violet?0'
|
343
|
+
@bits = @cmd.to_s
|
344
|
+
@state = :r1_transmission_bit
|
345
|
+
end
|
346
|
+
when :r1_transmission_bit
|
347
|
+
@times << @time
|
348
|
+
@phases << 'Transmission bit'
|
349
|
+
@values << @cmd.to_s
|
350
|
+
@cnt = 0
|
351
|
+
@r_cmd_index = 0
|
352
|
+
@bits += @cmd.to_s
|
353
|
+
@state = :r1_command_index
|
354
|
+
puts 'WARNING: bit is 1 at response transmission bit'.light_red.bold if @cmd == 1
|
355
|
+
when :r1_command_index
|
356
|
+
if @cnt == 0 then
|
357
|
+
@times << @time
|
358
|
+
end
|
359
|
+
@r_cmd_index = (@r_cmd_index << 1) | @cmd
|
360
|
+
@cnt += 1
|
361
|
+
if @cnt == 6 then
|
362
|
+
@phases << 'CMD index'
|
363
|
+
if @r_cmd_index == @cmd_index then
|
364
|
+
@values << "#{@r_cmd_index} (OK)"
|
365
|
+
else
|
366
|
+
@values << "#{@r_cmd_index} (Should be #{@cmd_index})"
|
367
|
+
puts "WARNING: R1 response to command #{@r_cmd_index} instead of #{@cmd_index}".light_red.bold
|
368
|
+
end
|
369
|
+
@cnt = 0
|
370
|
+
@card_status = 0
|
371
|
+
@state = :r1_status
|
372
|
+
end
|
373
|
+
@bits += @cmd.to_s
|
374
|
+
when :r1_status
|
375
|
+
if @cnt == 0 then
|
376
|
+
@times << @time
|
377
|
+
@phases << 'Card status'
|
378
|
+
end
|
379
|
+
@card_status = (@card_status << 1) | @cmd
|
380
|
+
@cnt += 1
|
381
|
+
if @cnt == 32 then
|
382
|
+
puts " R1: #{card_status_to_string(@card_status)}"
|
383
|
+
@values << card_status_to_string(@card_status)
|
384
|
+
@cnt = 0
|
385
|
+
@crc = 0
|
386
|
+
@state = :r_crc7
|
387
|
+
end
|
388
|
+
@bits += @cmd.to_s
|
389
|
+
when :r_crc7
|
390
|
+
if @cnt == 0 then
|
391
|
+
@times << @time
|
392
|
+
@phases << 'CRC7'
|
393
|
+
end
|
394
|
+
@crc = (@crc << 1) | @cmd
|
395
|
+
@cnt += 1
|
396
|
+
if @cnt == 7 then
|
397
|
+
if @crc == crc7(@bits) then
|
398
|
+
@values << "#{@crc} (OK)"
|
399
|
+
else
|
400
|
+
puts "WARNING: CRC7(#{@bits}) = #{crc7(@bits)}, got, #{@crc}".light_red.bold
|
401
|
+
@values << "#{@crc} (FAIL -> #{crc7(@bits)})"
|
402
|
+
end
|
403
|
+
@state = :r_end_bit
|
404
|
+
end
|
405
|
+
when :r_end_bit
|
406
|
+
@times << @time
|
407
|
+
@phases << 'E'
|
408
|
+
@values << @cmd.to_s
|
409
|
+
@state = :response_sent
|
410
|
+
puts 'WARNING: bit is 0 at end bit'.light_red.bold if @cmd == 0
|
411
|
+
when :response_sent
|
412
|
+
@times << @time
|
413
|
+
@phases << nil
|
414
|
+
@values << nil
|
415
|
+
@state = :wait_host_start_bit
|
416
|
+
|
417
|
+
## R7 ##
|
418
|
+
when :r7_start_bit
|
419
|
+
if @cmd == 0 then
|
420
|
+
@times << @time
|
421
|
+
@phases << '?violet?Start bit'
|
422
|
+
@values << '?violet?0'
|
423
|
+
@bits = @cmd.to_s
|
424
|
+
@state = :r7_transmission_bit
|
425
|
+
end
|
426
|
+
when :r7_transmission_bit
|
427
|
+
@times << @time
|
428
|
+
@phases << 'Transmission bit'
|
429
|
+
@values << @cmd.to_s
|
430
|
+
@cnt = 0
|
431
|
+
@r_cmd_index = 0
|
432
|
+
@bits += @cmd.to_s
|
433
|
+
@state = :r7_command_index
|
434
|
+
puts 'WARNING: bit is 1 at response transmission bit'.light_red.bold if @cmd == 1
|
435
|
+
when :r7_command_index
|
436
|
+
if @cnt == 0 then
|
437
|
+
@times << @time
|
438
|
+
end
|
439
|
+
@r_cmd_index = (@r_cmd_index << 1) | @cmd
|
440
|
+
@cnt += 1
|
441
|
+
if @cnt == 6 then
|
442
|
+
@phases << 'CMD index'
|
443
|
+
if @r_cmd_index == @cmd_index then
|
444
|
+
@values << "#{@r_cmd_index} (OK)"
|
445
|
+
else
|
446
|
+
@values << "#{@r_cmd_index} (Should be #{@cmd_index})"
|
447
|
+
puts "WARNING: R7 response to command #{@r_cmd_index} instead of #{@cmd_index}".light_red.bold
|
448
|
+
end
|
449
|
+
@cnt = 0
|
450
|
+
@tmp = 0
|
451
|
+
@state = :r7_reserved
|
452
|
+
end
|
453
|
+
@bits += @cmd.to_s
|
454
|
+
when :r7_reserved
|
455
|
+
if @cnt == 0 then
|
456
|
+
@times << @time
|
457
|
+
@phases << 'Reserved'
|
458
|
+
end
|
459
|
+
@tmp = (@tmp << 1) | @cmd
|
460
|
+
@cnt += 1
|
461
|
+
if @cnt == 18 then
|
462
|
+
@values << "0x#{@tmp.to_s(16).rjust(5, '0')}"
|
463
|
+
@cnt = 0
|
464
|
+
@tmp = 0
|
465
|
+
@state = :r7_status
|
466
|
+
end
|
467
|
+
@bits += @cmd.to_s
|
468
|
+
when :r7_status
|
469
|
+
if @cnt == 0 then
|
470
|
+
@times << @time
|
471
|
+
@phases << 'Status'
|
472
|
+
end
|
473
|
+
@tmp = (@tmp << 1) | @cmd
|
474
|
+
@cnt += 1
|
475
|
+
if @cnt == 14 then
|
476
|
+
str = "PCIe 1.2v: #{@tmp[13] == 1 ? 'Y' : 'N'}"
|
477
|
+
str += ", PCIe: #{@tmp[12] == 1 ? 'Y' : 'N'}"
|
478
|
+
str += ", Voltage accepted: #{{0=>'Not defined', 1=>'2.7-3.6V', 2=>'Res for LV range', 4=>'Res', 8=>'Res'}.fetch((@tmp >> 8) & 0x0f, 'Not defined')}"
|
479
|
+
str += ", Check pattern: #{@tmp & 0xff}"
|
480
|
+
puts " R7: #{str}"
|
481
|
+
@values << str
|
482
|
+
@cnt = 0
|
483
|
+
@crc = 0
|
484
|
+
@state = :r7_crc7
|
485
|
+
end
|
486
|
+
@bits += @cmd.to_s
|
487
|
+
when :r7_crc7
|
488
|
+
if @cnt == 0 then
|
489
|
+
@times << @time
|
490
|
+
@phases << 'CRC7'
|
491
|
+
end
|
492
|
+
@crc = (@crc << 1) | @cmd
|
493
|
+
@cnt += 1
|
494
|
+
if @cnt == 7 then
|
495
|
+
if @crc == crc7(@bits) then
|
496
|
+
@values << "#{@crc} (OK)"
|
497
|
+
else
|
498
|
+
puts "WARNING: CRC7(#{@bits}) = #{crc7(@bits)}, got, #{@crc}".light_red.bold
|
499
|
+
@values << "#{@crc} (FAIL -> #{crc7(@bits)})"
|
500
|
+
end
|
501
|
+
@state = :r_end_bit
|
502
|
+
end
|
503
|
+
|
504
|
+
## R3 ##
|
505
|
+
when :r3_start_bit
|
506
|
+
if @cmd == 0 then
|
507
|
+
@times << @time
|
508
|
+
@phases << '?violet?Start bit'
|
509
|
+
@values << '?violet?0'
|
510
|
+
@bits = @cmd.to_s
|
511
|
+
@state = :r3_transmission_bit
|
512
|
+
end
|
513
|
+
when :r3_transmission_bit
|
514
|
+
@times << @time
|
515
|
+
@phases << 'Transmission bit'
|
516
|
+
@values << @cmd.to_s
|
517
|
+
@cnt = 0
|
518
|
+
@r_cmd_index = 0
|
519
|
+
@bits += @cmd.to_s
|
520
|
+
@state = :r3_command_index
|
521
|
+
puts 'WARNING: bit is 1 at response transmission bit'.light_red.bold if @cmd == 1
|
522
|
+
when :r3_command_index
|
523
|
+
if @cnt == 0 then
|
524
|
+
@times << @time
|
525
|
+
end
|
526
|
+
@r_cmd_index = (@r_cmd_index << 1) | @cmd
|
527
|
+
@cnt += 1
|
528
|
+
if @cnt == 6 then
|
529
|
+
@phases << 'Reserved'
|
530
|
+
@values << "0b#{@r_cmd_index.to_s(2).rjust(6,'0')}#{@r_cmd_index == 0b111111 ? '' : ' (ERROR)'}"
|
531
|
+
puts "WARNING: R3 reserved zone should be 0b111111 instead of 0b#{@r_cmd_index.to_s(2).rjust(6,'0')}".light_red.bold unless @r_cmd_index == 0b111111
|
532
|
+
@cnt = 0
|
533
|
+
@tmp = 0
|
534
|
+
@state = :r3_OCR
|
535
|
+
end
|
536
|
+
@bits += @cmd.to_s
|
537
|
+
when :r3_OCR
|
538
|
+
if @cnt == 0 then
|
539
|
+
@times << @time
|
540
|
+
@phases << 'OCR'
|
541
|
+
end
|
542
|
+
@tmp = (@tmp << 1) | @cmd
|
543
|
+
@cnt += 1
|
544
|
+
if @cnt == 32 then
|
545
|
+
puts " R3: OCR = 0x#{@tmp.to_s(16).rjust(8, '0')}"
|
546
|
+
@values << "OCR = 0x#{@tmp.to_s(16).rjust(8, '0')}"
|
547
|
+
@cnt = 0
|
548
|
+
@crc = 0
|
549
|
+
@state = :r3_crc7
|
550
|
+
end
|
551
|
+
@bits += @cmd.to_s
|
552
|
+
when :r3_crc7
|
553
|
+
if @cnt == 0 then
|
554
|
+
@times << @time
|
555
|
+
@phases << 'Reserved'
|
556
|
+
end
|
557
|
+
@crc = (@crc << 1) | @cmd
|
558
|
+
@cnt += 1
|
559
|
+
if @cnt == 7 then
|
560
|
+
@values << "0b#{@crc.to_s(2).rjust(7, '0')}"
|
561
|
+
puts "WARNING: R3 reserved zone should be 0b1111111 instead of 0b#{@crc.to_s(2).rjust(7,'0')}".light_red.bold unless @crc == 0b1111111
|
562
|
+
@state = :r_end_bit
|
563
|
+
end
|
564
|
+
|
565
|
+
## R2 ##
|
566
|
+
when :r2_start_bit
|
567
|
+
if @cmd == 0 then
|
568
|
+
@times << @time
|
569
|
+
@phases << '?violet?Start bit'
|
570
|
+
@values << '?violet?0'
|
571
|
+
@state = :r2_transmission_bit
|
572
|
+
end
|
573
|
+
when :r2_transmission_bit
|
574
|
+
@times << @time
|
575
|
+
@phases << 'Transmission bit'
|
576
|
+
@values << @cmd.to_s
|
577
|
+
@cnt = 0
|
578
|
+
@r_cmd_index = 0
|
579
|
+
@state = :r2_command_index
|
580
|
+
puts 'WARNING: bit is 1 at response transmission bit'.light_red.bold if @cmd == 1
|
581
|
+
when :r2_command_index
|
582
|
+
if @cnt == 0 then
|
583
|
+
@times << @time
|
584
|
+
end
|
585
|
+
@r_cmd_index = (@r_cmd_index << 1) | @cmd
|
586
|
+
@cnt += 1
|
587
|
+
if @cnt == 6 then
|
588
|
+
@phases << 'Reserved'
|
589
|
+
@values << "0b#{@r_cmd_index.to_s(2).rjust(6,'0')}#{@r_cmd_index == 0b111111 ? '' : ' (ERROR)'}"
|
590
|
+
puts "WARNING: R2 reserved zone should be 0b111111 instead of 0b#{@r_cmd_index.to_s(2).rjust(6,'0')}".light_red.bold unless @r_cmd_index == 0b111111
|
591
|
+
@cnt = 0
|
592
|
+
@tmp = 0
|
593
|
+
@bits = ''
|
594
|
+
@state = :r2_CID_CSD
|
595
|
+
end
|
596
|
+
when :r2_CID_CSD
|
597
|
+
if @cnt == 0 then
|
598
|
+
@times << @time
|
599
|
+
@phases << (@cmd_index == 2 || @cmd_index == 10 ? 'CID' : 'CSD')
|
600
|
+
end
|
601
|
+
@tmp = (@tmp << 1) | @cmd
|
602
|
+
@cnt += 1
|
603
|
+
if @cnt == 120 then
|
604
|
+
if @cmd_index == 2 || @cmd_index == 10 then
|
605
|
+
puts " R2: CID = #{cid_to_s(@tmp)}"
|
606
|
+
@values << "CID = #{cid_to_s(@tmp)}"
|
607
|
+
else
|
608
|
+
puts " R2: CSD = 0x#{@tmp.to_s(16).rjust(30, '0')}"
|
609
|
+
@values << "CSD = 0x#{@tmp.to_s(16).rjust(30, '0')}"
|
610
|
+
end
|
611
|
+
@cnt = 0
|
612
|
+
@crc = 0
|
613
|
+
@state = :r_crc7
|
614
|
+
end
|
615
|
+
@bits += @cmd.to_s
|
616
|
+
|
617
|
+
## R6 ##
|
618
|
+
when :r6_start_bit
|
619
|
+
if @cmd == 0 then
|
620
|
+
@times << @time
|
621
|
+
@phases << '?violet?Start bit'
|
622
|
+
@values << '?violet?0'
|
623
|
+
@bits = @cmd.to_s
|
624
|
+
@state = :r6_transmission_bit
|
625
|
+
end
|
626
|
+
when :r6_transmission_bit
|
627
|
+
@times << @time
|
628
|
+
@phases << 'Transmission bit'
|
629
|
+
@values << @cmd.to_s
|
630
|
+
@cnt = 0
|
631
|
+
@r_cmd_index = 0
|
632
|
+
@bits += @cmd.to_s
|
633
|
+
@state = :r6_command_index
|
634
|
+
puts 'WARNING: bit is 1 at response transmission bit'.light_red.bold if @cmd == 1
|
635
|
+
when :r6_command_index
|
636
|
+
if @cnt == 0 then
|
637
|
+
@times << @time
|
638
|
+
end
|
639
|
+
@r_cmd_index = (@r_cmd_index << 1) | @cmd
|
640
|
+
@cnt += 1
|
641
|
+
if @cnt == 6 then
|
642
|
+
@phases << 'CMD index'
|
643
|
+
if @r_cmd_index == @cmd_index then
|
644
|
+
@values << "#{@r_cmd_index} (OK)"
|
645
|
+
else
|
646
|
+
@values << "#{@r_cmd_index} (Should be #{@cmd_index})"
|
647
|
+
puts "WARNING: R1 response to command #{@r_cmd_index} instead of #{@cmd_index}".light_red.bold
|
648
|
+
end
|
649
|
+
@cnt = 0
|
650
|
+
@tmp = 0
|
651
|
+
@state = :r6_status
|
652
|
+
end
|
653
|
+
@bits += @cmd.to_s
|
654
|
+
when :r6_status
|
655
|
+
if @cnt == 0 then
|
656
|
+
@times << @time
|
657
|
+
@phases << 'Card status'
|
658
|
+
end
|
659
|
+
@tmp = (@tmp << 1) | @cmd
|
660
|
+
@cnt += 1
|
661
|
+
if @cnt == 32 then
|
662
|
+
cs = (@tmp & 0x1fff) | ((@tmp & 0x2000) << 6) | ((@tmp & 0x4000) << 8) | ((@tmp & 0x8000) << 8)
|
663
|
+
str = "RCA: #{(@tmp >> 16) & 0xffff}"
|
664
|
+
puts " R6: #{str}"
|
665
|
+
@values << str
|
666
|
+
@cnt = 0
|
667
|
+
@crc = 0
|
668
|
+
@state = :r_crc7
|
669
|
+
end
|
670
|
+
@bits += @cmd.to_s
|
671
|
+
end
|
672
|
+
end
|
673
|
+
|
674
|
+
|
675
|
+
def falling_edge
|
676
|
+
case @state
|
677
|
+
when :wait_host_start_bit
|
678
|
+
if @cmd == 0 then
|
679
|
+
@times << @time
|
680
|
+
@phases << '?green?Start bit'
|
681
|
+
@values << '?green?0'
|
682
|
+
@bits = @cmd.to_s
|
683
|
+
@state = :host_transmission_bit
|
684
|
+
end
|
685
|
+
when :host_transmission_bit
|
686
|
+
@times << @time
|
687
|
+
@phases << 'Transmission bit'
|
688
|
+
@values << @cmd.to_s
|
689
|
+
@cnt = 0
|
690
|
+
@cmd_index = 0
|
691
|
+
@bits += @cmd.to_s
|
692
|
+
@state = :host_command_index
|
693
|
+
puts 'WARNING: bit is 0 at host transmission bit'.light_red.bold if @cmd == 0
|
694
|
+
when :host_command_index
|
695
|
+
if @cnt == 0 then
|
696
|
+
@times << @time
|
697
|
+
end
|
698
|
+
@cmd_index = (@cmd_index << 1) | @cmd
|
699
|
+
@cnt += 1
|
700
|
+
if @cnt == 6 then
|
701
|
+
if @last_cmd_is_cmd_app then
|
702
|
+
@command = ACMDS[@cmd_index]
|
703
|
+
else
|
704
|
+
@command = CMDS[@cmd_index]
|
705
|
+
end
|
706
|
+
@last_cmd_is_cmd_app = (@cmd_index == 55)
|
707
|
+
@phases << @command[0]
|
708
|
+
@values << @command[2]
|
709
|
+
$stderr.write @command[2] ? @command[2].light_green.bold : @command[0].light_yellow.bold
|
710
|
+
@cnt = 0
|
711
|
+
@argument = 0
|
712
|
+
@state = :host_argument
|
713
|
+
end
|
714
|
+
@bits += @cmd.to_s
|
715
|
+
when :host_argument
|
716
|
+
if @cnt == 0 then
|
717
|
+
@times << @time
|
718
|
+
@phases << 'Argument'
|
719
|
+
end
|
720
|
+
@argument = (@argument << 1) | @cmd
|
721
|
+
@cnt += 1
|
722
|
+
if @cnt == 32 then
|
723
|
+
if @command[3].nil? then
|
724
|
+
@values << "0x#{@argument.to_s(16).rjust(8, '0')}"
|
725
|
+
puts
|
726
|
+
else
|
727
|
+
str = @command[3].collect{|range, name|
|
728
|
+
b = range.begin
|
729
|
+
e = range.end
|
730
|
+
e += 1 unless range.exclude_end?
|
731
|
+
l = e - b
|
732
|
+
v = (@argument >> b) & ((1 << l) - 1)
|
733
|
+
"#{name} = #{v}"
|
734
|
+
}.join(', ')
|
735
|
+
@values << str
|
736
|
+
puts ' ' + str
|
737
|
+
end
|
738
|
+
@cnt = 0
|
739
|
+
@crc = 0
|
740
|
+
@state = :host_crc7
|
741
|
+
end
|
742
|
+
@bits += @cmd.to_s
|
743
|
+
when :host_crc7
|
744
|
+
if @cnt == 0 then
|
745
|
+
@times << @time
|
746
|
+
@phases << 'CRC7'
|
747
|
+
end
|
748
|
+
@crc = (@crc << 1) | @cmd
|
749
|
+
@cnt += 1
|
750
|
+
if @cnt == 7 then
|
751
|
+
if @crc == crc7(@bits) then
|
752
|
+
@values << "#{@crc} (OK)"
|
753
|
+
else
|
754
|
+
puts "WARNING: CRC7(#{@bits}) = #{crc7(@bits)}, got, #{@crc}".light_red.bold
|
755
|
+
@values << "#{@crc} (FAIL -> #{crc7(@bits)})"
|
756
|
+
end
|
757
|
+
@state = :host_end_bit
|
758
|
+
end
|
759
|
+
when :host_end_bit
|
760
|
+
@times << @time
|
761
|
+
@phases << 'End bit'
|
762
|
+
@values << @cmd.to_s
|
763
|
+
@state = :command_send
|
764
|
+
puts 'WARNING: bit is 0 at end bit'.light_red.bold if @cmd == 0
|
765
|
+
when :command_send
|
766
|
+
@times << @time
|
767
|
+
@phases << nil
|
768
|
+
@values << nil
|
769
|
+
@state = case @command[1]
|
770
|
+
when :R1, :R1b
|
771
|
+
:r1_start_bit
|
772
|
+
when :R2
|
773
|
+
:r2_start_bit
|
774
|
+
when :R3
|
775
|
+
:r3_start_bit
|
776
|
+
when :R6
|
777
|
+
:r6_start_bit
|
778
|
+
when :R7
|
779
|
+
:r7_start_bit
|
780
|
+
when nil
|
781
|
+
:wait_host_start_bit
|
782
|
+
else
|
783
|
+
puts "Stopping because expecting unsupported #{@command[1]} response".light_yellow.bold
|
784
|
+
:wait
|
785
|
+
end
|
786
|
+
end
|
787
|
+
end
|
788
|
+
|
789
|
+
end
|
790
|
+
|
791
|
+
|
792
|
+
SDCardDecoder.run
|
793
|
+
|