| ... | @@ -110,18 +110,7 @@ pub fn encode(comptime mode: Mode, comptime level: Level, comptime version: u16, | ... | @@ -110,18 +110,7 @@ pub fn encode(comptime mode: Mode, comptime level: Level, comptime version: u16, |
| 110 | std.log.warn("{d}", .{&bitReverse(scratch.masks)}); | 110 | std.log.warn("{d}", .{&bitReverse(scratch.masks)}); |
| 111 | std.log.warn("{x}", .{&bitReverse(scratch.masks)}); | 111 | std.log.warn("{x}", .{&bitReverse(scratch.masks)}); |
| 112 | | 112 | |
| 113 | const groups = if (groupTwoBlockCount) |_| 2 else 1; | 113 | const generator_polynomial = reverseArray(generatorPolynomial(ecCodewordsPerBlock)); |
| 114 | _ = &groups; | | |
| 115 | const blocks = groupOneBlockCount; | | |
| 116 | _ = &blocks; | | |
| 117 | const dc_per_block = groupOneDataCodewordsCountPerBlock; | | |
| 118 | _ = &dc_per_block; | | |
| 119 | const ecc_per_block = ecCodewordsPerBlock; | | |
| 120 | | | |
| 121 | var message_polynomial = scratch.masks; | | |
| 122 | std.log.warn("message_polynomial: {d}", .{&bitReverse(message_polynomial)}); | | |
| 123 | | | |
| 124 | const generator_polynomial = reverseArray(generatorPolynomial(ecc_per_block)); | | |
| 125 | std.log.warn("generator_polynomial: {d}", .{generator_polynomial}); | 114 | std.log.warn("generator_polynomial: {d}", .{generator_polynomial}); |
| 126 | | 115 | |
| 127 | const generator_polynomial_alpha = to_alpha(generator_polynomial); | 116 | const generator_polynomial_alpha = to_alpha(generator_polynomial); |
| ... | @@ -135,24 +124,91 @@ pub fn encode(comptime mode: Mode, comptime level: Level, comptime version: u16, | ... | @@ -135,24 +124,91 @@ pub fn encode(comptime mode: Mode, comptime level: Level, comptime version: u16, |
| 135 | // 3. XOR the result of Step 2 with the message polynomial and discard the lead 0 term. | 124 | // 3. XOR the result of Step 2 with the message polynomial and discard the lead 0 term. |
| 136 | // 4. Repeat Steps 2-3 n-1 more times where n is the number of data codewords. | 125 | // 4. Repeat Steps 2-3 n-1 more times where n is the number of data codewords. |
| 137 | } | 126 | } |
| 138 | var mp: [scratch.masks.len + ecc_per_block]?u8 = @splat(null); | | |
| 139 | for (&message_polynomial, 0..) |x, i| mp[i] = to_alpha(.{@bitReverse(x)})[0]; | | |
| 140 | | 127 | |
| 141 | for (0..scratch.masks.len) |i| { | 128 | const group2_block_count = groupTwoBlockCount orelse 0; |
| 142 | const lead = mp[i].?; | 129 | const group2_datacodewords_per_block = groupTwoDataCodewordsCountPerBlock orelse 0; |
| 143 | for (&generator_polynomial_alpha, 0..) |x, j| { | 130 | |
| 144 | var y = GF[(@as(usize, x) + lead) % 255]; | 131 | var group1_ec: [groupOneBlockCount][ecCodewordsPerBlock]u8 = @splat(@splat(0)); |
| 145 | if (mp[i + j]) |z| y ^= GF[z]; | 132 | var group2_ec: [group2_block_count][ecCodewordsPerBlock]u8 = @splat(@splat(0)); |
| 146 | mp[i + j] = if (y == 0) null else to_alpha(.{y})[0]; | 133 | |
| | 134 | for (&group1_ec, 0..) |*g, gn| { |
| | 135 | const message_polynomial = scratch.masks[groupOneDataCodewordsCountPerBlock * gn ..][0..groupOneDataCodewordsCountPerBlock]; |
| | 136 | std.log.warn("message_polynomial: 1,{d},{d},{d}", .{ gn, message_polynomial.len, &bitReverse(message_polynomial.*) }); |
| | 137 | |
| | 138 | var mp: [groupOneDataCodewordsCountPerBlock + ecCodewordsPerBlock]?u8 = @splat(null); |
| | 139 | for (message_polynomial, 0..) |x, i| mp[i] = to_alpha(.{@bitReverse(x)})[0]; |
| | 140 | |
| | 141 | for (0..groupOneDataCodewordsCountPerBlock) |i| { |
| | 142 | const lead = mp[i].?; |
| | 143 | for (&generator_polynomial_alpha, 0..) |x, j| { |
| | 144 | var y = GF[(@as(usize, x) + lead) % 255]; |
| | 145 | if (mp[i + j]) |z| y ^= GF[z]; |
| | 146 | mp[i + j] = if (y == 0) null else to_alpha(.{y})[0]; |
| | 147 | } |
| | 148 | } |
| | 149 | for (g, 0..) |_, i| { |
| | 150 | g[i] = if (mp[message_polynomial.len..][i]) |x| GF[x] else 0; |
| | 151 | } |
| | 152 | } |
| | 153 | for (&group2_ec, 0..) |*g, gn| { |
| | 154 | const message_polynomial = scratch.masks[groupOneBlockCount * groupOneDataCodewordsCountPerBlock ..][group2_datacodewords_per_block * gn ..][0..group2_datacodewords_per_block]; |
| | 155 | std.log.warn("message_polynomial: 2,{d},{d},{d}", .{ gn, message_polynomial.len, &bitReverse(message_polynomial.*) }); |
| | 156 | |
| | 157 | var mp: [group2_datacodewords_per_block + ecCodewordsPerBlock]?u8 = @splat(null); |
| | 158 | for (message_polynomial, 0..) |x, i| mp[i] = to_alpha(.{@bitReverse(x)})[0]; |
| | 159 | |
| | 160 | for (0..group2_datacodewords_per_block) |i| { |
| | 161 | const lead = mp[i].?; |
| | 162 | for (&generator_polynomial_alpha, 0..) |x, j| { |
| | 163 | var y = GF[(@as(usize, x) + lead) % 255]; |
| | 164 | if (mp[i + j]) |z| y ^= GF[z]; |
| | 165 | mp[i + j] = if (y == 0) null else to_alpha(.{y})[0]; |
| | 166 | } |
| | 167 | } |
| | 168 | for (g, 0..) |_, i| { |
| | 169 | g[i] = if (mp[message_polynomial.len..][i]) |x| GF[x] else 0; |
| 147 | } | 170 | } |
| 148 | } | 171 | } |
| 149 | | 172 | |
| 150 | var error_codewords: [ecc_per_block]u8 = @splat(0); | 173 | comptime std.debug.assert(groupOneDataCodewordsCountPerBlock != group2_datacodewords_per_block); |
| 151 | for (0..ecc_per_block) |i| error_codewords[i] = if (mp[message_polynomial.len..][i]) |x| GF[x] else 0; | 174 | const group1_allcodewords_count = groupOneBlockCount * groupOneDataCodewordsCountPerBlock + groupOneBlockCount * ecCodewordsPerBlock; |
| 152 | std.log.warn("error_codewords: {d}", .{error_codewords}); | 175 | const group2_allcodewords_count = group2_block_count * group2_datacodewords_per_block + group2_block_count * ecCodewordsPerBlock; |
| 153 | | 176 | var interleaved_message: [group1_allcodewords_count + group2_allcodewords_count]u8 = @splat(0); |
| 154 | const interleaved_message = scratch.masks ++ bitReverse(error_codewords); | 177 | var imi: usize = 0; |
| | 178 | for (0..@min(groupOneDataCodewordsCountPerBlock, group2_datacodewords_per_block)) |j| { |
| | 179 | for (0..groupOneBlockCount) |i| { |
| | 180 | interleaved_message[imi] = scratch.masks[(i * groupOneDataCodewordsCountPerBlock) + j]; |
| | 181 | imi += 1; |
| | 182 | } |
| | 183 | for (0..group2_block_count) |i| { |
| | 184 | interleaved_message[imi] = scratch.masks[(groupOneBlockCount * groupOneDataCodewordsCountPerBlock) + (i * group2_datacodewords_per_block) + j]; |
| | 185 | imi += 1; |
| | 186 | } |
| | 187 | } |
| | 188 | for (0..groupOneDataCodewordsCountPerBlock - @min(groupOneDataCodewordsCountPerBlock, group2_datacodewords_per_block)) |j| { |
| | 189 | for (0..groupOneBlockCount) |i| { |
| | 190 | interleaved_message[imi] = scratch.masks[(i * groupOneDataCodewordsCountPerBlock) + j]; |
| | 191 | imi += 1; |
| | 192 | } |
| | 193 | } |
| | 194 | for (0..group2_datacodewords_per_block - @min(groupOneDataCodewordsCountPerBlock, group2_datacodewords_per_block)) |j| { |
| | 195 | for (0..group2_block_count) |i| { |
| | 196 | interleaved_message[imi] = scratch.masks[(groupOneBlockCount * groupOneDataCodewordsCountPerBlock) + (i * group2_datacodewords_per_block) + j]; |
| | 197 | imi += 1; |
| | 198 | } |
| | 199 | } |
| | 200 | for (0..ecCodewordsPerBlock) |j| { |
| | 201 | for (0..groupOneBlockCount) |i| { |
| | 202 | interleaved_message[imi] = @bitReverse(group1_ec[i][j]); |
| | 203 | imi += 1; |
| | 204 | } |
| | 205 | for (0..group2_block_count) |i| { |
| | 206 | interleaved_message[imi] = @bitReverse(group2_ec[i][j]); |
| | 207 | imi += 1; |
| | 208 | } |
| | 209 | } |
| 155 | std.log.warn("interleaved_message: {b:0>8}", .{&bitReverse(interleaved_message)}); | 210 | std.log.warn("interleaved_message: {b:0>8}", .{&bitReverse(interleaved_message)}); |
| | 211 | std.debug.assert(imi == interleaved_message.len); |
| 156 | | 212 | |
| 157 | // remainder bits | 213 | // remainder bits |
| 158 | const remainder_bits_count = comptime remainderBitsCount(version); | 214 | const remainder_bits_count = comptime remainderBitsCount(version); |
| ... | @@ -184,8 +240,6 @@ pub fn encode(comptime mode: Mode, comptime level: Level, comptime version: u16, | ... | @@ -184,8 +240,6 @@ pub fn encode(comptime mode: Mode, comptime level: Level, comptime version: u16, |
| 184 | // dark module | 240 | // dark module |
| 185 | grid.set(8, 4 * (version - 1) + 13); | 241 | grid.set(8, 4 * (version - 1) + 13); |
| 186 | | 242 | |
| 187 | // version block | | |
| 188 | | | |
| 189 | // data mask (data cannot be placed where this is set) | 243 | // data mask (data cannot be placed where this is set) |
| 190 | var data_mask: BitGrid(size) = .initEmpty(); | 244 | var data_mask: BitGrid(size) = .initEmpty(); |
| 191 | for (0..9) |y| for (0..9) |x| data_mask.set(x, y); | 245 | for (0..9) |y| for (0..9) |x| data_mask.set(x, y); |
| ... | @@ -196,13 +250,12 @@ pub fn encode(comptime mode: Mode, comptime level: Level, comptime version: u16, | ... | @@ -196,13 +250,12 @@ pub fn encode(comptime mode: Mode, comptime level: Level, comptime version: u16, |
| 196 | | 250 | |
| 197 | // alignment patterns | 251 | // alignment patterns |
| 198 | const alignment_pattern_centers = comptime alignmentPatternCenters(version); | 252 | const alignment_pattern_centers = comptime alignmentPatternCenters(version); |
| 199 | for (alignment_pattern_centers) |y| { | 253 | for (alignment_pattern_centers, 0..) |y, i| { |
| 200 | for (alignment_pattern_centers) |x| blk: { | 254 | for (alignment_pattern_centers, 0..) |x, j| blk: { |
| 201 | for (y - 2..y + 2 + 1) |y2| { | 255 | if (i == 0 and j == 0) break :blk; |
| 202 | for (x - 2..x + 2 + 1) |x2| { | 256 | if (i == 0 and j == alignment_pattern_centers.len - 1) break :blk; |
| 203 | if (grid.isSet(x2, y2)) break :blk; | 257 | if (j == 0 and i == alignment_pattern_centers.len - 1) break :blk; |
| 204 | } | 258 | |
| 205 | } | | |
| 206 | for (y - 2..y + 2 + 1) |y2| for (x - 2..x + 2 + 1) |x2| { | 259 | for (y - 2..y + 2 + 1) |y2| for (x - 2..x + 2 + 1) |x2| { |
| 207 | grid.setT(x2, y2); | 260 | grid.setT(x2, y2); |
| 208 | data_mask.set(x2, y2); | 261 | data_mask.set(x2, y2); |
| ... | @@ -216,6 +269,27 @@ pub fn encode(comptime mode: Mode, comptime level: Level, comptime version: u16, | ... | @@ -216,6 +269,27 @@ pub fn encode(comptime mode: Mode, comptime level: Level, comptime version: u16, |
| 216 | } | 269 | } |
| 217 | } | 270 | } |
| 218 | | 271 | |
| | 272 | // version block |
| | 273 | if (version >= 7) { |
| | 274 | var bititer: std.bit_set.IntegerBitSet(18) = .{ .mask = versionBits(version) }; |
| | 275 | std.debug.assert(bititer.mask == 0b001010010011010011); |
| | 276 | std.debug.assert(bititer.isSet(0)); |
| | 277 | std.debug.assert(bititer.isSet(1)); |
| | 278 | |
| | 279 | for (0..3) |x| { |
| | 280 | for (0..6) |y| { |
| | 281 | grid.setV(size - 11 + x, y, bititer.isSet((y * 3) + x)); |
| | 282 | data_mask.set(size - 11 + x, y); |
| | 283 | } |
| | 284 | } |
| | 285 | for (0..6) |x| { |
| | 286 | for (0..3) |y| { |
| | 287 | grid.setV(x, size - 11 + y, bititer.isSet((x * 3) + y)); |
| | 288 | data_mask.set(x, size - 11 + y); |
| | 289 | } |
| | 290 | } |
| | 291 | } |
| | 292 | |
| 219 | // write data | 293 | // write data |
| 220 | var data_iter: BufBiterator = .init(&bitReverse(interleaved_message)); | 294 | var data_iter: BufBiterator = .init(&bitReverse(interleaved_message)); |
| 221 | | 295 | |
| ... | @@ -567,7 +641,7 @@ fn isAlphanumeric(c: u8) bool { | ... | @@ -567,7 +641,7 @@ fn isAlphanumeric(c: u8) bool { |
| 567 | return switch (c) { | 641 | return switch (c) { |
| 568 | '0'...'9' => true, | 642 | '0'...'9' => true, |
| 569 | 'A'...'Z' => true, | 643 | 'A'...'Z' => true, |
| 570 | ' ', '$', '%', '*', '+', '-', '.', '/', ':', ',' => true, | 644 | ' ', '$', '%', '*', '+', '-', '.', '/', ':' => true, |
| 571 | else => false, | 645 | else => false, |
| 572 | }; | 646 | }; |
| 573 | } | 647 | } |
| ... | @@ -887,6 +961,52 @@ fn alignmentPatternCenters(version: u16) []const u8 { | ... | @@ -887,6 +961,52 @@ fn alignmentPatternCenters(version: u16) []const u8 { |
| 887 | }[version]; | 961 | }[version]; |
| 888 | } | 962 | } |
| 889 | | 963 | |
| | 964 | fn versionBits(version: u16) u18 { |
| | 965 | return ([_]u18{ |
| | 966 | 0, |
| | 967 | 0, |
| | 968 | 0, |
| | 969 | 0, |
| | 970 | 0, |
| | 971 | 0, |
| | 972 | 0, |
| | 973 | 0b000111110010010100, |
| | 974 | 0b001000010110111100, |
| | 975 | 0b001001101010011001, |
| | 976 | 0b001010010011010011, |
| | 977 | 0b001011101111110110, |
| | 978 | 0b001100011101100010, |
| | 979 | 0b001101100001000111, |
| | 980 | 0b001110011000001101, |
| | 981 | 0b001111100100101000, |
| | 982 | 0b010000101101111000, |
| | 983 | 0b010001010001011101, |
| | 984 | 0b010010101000010111, |
| | 985 | 0b010011010100110010, |
| | 986 | 0b010100100110100110, |
| | 987 | 0b010101011010000011, |
| | 988 | 0b010110100011001001, |
| | 989 | 0b010111011111101100, |
| | 990 | 0b011000111011000100, |
| | 991 | 0b011001000111100001, |
| | 992 | 0b011010111110101011, |
| | 993 | 0b011011000010001110, |
| | 994 | 0b011100110000011010, |
| | 995 | 0b011101001100111111, |
| | 996 | 0b011110110101110101, |
| | 997 | 0b011111001001010000, |
| | 998 | 0b100000100111010101, |
| | 999 | 0b100001011011110000, |
| | 1000 | 0b100010100010111010, |
| | 1001 | 0b100011011110011111, |
| | 1002 | 0b100100101100001011, |
| | 1003 | 0b100101010000101110, |
| | 1004 | 0b100110101001100100, |
| | 1005 | 0b100111010101000001, |
| | 1006 | 0b101000110001101001, |
| | 1007 | })[version]; |
| | 1008 | } |
| | 1009 | |
| 890 | // | 1010 | // |
| 891 | // | 1011 | // |
| 892 | // | 1012 | // |
| ... | @@ -895,10 +1015,11 @@ fn alignmentPatternCenters(version: u16) []const u8 { | ... | @@ -895,10 +1015,11 @@ fn alignmentPatternCenters(version: u16) []const u8 { |
| 895 | const BufBiterator = struct { | 1015 | const BufBiterator = struct { |
| 896 | buf: []const u8, | 1016 | buf: []const u8, |
| 897 | bits: std.bit_set.IntegerBitSet(8), | 1017 | bits: std.bit_set.IntegerBitSet(8), |
| 898 | idx: u8, // buf index | 1018 | idx: u32, // buf index |
| 899 | jdx: u8, // bits index | 1019 | jdx: u8, // bits index |
| 900 | | 1020 | |
| 901 | pub fn init(buf: []const u8) BufBiterator { | 1021 | pub fn init(buf: []const u8) BufBiterator { |
| | 1022 | std.debug.assert(buf.len > 0); |
| 902 | return .{ | 1023 | return .{ |
| 903 | .buf = buf, | 1024 | .buf = buf, |
| 904 | .bits = .{ .mask = buf[0] }, | 1025 | .bits = .{ .mask = buf[0] }, |