aboutsummaryrefslogtreecommitdiff
path: root/examples/example3a_spi_wasm/instructions.wat
diff options
context:
space:
mode:
authorWojciech Kosior <kwojtus@protonmail.com>2020-12-29 19:56:04 +0100
committerWojciech Kosior <kwojtus@protonmail.com>2020-12-29 19:56:04 +0100
commit68c80359ba0983bc21a18c0270025be9b441c0bb (patch)
treea06a04eb8756f96d05c55768bd356917847cdc95 /examples/example3a_spi_wasm/instructions.wat
parent5b6a3f3b216939a11ed1978d7da4dd6bbe4edc2a (diff)
downloadAGH-engineering-thesis-68c80359ba0983bc21a18c0270025be9b441c0bb.tar.gz
AGH-engineering-thesis-68c80359ba0983bc21a18c0270025be9b441c0bb.zip
add the ability to include additional data at the end of bitstream image and prepare an example, that reads thic data through SPI and displays it
Diffstat (limited to 'examples/example3a_spi_wasm/instructions.wat')
-rw-r--r--examples/example3a_spi_wasm/instructions.wat115
1 files changed, 115 insertions, 0 deletions
diff --git a/examples/example3a_spi_wasm/instructions.wat b/examples/example3a_spi_wasm/instructions.wat
new file mode 100644
index 0000000..f09e080
--- /dev/null
+++ b/examples/example3a_spi_wasm/instructions.wat
@@ -0,0 +1,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)))