blob: f09e080e34d3f56221149f540b587aa4c52250a3 (
about) (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
;; See instructions.wat of soc_print_number test. A lot has been taken from
;; there.
;; Relevant addresses are VGA text memory (0xFFC00), VGA regs (0x100600),
;; lower half of timer reg (0x1BFC08), SPI memory (0x13FC00),
;; SPI bytes_to_output reg (0x13FE00), SPI bytes_to_receive reg (0x13FE02)
;; and SPI operating reg (0x13FE04).
(module
(memory 0 2)
(func $main
(local $transfers i32)
(local $offset i32)
(local $address i32)
(local $index i32)
;; power up flash chip
;; set bytes_to_output to 1
(i32.store16 offset=0 align=2
(i32.const 0x13FE00) (i32.const 1))
;; set bytes_to_receive to 0
(i32.store16 offset=0 align=2
(i32.const 0x13FE02) (i32.const 0))
;; release power-down SPI command
(i32.store8 offset=0 align=1
(i32.const 0x13FC00) (i32.const 0xAB))
;; start SPI operation
(i32.store16 offset=0 align=2
(i32.const 0x13FE04) (i32.const 0x1))
;; wait for at least 3000 ns after command gets sent
;; reset the timer
(i32.store16 offset=0x0 align=2
(i32.const 0x1BFC08) (i32.const 0x0))
;; loop until 45 ticks pass; 45 ticks is 3600 ns; additional 600ns
;; is enough for power-up command to be sent
(loop $again
(br_if $again (i32.lt_u
(i32.load16_u offset=0x0 align=2
(i32.const 0x1BFC08))
(i32.const 45))))
;; we'll transfer 2400 bytes by making 5 transfers of 480 bytes;
;; our SPI peripheral can transfer at most 511 bytes in one SPI command
(set_local $transfers (i32.const 0))
(loop $outer
;; set bytes_to_output to 5
(i32.store16 offset=0 align=2
(i32.const 0x13FE00) (i32.const 5))
;; set bytes_to_receive to 480
(i32.store16 offset=0 align=2
(i32.const 0x13FE02) (i32.const 480))
;; fast read SPI command
(i32.store8 offset=0 align=1
(i32.const 0x13FC00) (i32.const 0x0B))
;; prepare address - first, compute current offset
(set_local $offset (i32.mul (get_local $transfers)
(i32.const 480)))
;; then, add computed offset to base address of 135100
(set_local $address (i32.add (get_local $offset)
(i32.const 135100)))
;; store the address in big endian
(i32.store16 offset=0 align=2
(i32.const 0x13FC02)
(i32.div_u (get_local $address)
(i32.const 256)))
(i32.store8 offset=0 align=1
(i32.const 0x13FC03) (get_local $address))
(i32.store8 offset=0 align=1
(i32.const 0x13FC01)
(i32.div_u (get_local $address)
(i32.const 65536)))
;; start SPI operation
(i32.store16 offset=0 align=2
(i32.const 0x13FE04) (i32.const 0x1))
;; force wait for operation completion
(i32.store16 offset=0 align=2
(i32.const 0x13FE00) (i32.const 0))
;; assume transferred data to be ascii text and print it to screen
;; initialize index to 0
(set_local $index (i32.const 0))
;; copy characters in a loop
(loop $inner
;; copy 4 characters to VGA memory
(i32.store offset=0xFFC00 align=4
(i32.add (get_local $index)
(get_local $offset))
(i32.load offset=0x13FC00 align=4
(get_local $index)))
;; increase index
(set_local $index (i32.add (get_local $index)
(i32.const 4)))
;; loop condition
(br_if $inner (i32.lt_u
(get_local $index)
(i32.const 480))))
;; increase transfers count
(set_local $transfers (i32.add (get_local $transfers)
(i32.const 1)))
;; switch LED2
(i32.store16 offset=0x0 align=2
(i32.const 0x1BFC06)
(i32.rem_u (get_local $transfers) (i32.const 2)))
;; if less than 5 transfers were done, continue with another one
(br_if $outer (i32.lt_u (get_local $transfers) (i32.const 5))))
;; write a non-zero value to the VGA power-on reg at 0x100600 (0x100A00)
(i32.store16 offset=0x0 align=2
(i32.const 0x100600) (i32.const 0x1)))
(export "main" (func $main)))
|