nx_jpeg_mcu_test.nx source
↩ module page · 127 lines · 4306 B
1// nx_jpeg_mcu_test.nx -- KAT for the MCU walker.
2//
3// Strategy: minimal grayscale 8x8 image (1 MCU, 1 block, 1 component).
4//
5// Bitstream design: DC category 0 -> "0" + no magnitude bits. Then
6// AC EOB -> "0". Total 2 bits: 0b00000000 = 0x00.
7//
8// Expected output: all 64 IDCT samples are 0 (since all coefficients
9// are 0), then level-shift +128 -> all samples = 128. Plane should
10// have all 128s in the 8x8 region.
11//
12// Huffman tables:
13// DC: BITS={1,0,...}, HUFFVAL={0}. symbol 0 = code "0" (1 bit)
14// AC: BITS={1,0,...}, HUFFVAL={0x00}. symbol 0x00 = code "0" (1 bit) EOB
15//
16// expect_exit: 0
17// license_tier: ORIGINAL
18
19import "nx_syscalls.nx"
20import "nx_jpeg_dht.nx"
21import "nx_jpeg_mcu.nx"
22import "nx_jpeg_idct.nx"
23import "nx_jpeg_sof.nx"
24
25func _fail(n: i64) -> i64 {
26 let b: *u8 = sys_mmap(16)
27 b[0]=0x46; b[1]=0x41; b[2]=0x49; b[3]=0x4C; b[4]=0x3D
28 sys_write(2, b, 5)
29 var x: i64 = n
30 if x < 0 { let m: *u8 = sys_mmap(4); m[0]=0x2D; sys_write(2, m, 1); x = 0 - x }
31 if x == 0 { let z: *u8 = sys_mmap(4); z[0]=0x30; sys_write(2, z, 1) }
32 else {
33 let buf: *u8 = sys_mmap(16)
34 var pos: i64 = 0
35 while x > 0 { buf[pos] = (0x30 + (x % 10)) as u8; x = x / 10; pos = pos + 1 }
36 let out: *u8 = sys_mmap(16)
37 var i: i64 = 0
38 while i < pos { out[i] = buf[pos - 1 - i]; i = i + 1 }
39 sys_write(2, out, pos)
40 }
41 let nl: *u8 = sys_mmap(4); nl[0]=0x0A; sys_write(2, nl, 1)
42 return 0
43}
44
45func main() -> i64 {
46 // ---- Build DC + AC Huffman tables ----
47 let tables: *NxJpegHTable = sys_mmap(NX_JPEG_HTABLE_BYTES * 4) as *NxJpegHTable
48 let bits_pool: *i64 = sys_mmap(4 * 17 * 8) as *i64
49 let hv_pool: *i64 = sys_mmap(4 * 256 * 8) as *i64
50 let mc_pool: *i64 = sys_mmap(4 * 17 * 8) as *i64
51 let xc_pool: *i64 = sys_mmap(4 * 17 * 8) as *i64
52 let vp_pool: *i64 = sys_mmap(4 * 17 * 8) as *i64
53 let count_p: *i64 = sys_mmap(8) as *i64
54
55 let pld: *u8 = sys_mmap(128)
56 // DC: Tc=0 Th=0, BITS={1, 0...}, HUFFVAL={0}
57 pld[0] = 0x00
58 pld[1] = 1
59 var i: i64 = 2
60 while i <= 16 { pld[i] = 0; i = i + 1 }
61 pld[17] = 0
62 // AC: Tc=1 Th=0, BITS={1, 0...}, HUFFVAL={0x00}
63 pld[18] = 0x10
64 pld[19] = 1
65 i = 20
66 while i <= 34 { pld[i] = 0; i = i + 1 }
67 pld[35] = 0x00
68
69 let rc_p: i64 = nx_jpeg_dht_parse(pld, 36, tables, bits_pool, hv_pool, mc_pool, xc_pool, vp_pool, count_p)
70 if rc_p != NX_JPEG_DHT_OK { _fail(1); return 1 }
71 if count_p[0] != 2 { _fail(2); return 2 }
72
73 let dc_table: *NxJpegHTable = tables
74 let ac_table: *NxJpegHTable = (tables as i64 + NX_JPEG_HTABLE_BYTES) as *NxJpegHTable
75
76 // ---- Quantization table: identity (all 1s) ----
77 let qt: *i64 = sys_mmap(64 * 8) as *i64
78 i = 0
79 while i < 64 { qt[i] = 1; i = i + 1 }
80
81 // ---- Bitstream: 0x00 = "0 0" = DC sym 0 (cat 0) + AC EOB ----
82 let stream: *u8 = sys_mmap(8)
83 stream[0] = 0x00
84 stream[1] = 0x00
85
86 // ---- Bitstream cursor (struct API) ----
87 let bs: *NxJpegBitStream = sys_mmap(NX_JPEG_BITSTREAM_BYTES) as *NxJpegBitStream
88 bs.src = stream
89 bs.src_end = 2
90 bs.byte_idx = 0
91 bs.bit_off = 0
92
93 let prev_dc_p: *i64 = sys_mmap(8) as *i64
94 prev_dc_p[0] = 0
95
96 // ---- Output plane: 8x8 u8, init to 0xFF to verify writes ----
97 let plane: *u8 = sys_mmap(64)
98 i = 0
99 while i < 64 { plane[i] = 0xFF; i = i + 1 }
100
101 // ---- Scratch context (cosine table + 3 i64 64-entry buffers) ----
102 let sc: *NxJpegMcuScratch = sys_mmap(NX_JPEG_MCU_SCRATCH_BYTES) as *NxJpegMcuScratch
103 nx_jpeg_mcu_scratch_init(sc)
104
105 // ---- Decode one block at (0, 0) ----
106 let rc: i64 = nx_jpeg_mcu_decode_one_block(
107 dc_table, ac_table, qt, prev_dc_p,
108 bs, plane, 8, 0, 0, sc)
109 if rc != NX_JPEG_MCU_OK { _fail(10 + rc); return 10 }
110
111 // ---- Verify: all 64 plane bytes are 128 (level-shift of zero block) ----
112 var k: i64 = 0
113 while k < 64 {
114 if plane[k] != 128 {
115 _fail(20 + k); return 20
116 }
117 k = k + 1
118 }
119
120 // ---- Verify prev_dc was updated to 0 (DC delta was 0) ----
121 if prev_dc_p[0] != 0 { _fail(100); return 100 }
122
123 let pass: *u8 = sys_mmap(16)
124 pass[0]=0x50; pass[1]=0x41; pass[2]=0x53; pass[3]=0x53; pass[4]=0x0A
125 sys_write(1, pass, 5)
126 return 0
127}