From 68c80359ba0983bc21a18c0270025be9b441c0bb Mon Sep 17 00:00:00 2001 From: Wojciech Kosior Date: Tue, 29 Dec 2020 19:56:04 +0100 Subject: 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 --- examples/example3a_spi_wasm/instructions.wat | 115 +++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 examples/example3a_spi_wasm/instructions.wat (limited to 'examples/example3a_spi_wasm/instructions.wat') 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))) -- cgit v1.2.3