From 195a1c2ddd0d7a0b4b8e0cea98ea3864dd924b87 Mon Sep 17 00:00:00 2001
From: cuu <gnubsd@me.com>
Date: Fri, 28 Mar 2025 00:01:51 +0800
Subject: [PATCH] picocalc_helloworld add psram code

---
 .gitmodules                             |   3 +
 Code/picocalc_helloworld/CMakeLists.txt |  15 ++-
 Code/picocalc_helloworld/main.c         | 168 +++++++++++++++++++++++-
 Code/picocalc_helloworld/rp2040-psram   |   1 +
 4 files changed, 185 insertions(+), 2 deletions(-)
 create mode 100644 .gitmodules
 create mode 160000 Code/picocalc_helloworld/rp2040-psram

diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..e223fbb
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "Code/picocalc_helloworld/rp2040-psram"]
+	path = Code/picocalc_helloworld/rp2040-psram
+	url = https://github.com/polpo/rp2040-psram.git
diff --git a/Code/picocalc_helloworld/CMakeLists.txt b/Code/picocalc_helloworld/CMakeLists.txt
index d2104ac..7a9e358 100644
--- a/Code/picocalc_helloworld/CMakeLists.txt
+++ b/Code/picocalc_helloworld/CMakeLists.txt
@@ -15,10 +15,23 @@ include_directories(
 add_subdirectory(i2ckbd)
 add_subdirectory(lcdspi)
 
+add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/rp2040-psram rp2040-psram)
+
 add_executable(picocalc_helloworld
 	main.c
 	)
 
+##picocalc spi0
+target_compile_definitions(picocalc_helloworld PRIVATE
+    PSRAM_MUTEX=1
+    #PSRAM_SPINLOCK=0
+    PSRAM_ASYNC=0
+    PSRAM_PIN_CS=20
+    PSRAM_PIN_SCK=21
+    PSRAM_PIN_MOSI=2
+    PSRAM_PIN_MISO=3
+)
+
 target_link_libraries(picocalc_helloworld
     pico_stdlib
     hardware_flash
@@ -33,7 +46,7 @@ target_link_libraries(picocalc_helloworld
     pico_multicore
 	i2ckbd
 	lcdspi
-
+    rp2040-psram
 	)
 
 pico_enable_stdio_usb(picocalc_helloworld 0)
diff --git a/Code/picocalc_helloworld/main.c b/Code/picocalc_helloworld/main.c
index 4a49a45..bc09c02 100644
--- a/Code/picocalc_helloworld/main.c
+++ b/Code/picocalc_helloworld/main.c
@@ -9,8 +9,170 @@
 
 #include "i2ckbd.h"
 #include "lcdspi.h"
+#include "psram_spi.h"
 
 const uint LEDPIN = 25;
+psram_spi_inst_t* async_spi_inst;
+
+int psram_test(psram_spi_inst_t*psram_spi){
+    uint32_t psram_begin, psram_elapsed;
+    float psram_speed;
+    char buf[128];
+    sprintf(buf,"Testing PSRAM...\n");
+    printf("%s",buf);
+    lcd_print_string(buf);
+
+    // **************** 8 bits testing ****************
+    psram_begin = time_us_32();
+    for (uint32_t addr = 0; addr < (8 * 1024 * 1024); ++addr) {
+        psram_write8(psram_spi, addr, (addr & 0xFF));
+    }
+    psram_elapsed = time_us_32() - psram_begin;
+    psram_speed = 1000000.0 * 8 * 1024.0 * 1024 / psram_elapsed;
+    sprintf(buf,"8 bit: PSRAM write 8MB in %d us, %d B/s\n", psram_elapsed, (uint32_t)psram_speed);
+    printf("%s", buf);
+    lcd_print_string(buf);
+
+    psram_begin = time_us_32();
+    for (uint32_t addr = 0; addr < (8 * 1024 * 1024); ++addr) {
+        psram_write8_async(psram_spi, addr, (addr & 0xFF));
+    }
+    psram_elapsed = time_us_32() - psram_begin;
+    psram_speed = 1000000.0 * 8 * 1024.0 * 1024 / psram_elapsed;
+    sprintf(buf,"8 bit: PSRAM write async 8MB in %d us, %d B/s\n", psram_elapsed, (uint32_t)psram_speed);
+    printf("%s", buf);
+    lcd_print_string(buf);
+
+    psram_begin = time_us_32();
+    for (uint32_t addr = 0; addr < (8 * 1024 * 1024); ++addr) {
+        uint8_t result = psram_read8(psram_spi, addr);
+        if ((uint8_t)(addr & 0xFF) != result) {
+            sprintf(buf,"\nPSRAM failure at address %x (%x != %x)\n", addr, addr & 0xFF, result);
+            printf("%s", buf);
+            lcd_print_string(buf);
+            return 1;
+        }
+    }
+    psram_elapsed = time_us_32() - psram_begin;
+    psram_speed = 1000000.0 * 8 * 1024.0 * 1024 / psram_elapsed;
+    sprintf(buf,"8 bit: PSRAM read 8MB in %d us, %d B/s\n", psram_elapsed, (uint32_t)psram_speed);
+    printf("%s", buf);
+    lcd_print_string(buf);
+
+    // **************** 16 bits testing ****************
+    psram_begin = time_us_32();
+    for (uint32_t addr = 0; addr < (8 * 1024 * 1024); addr += 2) {
+        psram_write16(psram_spi, addr, (((addr + 1) & 0xFF) << 8) | (addr & 0xFF));
+    }
+    psram_elapsed = time_us_32() - psram_begin;
+    psram_speed = 1000000.0 * 8 * 1024.0 * 1024 / psram_elapsed;
+    sprintf(buf,"16 bit: PSRAM write 8MB in %d us, %d B/s\n", psram_elapsed, (uint32_t)psram_speed);
+    printf("%s", buf);
+    lcd_print_string(buf);
+
+    psram_begin = time_us_32();
+    for (uint32_t addr = 0; addr < (8 * 1024 * 1024); addr += 2) {
+        uint16_t result = psram_read16(psram_spi, addr);
+        if ((uint16_t)(
+                (((addr + 1) & 0xFF) << 8) |
+                (addr & 0xFF)) != result
+                ) {
+            sprintf(buf,"PSRAM failure at address %x (%x != %x) ", addr, (
+                    (((addr + 1) & 0xFF) << 8) |
+                    (addr & 0xFF)), result
+            );
+            printf("%s", buf);
+            lcd_print_string(buf);
+            return 1;
+        }
+    }
+    psram_elapsed = (time_us_32() - psram_begin);
+    psram_speed = 1000000.0 * 8 * 1024 * 1024 / psram_elapsed;
+    sprintf(buf,"16 bit: PSRAM read 8MB in %d us, %d B/s\n", psram_elapsed, (uint32_t)psram_speed);
+    printf("%s", buf);
+    lcd_print_string(buf);
+
+    // **************** 32 bits testing ****************
+    psram_begin = time_us_32();
+    for (uint32_t addr = 0; addr < (8 * 1024 * 1024); addr += 4) {
+        psram_write32(
+                psram_spi, addr,
+                (uint32_t)(
+                        (((addr + 3) & 0xFF) << 24) |
+                        (((addr + 2) & 0xFF) << 16) |
+                        (((addr + 1) & 0xFF) << 8)  |
+                        (addr & 0XFF))
+        );
+    }
+    psram_elapsed = time_us_32() - psram_begin;
+    psram_speed = 1000000.0 * 8 * 1024.0 * 1024 / psram_elapsed;
+    sprintf(buf,"32 bit: PSRAM write 8MB in %d us, %d B/s\n", psram_elapsed, (uint32_t)psram_speed);
+    printf("%s", buf);
+    lcd_print_string(buf);
+
+    psram_begin = time_us_32();
+    for (uint32_t addr = 0; addr < (8 * 1024 * 1024); addr += 4) {
+        uint32_t result = psram_read32(psram_spi, addr);
+        if ((uint32_t)(
+                (((addr + 3) & 0xFF) << 24) |
+                (((addr + 2) & 0xFF) << 16) |
+                (((addr + 1) & 0xFF) << 8)  |
+                (addr & 0XFF)) != result
+                ) {
+            sprintf(buf,"PSRAM failure at address %x (%x != %x) ", addr, (
+                    (((addr + 3) & 0xFF) << 24) |
+                    (((addr + 2) & 0xFF) << 16) |
+                    (((addr + 1) & 0xFF) << 8)  |
+                    (addr & 0XFF)), result
+            );
+            printf("%s", buf);
+            lcd_print_string(buf);
+            return 1;
+        }
+    }
+    psram_elapsed = (time_us_32() - psram_begin);
+    psram_speed = 1000000.0 * 8 * 1024 * 1024 / psram_elapsed;
+    sprintf(buf,"32 bit: PSRAM read 8MB in %d us, %d B/s\n", psram_elapsed, (uint32_t)psram_speed);
+    printf("%s", buf);
+    lcd_print_string(buf);
+    // **************** n bits testing ****************
+    uint8_t write_data[256];
+    for (size_t i = 0; i < 256; ++i) {
+        write_data[i] = i;
+    }
+    psram_begin = time_us_32();
+    for (uint32_t addr = 0; addr < (8 * 1024 * 1024); addr += 256) {
+        for (uint32_t step = 0; step < 256; step += 16) {
+            psram_write(psram_spi, addr + step, write_data + step, 16);
+        }
+    }
+    psram_elapsed = time_us_32() - psram_begin;
+    psram_speed = 1000000.0 * 8 * 1024.0 * 1024 / psram_elapsed;
+    sprintf(buf,"128 bit: PSRAM write 8MB in %d us, %d B/s\n", psram_elapsed, (uint32_t)psram_speed);
+    printf("%s", buf);
+    lcd_print_string(buf);
+
+    psram_begin = time_us_32();
+    uint8_t read_data[16];
+    for (uint32_t addr = 0; addr < (8 * 1024 * 1024); addr += 256) {
+        for (uint32_t step = 0; step < 256; step += 16) {
+            psram_read(psram_spi, addr + step, read_data, 16);
+            if (memcmp(read_data, write_data + step, 16) != 0) {
+                sprintf(buf,"PSRAM failure at address %x", addr);
+                printf("%s", buf);
+                lcd_print_string(buf);
+                return 1;
+            }
+        }
+    }
+    psram_elapsed = time_us_32() - psram_begin;
+    psram_speed = 1000000.0 * 8 * 1024.0 * 1024 / psram_elapsed;
+    sprintf(buf,"128 bit: PSRAM read 8MB in %d us, %d B/s\n", psram_elapsed, (uint32_t)psram_speed);
+    printf("%s", buf);
+    lcd_print_string(buf);
+
+    lcd_print_string("PSRAM testing done\n");
+}
 
 int main() {
 
@@ -23,10 +185,14 @@ int main() {
     gpio_set_dir(LEDPIN, GPIO_OUT);
 
     lcd_clear();
-    lcd_print_string("Hello World");
+    lcd_print_string("Hello World PicoCalc\n");
     gpio_put(LEDPIN, 1);
     sleep_ms(500);
     gpio_put(LEDPIN, 0);
+
+    psram_spi_inst_t psram_spi = psram_spi_init_clkdiv(pio1, -1,1.0f,true);
+
+    psram_test(&psram_spi);
     while (1) {
         int c = lcd_getc(0);
         if(c != -1 && c > 0) {
diff --git a/Code/picocalc_helloworld/rp2040-psram b/Code/picocalc_helloworld/rp2040-psram
new file mode 160000
index 0000000..7786c93
--- /dev/null
+++ b/Code/picocalc_helloworld/rp2040-psram
@@ -0,0 +1 @@
+Subproject commit 7786c93ec8d02dbb4f94a2e99645b25fb4abc2db