diff --git a/nanosoc_board/C_Cxx/CMakeLists.txt b/nanosoc_board/C_Cxx/CMakeLists.txt index 40fc712324473d25b5b565ad3709b041e46fe0fb..59dddeddaa18a8451a7dd86c1004031928963715 100644 --- a/nanosoc_board/C_Cxx/CMakeLists.txt +++ b/nanosoc_board/C_Cxx/CMakeLists.txt @@ -41,4 +41,6 @@ add_subdirectory(no-OS-FatFS-SD-SPI-RPi-Pico/FatFs_SPI build) add_subdirectory(clock_scaling_power_measurement) add_subdirectory(nanosoc_demo) add_subdirectory(nanosoc_regression) +add_subdirectory(fast_knn_demo2) +add_subdirectory(srimanth_demo) #add_subdirectory(FT1248) \ No newline at end of file diff --git a/nanosoc_board/C_Cxx/fast_knn_demo2/CMakeLists.txt b/nanosoc_board/C_Cxx/fast_knn_demo2/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..2a3ddc018df68573ae8f837fe78f9d83cd92adf3 --- /dev/null +++ b/nanosoc_board/C_Cxx/fast_knn_demo2/CMakeLists.txt @@ -0,0 +1,40 @@ +if (TARGET tinyusb_device) + set(PROJECT_NAME fast_knn_demo2) + + # Add your source files + add_executable(${PROJECT_NAME} + fast_knn_demo2.cpp + hardware_config.c + ) + #target_compile_definitions(fast_knn_demo PRIVATE + ## PICO_DEFAULT_UART=0 + # PICO_DEFAULT_UART_TX_PIN=28 + # PICO_DEFAULT_UART_RX_PIN=29 + # PICO_DEFAULT_UART_BAUD_RATE=9600 + # ) + pico_enable_stdio_usb(${PROJECT_NAME} 1) + pico_enable_stdio_uart(${PROJECT_NAME} 0) + + pico_generate_pio_header(${PROJECT_NAME} + ${SOCLABS_PIO_PATH}/ft1248x1/ft1248x1_sm.pio + ) + + # Don't forget to link the libraries you need! + target_link_libraries(${PROJECT_NAME} + pico_explorer + hardware_pio + hardware_i2c + nanosoc_graphics + nanosoc_board_system + pico_multicore + I2C_device_bus + hardware_clocks + FatFs_SPI + ) + + + # create map/bin/hex file etc. + pico_add_extra_outputs(${PROJECT_NAME}) +elseif(PICO_ON_DEVICE) + message(WARNING "not building hello_usb because TinyUSB submodule is not initialized in the SDK") +endif() diff --git a/nanosoc_board/C_Cxx/fast_knn_demo2/fast_knn_demo2.cpp b/nanosoc_board/C_Cxx/fast_knn_demo2/fast_knn_demo2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..055387b66ef538cbbc6e741f4616f9ccbf7db26a --- /dev/null +++ b/nanosoc_board/C_Cxx/fast_knn_demo2/fast_knn_demo2.cpp @@ -0,0 +1,813 @@ +#include <string> +#include <math.h> +#include <vector> +#include <stdlib.h> +#include "ft1248x1_sm.pio.h" +#include "hardware/pio.h" +#include "hardware/pll.h" +#include "hardware/clocks.h" +#include "hardware/structs/pll.h" +#include "hardware/structs/clocks.h" +#include "pico/stdlib.h" +#include "hardware/i2c.h" +#include "ff.h" +#include "f_util.h" +#include "diskio.h" /* Declarations of disk functions */ +#include "sd_card.h" +#include "hw_config.h" +#include "nanosoc_graphics.hpp" + +#include "pico/multicore.h" +#include <stdio.h> +#include <cmath> + +extern "C"{ +#include "nanosoc_board_system.h" +#include "I2C_device_bus.h" +} + +#include "libraries/pico_display_2/pico_display_2.hpp" +#include "drivers/st7789/st7789.hpp" +#include "libraries/pico_graphics/pico_graphics.hpp" + +using namespace pimoroni; + +// Variables/structs for Graphics control of Pico Display +ST7789 st7789(320, 240, ROTATE_270, false, get_spi_pins(BG_SPI_FRONT)); +PicoGraphics_PenRGB332 graphics(st7789.width, st7789.height, nullptr); +Pen BG = graphics.create_pen(0, 0, 0); +Pen WHITE = graphics.create_pen(255, 255, 255); +bool BUTTON_Y_pressed = false; +bool BUTTON_X_pressed = false; +int x=0; +int y=0; +int xtext=0; +int ytext=0; + + +// Variables for screen/graphics state +const uint8_t CONSOLE_FIFO_DEPTH=32; +const uint NO_LABELLED_IMGS = 130; +const uint NO_UNLABELLED_IMGS = 36; +#define NO_OF_CLASSES 10 +#define NO_IMAGE_PER_CLASS NO_LABELLED_IMGS/NO_OF_CLASSES +#define K_KNN 3 +#define KNN_RESULTS_REG 0x30000100+3*4*NO_IMAGE_PER_CLASS + +std::string console[CONSOLE_FIFO_DEPTH]; +std::string labelled_files[NO_OF_CLASSES][NO_IMAGE_PER_CLASS]; +std::string unlabelled_files[NO_UNLABELLED_IMGS]; +uint8_t unlabelled_buffer[NO_UNLABELLED_IMGS][784]; +uint8_t labelled_buffer[NO_LABELLED_IMGS][784]; +uint8_t current_class = 0; + +// Path to labelled images +std::string labelled_image_dirs[10] = { + "./data/labelled_images/image0", + "./data/labelled_images/image1", + "./data/labelled_images/image2", + "./data/labelled_images/image3", + "./data/labelled_images/image4", + "./data/labelled_images/image5", + "./data/labelled_images/image6", + "./data/labelled_images/image7", + "./data/labelled_images/image8", + "./data/labelled_images/image9"}; + +// Path to unlabelled images +std::string unlabelled_image_dir = "0:/data/unlabelled_images"; + +Point console_text_location(5,30); +uint8_t console_addr_screen = 0; +uint8_t console_addr=0; +uint8_t current_labelled_image=0; +volatile uint current_image=0; +int current_img_buf[784]; +double knn_class_average[NO_IMAGE_PER_CLASS]; +int knn_min; + +// Enumerator for screen state, this allows for different 'pages' on the screen +typedef enum{ + HOME, + CONSOLE, + DEMO, + POWER +} screen_state; + +screen_state current_screen_state=HOME; +screen_state last_screen_state=POWER; + +// Global variables for Core 0 program flow +bool DEMO_RUN = false; +bool KNN_done = false; +bool KNN_start = false; +bool nanosoc_console = false; +bool nanosoc_console_draw = false; +bool new_unlabelled_img = true; +i2c_inst_t *i2c = i2c1; + +static spi_t spis[] = {{ + .hw_inst = spi0, + .miso_gpio = 0, + .mosi_gpio = 19, + .sck_gpio = 18, + .baud_rate = 12500 * 1000 +}}; + + +// Hardware Configuration of the SD Card "objects" +static sd_card_t sd_cards[] = {{ + .pcName = "0:", + .spi = &spis[0], + .ss_gpio = 1, + .use_card_detect = false +}}; + +// Adresses in nanosoc for labelled and unlabelled images +uint32_t labelled_image_addr[] = { + 0x80000000, + 0x80000310, + 0x80000620, + 0x80000930, + 0x80000C40, + 0x80000F50, + 0x80001260, + 0x80001570, + 0x80001880, + 0x80001B90}; + +uint32_t unlabelled_image_addr[] = { + 0x90000000, + 0x90000310, + 0x90000620, + 0x90000930, + 0x90000C40, + 0x90000F50, + 0x90001260, + 0x90001570, + 0x90001880, + 0x90001B90}; + +int img_x_grid[] = {3, 83, 163}; +int img_y_grid[] = {30, 118, 206}; + +std::string classes[] = { + "T-Shirt", + "Trousers", + "Pullover", + "Dress", + "Coat", + "Sandal", + "Shirt", + "Sneaker", + "Bag", + "Boot"}; + +// Knn Results structure +struct KNN_result { + int classification; + float result; +}; + +bool compare_KNN_result(KNN_result k1, KNN_result k2){ + return (k1.result<k2.result); +} + +KNN_result knn_result[NO_LABELLED_IMGS]; +int maxcount=0; + +// Button IRQ (for controlling screen state) +void BUTTON_irq(uint gpio, uint32_t events) { + if(gpio==BUTTON_A){ + // if button A is pressed: increment through screen states + switch(current_screen_state) { + case HOME: + current_screen_state=CONSOLE; + break; + case CONSOLE: + current_screen_state=DEMO; + break; + case DEMO: + current_screen_state=POWER; + break; + case POWER: + current_screen_state=HOME; + break; + default: + current_screen_state = HOME; + } + + } + else if (gpio==BUTTON_B){ + // if button B is pressed: decrement through screen states + switch(current_screen_state) { + case HOME: + current_screen_state=POWER; + break; + case CONSOLE: + current_screen_state=HOME; + break; + case DEMO: + current_screen_state=CONSOLE; + break; + case POWER: + current_screen_state=DEMO; + break; + default: + current_screen_state = HOME; + } + } + else if (gpio == BUTTON_X){ + BUTTON_X_pressed = true; + } + else if (gpio == BUTTON_Y){ + BUTTON_Y_pressed = true; + } + +} + +// Screen refresh, clears the screen and sets the header and footer bar +void screen_refresh(){ + graphics.set_pen(BG); + graphics.clear(); + Rect blank(0,302,240,18); + graphics.set_pen(WHITE); + graphics.rectangle(blank); + graphics.set_pen(WHITE); + Rect blank1(0,0,240,18); + graphics.rectangle(blank1); +} + +// Routine for the HOME page: just displays a welcome message +void HOME_ROUTINE(){ + Point title_location(0, 2); + Point text_location(10,50); + if(current_screen_state!=last_screen_state){ + graphics.set_pen(WHITE); + Rect blank(0,0,240,18); + graphics.rectangle(blank); + graphics.set_pen(BG); + graphics.text(" <- HOME ->", title_location, 600); + graphics.set_pen(WHITE); + graphics.text("Welcome to Fast-KNN!",text_location, 230); + text_location.y+=30; + graphics.text("Fast-KNN is a K-nearest neighbour algorythm within the nannoSoC re-usable SoC framework. To use the testboard- press the A button to go one screen forward and B button to go back a screen", text_location, 225); + last_screen_state = HOME; + nanosoc_console = false; + } + if(BUTTON_X_pressed){ + BUTTON_X_pressed=false; + } + if(BUTTON_Y_pressed){ + BUTTON_Y_pressed=false; + } + +} + +// Routine for CONSOLE Page, prints out everything in the console FIFO to screen and clears when it gets to the end +void CONSOLE_ROUTINE(){ + Point title_location(0, 2); + Point footer_location(10,304); + Rect console_BG(0,18,240,284); + uint32_t data; + nanosoc_console = true; + if(current_screen_state!=last_screen_state){ + console_text_location.x = 5; + console_text_location.y = 30; + graphics.set_pen(BG); + graphics.text(" <- CONSOLE ->", title_location, 600); + graphics.text(" Reset Clear ",footer_location,600); + last_screen_state = CONSOLE; + } + if(current_screen_state==last_screen_state){ + if(nanosoc_console_draw){ + if (console_text_location.y > 298){ + console_text_location.y = 30; + graphics.set_pen(BG); + graphics.rectangle(console_BG); + } + + graphics.set_pen(WHITE); + graphics.text(console[console_addr_screen], console_text_location, 1000); + console_text_location.y += 16; + + // update screen + //st7789.update(&graphics); + console[console_addr_screen].clear(); + console_addr_screen++; + if(console_addr_screen == CONSOLE_FIFO_DEPTH){ + console_addr_screen=0; + } + if(console[console_addr_screen].empty()){ + nanosoc_console_draw=false; + } + } + } + if(BUTTON_X_pressed){ + // Clear console and fifo + graphics.set_pen(BG); + graphics.rectangle(console_BG); + console_text_location.y=30; + for(int i = 0; i<CONSOLE_FIFO_DEPTH; i++){ + console[i].clear(); + } + console_addr = 0; + console_addr_screen=0; + BUTTON_X_pressed=false; + } + if(BUTTON_Y_pressed){ + nanosoc_reset(i2c); + BUTTON_Y_pressed=false; + } +} + +// Routine for Demo Page +// Draws the unlabelled image that is currently being processed and once finished prints the classification label +void DEMO_ROUTINE(){ + Point title_location(0, 2); + Point result_location; + Point footer_location(10,304); + int x_plot; + int y_plot; + if(current_screen_state!=last_screen_state){ + graphics.set_pen(BG); + graphics.text(" <- Fast KNN DEMO ->", title_location, 600); + graphics.text(" Start ",footer_location,600); + last_screen_state = DEMO; + nanosoc_console = false; + } + if(current_screen_state==last_screen_state){ + if(KNN_start){ + x_plot = img_x_grid[x]; + y_plot = img_y_grid[y]; + screen_draw_vector(graphics,st7789,&unlabelled_buffer[current_image][0],x_plot, y_plot,28,28,2); + x++; + if(x>=3){ + x=0; + y++; + if(y>=3){ + y=0; + } + } + KNN_start=false; + printf("printed image\n"); + } + if(KNN_done){ + // KNN finished, plot the result + result_location.x = img_x_grid[xtext]; + result_location.y = img_y_grid[ytext]+60; + // - clear text area + graphics.set_pen(BG); + Rect blank(result_location.x-2, result_location.y-4, 60, 22); + graphics.rectangle(blank); + // - draw text + graphics.set_pen(WHITE); + graphics.text(classes[knn_min] ,result_location, result_location.x+56); + xtext++; + if(xtext>=3){ + xtext=0; + ytext++; + if(ytext>=3){ + ytext=0; + } + } + printf("printed result\n"); + DEMO_RUN=true; + KNN_done=false; + } + } + if(BUTTON_X_pressed){ + DEMO_RUN=true; + BUTTON_X_pressed=false; + } + if(BUTTON_Y_pressed){ + BUTTON_Y_pressed=false; + } +} +void POWER_ROUTINE(){ + Point title_location(0, 2); + Point footer_location(10,304); + Point text_location(5,50); + Point power_stat_location(185,50); + Rect power_stat_bg(183,48,100,115); + float result; + char print_result[10]; + std::string print_buf; + if(current_screen_state!=last_screen_state){ + graphics.set_pen(BG); + graphics.text(" <- POWER ->", title_location, 600); + graphics.text(" ",footer_location,600); + graphics.set_pen(WHITE); + graphics.text("Core Voltage (V)= ",text_location,600); + text_location.y+=16; + graphics.text("Core Current (mA)= ",text_location,600); + text_location.y+=16; + graphics.text("Core Power (mW)= ",text_location,600); + text_location.y+=16; + text_location.y+=16; + graphics.text("Accel Voltage (V)= ",text_location,600); + text_location.y+=16; + graphics.text("Accel Current(mA)= ",text_location,600); + text_location.y+=16; + graphics.text("Accel Power (mW)= ",text_location,600); + last_screen_state = POWER; + nanosoc_console = false; + } + if(current_screen_state==last_screen_state){ + + power_stat_location.y=50; + + graphics.set_pen(BG); + graphics.rectangle(power_stat_bg); + graphics.set_pen(WHITE); + + result = nanosoc_read_bus_voltage(i2c, VDD_MONITOR); + sprintf(print_result, "%1.3f",result); + print_buf = print_result; + graphics.text(print_buf, power_stat_location, 600); + power_stat_location.y+=16; + + result = 1e3*nanosoc_read_current(i2c, VDD_MONITOR); + sprintf(print_result, "%1.3f",result); + print_buf = print_result; + graphics.text(print_buf, power_stat_location, 600); + power_stat_location.y+=16; + + result = 1e3*nanosoc_read_power(i2c, VDD_MONITOR); + sprintf(print_result, "%1.3f",result); + print_buf = print_result; + graphics.text(print_buf, power_stat_location, 600); + power_stat_location.y+=16; + power_stat_location.y+=16; + + result = nanosoc_read_bus_voltage(i2c, VDDACC_MONITOR); + sprintf(print_result, "%1.3f",result); + print_buf = print_result; + graphics.text(print_buf, power_stat_location, 600); + power_stat_location.y+=16; + + result = 1e3*nanosoc_read_current(i2c, VDDACC_MONITOR); + sprintf(print_result, "%1.3f",result); + print_buf = print_result; + graphics.text(print_buf, power_stat_location, 600); + power_stat_location.y+=16; + + result = 1e3*nanosoc_read_power(i2c, VDDACC_MONITOR); + sprintf(print_result, "%1.3f",result); + print_buf = print_result; + graphics.text(print_buf, power_stat_location, 600); + power_stat_location.y+=16; + } + if(BUTTON_X_pressed){ + BUTTON_X_pressed=false; + } + if(BUTTON_Y_pressed){ + BUTTON_Y_pressed=false; + } +} + +void core1_entry(){ + // Set GPIO for buttons + gpio_init(BUTTON_A); + gpio_set_dir(BUTTON_A, GPIO_IN); + gpio_pull_up(BUTTON_A); + gpio_init(BUTTON_B); + gpio_set_dir(BUTTON_B, GPIO_IN); + gpio_pull_up(BUTTON_B); + gpio_init(BUTTON_X); + gpio_set_dir(BUTTON_X, GPIO_IN); + gpio_pull_up(BUTTON_X); + gpio_init(BUTTON_Y); + gpio_set_dir(BUTTON_Y, GPIO_IN); + gpio_pull_up(BUTTON_Y); + + // Setup interrupts for GPIO + gpio_set_irq_enabled_with_callback(BUTTON_A, GPIO_IRQ_EDGE_RISE, true, &BUTTON_irq); + gpio_set_irq_enabled(BUTTON_B, GPIO_IRQ_EDGE_RISE, true); + gpio_set_irq_enabled(BUTTON_X, GPIO_IRQ_EDGE_RISE, true); + gpio_set_irq_enabled(BUTTON_Y, GPIO_IRQ_EDGE_RISE, true); + + + // Set screen backlight (0-255) + st7789.set_backlight(255); + + + Point title_location(100, 0); + + graphics.set_pen(BG); + graphics.clear(); + graphics.set_pen(WHITE); + graphics.set_font(&font8); + while(1){ + if(current_screen_state!=last_screen_state){ + screen_refresh(); + } + + switch(current_screen_state) { + case HOME: + HOME_ROUTINE(); + break; + case CONSOLE: + CONSOLE_ROUTINE(); + break; + case DEMO: + DEMO_ROUTINE(); + break; + case POWER: + POWER_ROUTINE(); + break; + default: + current_screen_state = HOME; + } + st7789.update(&graphics); + } +} + + + + +int main() { + // Set GPIO for Data handshaking + gpio_init(26); + gpio_set_dir(26, GPIO_IN); + gpio_pull_up(26); + gpio_init(27); + gpio_set_dir(27, GPIO_OUT); + gpio_put(27,0); + + + stdio_init_all(); + //while(!stdio_usb_connected()){;} + + sleep_ms(500); + + // Setup nanosoc + nanosoc_i2c_init(i2c); + + PIO pio = pio0; + uint offset = pio_add_program(pio, &ft1248x1_sm_program); + uint sm = pio_claim_unused_sm(pio, true); + + ft1248x1_sm_program_init(pio, sm, offset); + pio_sm_clear_fifos(pio, sm); + pio_sm_restart(pio, sm); + sleep_ms(500); + + char buf[128]; + int len; + + + // Mount SD card + sd_card_t *pSD = &sd_cards[0]; + FRESULT fr = f_mount(&pSD->fatfs, pSD->pcName, 1); + if (FR_OK != fr) { + printf("f_mount error: %s (%d)\n", FRESULT_str(fr), fr); + } + else{ + printf("SD Card mounted\n"); + } + + // Read contents of ./programs from SD card + DIR dir; + static FILINFO fno; + uint i; + FRESULT res; + for(int j=0;j<10;j++){ + res = f_opendir(&dir, labelled_image_dirs[j].c_str()); + if (res == FR_OK) { + for (int i=0;i<NO_IMAGE_PER_CLASS;i++) { + res = f_readdir(&dir, &fno); /* Read a directory item */ + if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */ + else { /* It is a file. */ + labelled_files[j][i] = fno.fname; + } + } + f_closedir(&dir); + } + } + + // Read contents of unlabelled image directory from SD card + res = f_opendir(&dir, unlabelled_image_dir.c_str()); + if (res == FR_OK) { + for (int i=0;i<NO_UNLABELLED_IMGS;i++) { + res = f_readdir(&dir, &fno); /* Read a directory item */ + if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */ + else { /* It is a file. */ + unlabelled_files[i] = fno.fname; + } + } + f_closedir(&dir); + } + + // Clear FT1248 buffer + while(!pio_sm_is_rx_fifo_empty(pio,sm)){ + len = pio_ft1248_read8_blocking(pio, sm, &buf[0]); + for (int i = 0; i < len; i++) + { + printf("%c", (buf[i])); + } + } + + + // Main demo Start + FIL fil; + // Download program to nanosoc + f_chdir("./programs"); + fr = f_open(&fil, "fast_knn_demo2.hex", FA_READ); + if (FR_OK != fr && FR_EXIST != fr){ + printf("f_open(fast_knn_demo2.hex) error: %s (%d)\n", FRESULT_str(fr), fr); + printf("Can't open demo program. Is SD Card inserted?\n"); + return 1; + } + nanosoc_download_program(pio, sm, fil); + fr = f_close(&fil); + if (FR_OK != fr) { + printf("f_close error: %s (%d)\n", FRESULT_str(fr), fr); + } + f_chdir("/"); + + // Load labelled images to buffer + for(int i=0; i<NO_OF_CLASSES; i++){ + f_chdir(labelled_image_dirs[i].c_str()); + for(int j =0; j<NO_IMAGE_PER_CLASS; j++){ + fr = f_open(&fil, labelled_files[i][j].c_str(), FA_READ); + if (FR_OK != fr && FR_EXIST != fr){ + printf("f_open(%s) error: %s (%d)\n", labelled_files[i][j].c_str(), FRESULT_str(fr), fr); + } + char fil_buf[8]=""; + char * pEnd; + int k=0; + while(f_gets(fil_buf, 8, &fil)){ + labelled_buffer[j+i*NO_IMAGE_PER_CLASS][k] = strtol(fil_buf,&pEnd,16); + k++; + } + fr = f_close(&fil); + if (FR_OK != fr) { + printf("f_close error: %s (%d)\n", FRESULT_str(fr), fr); + } + } + f_chdir("/"); + } + + // Load Unlabelled images to buffer + f_chdir(unlabelled_image_dir.c_str()); + for(int j =0; j<NO_UNLABELLED_IMGS; j++){ + fr = f_open(&fil, unlabelled_files[j].c_str(), FA_READ); + if (FR_OK != fr && FR_EXIST != fr){ + printf("f_open(%s) error: %s (%d)\n", unlabelled_files[j].c_str(), FRESULT_str(fr), fr); + } + char fil_buf[8]=""; + char * pEnd; + int k=0; + while(f_gets(fil_buf, 8, &fil)){ + unlabelled_buffer[j][k] = strtol(fil_buf,&pEnd,16); + k++; + } + fr = f_close(&fil); + if (FR_OK != fr) { + printf("f_close error: %s (%d)\n", FRESULT_str(fr), fr); + } + } + f_chdir("/"); + + + f_unmount(pSD->pcName); + + uint current_image_addr=0; + uint timeout=0; + + // Reset nanosoc for program start + nanosoc_reset(i2c); + sleep_ms(100); + + // Launch Core 1 to handle graphics + multicore_launch_core1(core1_entry); + + + // Main loop for Core 0 + while(1){ + // Wait for GPIO handshake and if DEMO start button has been pressed + if(gpio_get(26) && DEMO_RUN && !KNN_done){ + // Either send new unlabelled image or new labelled image + if(new_unlabelled_img){ + KNN_start=true; + current_image_addr=0; + // Download unlabelled image to nanosoc + nanosoc_download_buffer(pio,sm,&unlabelled_buffer[current_image][0],unlabelled_image_addr[current_image_addr],784); + current_class=0; + current_image++; + if(current_image>=NO_UNLABELLED_IMGS){ + current_image=0; + } + new_unlabelled_img=false; + printf("Unlabelled image %s Downloaded \n", unlabelled_files[current_image].c_str()); + gpio_put(27,1); + //printf("GPIO 27 high\n"); + while(gpio_get(26)){ + if(!pio_sm_is_rx_fifo_empty(pio,sm)){ + len = pio_ft1248_readline(pio, sm, buf); + //printf("%c", buf); + } + } + gpio_put(27,0); + + } + else{ + // Send next labelled image + nanosoc_download_buffer(pio,sm,&labelled_buffer[current_labelled_image+current_class*NO_IMAGE_PER_CLASS][0],labelled_image_addr[current_image_addr],784); + // handshake transfer with nanosoc + //printf("Labelled image %s Downloaded \n", labelled_files[current_class][current_labelled_image].c_str()); + current_image_addr++; + if(current_image_addr>=10){ + current_image_addr=0; + } + + gpio_put(27,1); + //printf("GPIO 27 high\n"); + while(gpio_get(26)){ + if(!pio_sm_is_rx_fifo_empty(pio,sm)){ + len = pio_ft1248_readline(pio, sm, buf); + //printf("%c", buf); + } + } + gpio_put(27,0); + + // Wait for nanosoc to have completed everything and go back to start of its loop + while(!gpio_get(26)){ + if(!pio_sm_is_rx_fifo_empty(pio,sm)){ + len = pio_ft1248_readline(pio, sm, buf); + //printf("%c", buf); + } + } + + // Get results from nanosoc + knn_result[current_labelled_image+current_class*NO_IMAGE_PER_CLASS].result = sqrt(nanosoc_read_reg32(pio,sm,(KNN_RESULTS_REG+4*current_labelled_image))); + knn_result[current_labelled_image+current_class*NO_IMAGE_PER_CLASS].classification = current_class; + current_labelled_image++; + + // If that was the last labelled image of the class + if(current_labelled_image>=NO_IMAGE_PER_CLASS){ + current_labelled_image=0; + current_class++; + // If that was the last class + if(current_class>=NO_OF_CLASSES){ + // Find k nearest neighbours + // Sort from smallest to largest and store back in knn_result + std::sort(knn_result, knn_result+NO_LABELLED_IMGS, compare_KNN_result); + + // Reset the minimum knn (i.e. the classification for this image) and maxcount to count the K nearest + knn_min=0; + maxcount=0; + // Loop through the smallest K values of the sorted list + for(i=0;i<K_KNN;i++){ + int count=0; + for(int j=0;j<K_KNN;j++){ + // If knn_result[i] == knn_result[j] then increase the counter + if(knn_result[i].classification == knn_result[j].classification){ + count++; + } + } + // Find max number of elements + if(count>maxcount){ + maxcount=count; + knn_min = knn_result[i].classification; + } + } + printf("Min KNN is %d\n", knn_min); + // Handshake with core1 telling it to print the label and go to next image + new_unlabelled_img=true; + KNN_done=true; + DEMO_RUN=false; + } + } + } + } + + + // Always read in and store STDIO from nanosoc + while(!pio_sm_is_rx_fifo_empty(pio,sm)){ + len = pio_ft1248_readline(pio, sm, buf); + + for (int i =0; i <len; i++){ + console[console_addr] += buf[i]; + } + if(current_screen_state!=CONSOLE){ + printf(console[console_addr].c_str()); + console[console_addr].clear(); + } else{ + console_addr++; + if(console_addr == CONSOLE_FIFO_DEPTH){ + console_addr = 0; + } + nanosoc_console_draw = true; + if(nanosoc_console!=true){ + break; + } + } + } + + } + return 0; +} + + diff --git a/nanosoc_board/C_Cxx/fast_knn_demo2/hardware_config.c b/nanosoc_board/C_Cxx/fast_knn_demo2/hardware_config.c new file mode 100644 index 0000000000000000000000000000000000000000..f581d401551354883a994d2ecfd899b7877c19d0 --- /dev/null +++ b/nanosoc_board/C_Cxx/fast_knn_demo2/hardware_config.c @@ -0,0 +1,73 @@ +/* hw_config.c +Copyright 2021 Carl John Kugler III + +Licensed under the Apache License, Version 2.0 (the License); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at + + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +*/ +/* + +This file should be tailored to match the hardware design. + +There should be one element of the spi[] array for each hardware SPI used. + +There should be one element of the sd_cards[] array for each SD card slot. +The name is should correspond to the FatFs "logical drive" identifier. +(See http://elm-chan.org/fsw/ff/doc/filename.html#vol) +The rest of the constants will depend on the type of +socket, which SPI it is driven by, and how it is wired. + +*/ + +#include <string.h> +// +#include "my_debug.h" +// +#include "hw_config.h" +// +#include "ff.h" /* Obtains integer types */ +// +#include "diskio.h" /* Declarations of disk functions */ + +static spi_t spis[] = {{ + .hw_inst = spi0, + .miso_gpio = 0, + .mosi_gpio = 19, + .sck_gpio = 18, + .baud_rate = 12500 * 1000 +}}; + + +// Hardware Configuration of the SD Card "objects" +static sd_card_t sd_cards[] = {{ + .pcName = "0:", + .spi = &spis[0], + .ss_gpio = 1, + .use_card_detect = false +}}; + +/* ********************************************************************** */ +size_t sd_get_num() { return count_of(sd_cards); } +sd_card_t *sd_get_by_num(size_t num) { + if (num <= sd_get_num()) { + return &sd_cards[num]; + } else { + return NULL; + } +} +size_t spi_get_num() { return count_of(spis); } +spi_t *spi_get_by_num(size_t num) { + if (num <= sd_get_num()) { + return &spis[num]; + } else { + return NULL; + } +} + +/* [] END OF FILE */ diff --git a/nanosoc_board/C_Cxx/srimanth_demo/CMakeLists.txt b/nanosoc_board/C_Cxx/srimanth_demo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..44a3f080390ce838a16de92e846b47bf21c75b0d --- /dev/null +++ b/nanosoc_board/C_Cxx/srimanth_demo/CMakeLists.txt @@ -0,0 +1,39 @@ +if (TARGET tinyusb_device) + set(PROJECT_NAME srimanth_demo) + + # Add your source files + add_executable(${PROJECT_NAME} + srimanth_demo.cpp + hardware_config.c + ) + #target_compile_definitions(srimanth_demo PRIVATE + ## PICO_DEFAULT_UART=0 + # PICO_DEFAULT_UART_TX_PIN=28 + # PICO_DEFAULT_UART_RX_PIN=29 + # PICO_DEFAULT_UART_BAUD_RATE=9600 + # ) + pico_enable_stdio_usb(${PROJECT_NAME} 1) + pico_enable_stdio_uart(${PROJECT_NAME} 0) + + pico_generate_pio_header(srimanth_demo + ${SOCLABS_PIO_PATH}/ft1248x1/ft1248x1_sm.pio + ) + + # Don't forget to link the libraries you need! + target_link_libraries(${PROJECT_NAME} + pico_explorer + hardware_pio + hardware_i2c + nanosoc_board_system + pico_multicore + I2C_device_bus + hardware_clocks + FatFs_SPI + ) + + + # create map/bin/hex file etc. + pico_add_extra_outputs(${PROJECT_NAME}) +elseif(PICO_ON_DEVICE) + message(WARNING "not building hello_usb because TinyUSB submodule is not initialized in the SDK") +endif() diff --git a/nanosoc_board/C_Cxx/srimanth_demo/hardware_config.c b/nanosoc_board/C_Cxx/srimanth_demo/hardware_config.c new file mode 100644 index 0000000000000000000000000000000000000000..f581d401551354883a994d2ecfd899b7877c19d0 --- /dev/null +++ b/nanosoc_board/C_Cxx/srimanth_demo/hardware_config.c @@ -0,0 +1,73 @@ +/* hw_config.c +Copyright 2021 Carl John Kugler III + +Licensed under the Apache License, Version 2.0 (the License); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at + + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +*/ +/* + +This file should be tailored to match the hardware design. + +There should be one element of the spi[] array for each hardware SPI used. + +There should be one element of the sd_cards[] array for each SD card slot. +The name is should correspond to the FatFs "logical drive" identifier. +(See http://elm-chan.org/fsw/ff/doc/filename.html#vol) +The rest of the constants will depend on the type of +socket, which SPI it is driven by, and how it is wired. + +*/ + +#include <string.h> +// +#include "my_debug.h" +// +#include "hw_config.h" +// +#include "ff.h" /* Obtains integer types */ +// +#include "diskio.h" /* Declarations of disk functions */ + +static spi_t spis[] = {{ + .hw_inst = spi0, + .miso_gpio = 0, + .mosi_gpio = 19, + .sck_gpio = 18, + .baud_rate = 12500 * 1000 +}}; + + +// Hardware Configuration of the SD Card "objects" +static sd_card_t sd_cards[] = {{ + .pcName = "0:", + .spi = &spis[0], + .ss_gpio = 1, + .use_card_detect = false +}}; + +/* ********************************************************************** */ +size_t sd_get_num() { return count_of(sd_cards); } +sd_card_t *sd_get_by_num(size_t num) { + if (num <= sd_get_num()) { + return &sd_cards[num]; + } else { + return NULL; + } +} +size_t spi_get_num() { return count_of(spis); } +spi_t *spi_get_by_num(size_t num) { + if (num <= sd_get_num()) { + return &spis[num]; + } else { + return NULL; + } +} + +/* [] END OF FILE */ diff --git a/nanosoc_board/C_Cxx/srimanth_demo/srimanth_demo.cpp b/nanosoc_board/C_Cxx/srimanth_demo/srimanth_demo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7c82d3d719d2dc345b05cdeb2b95f7ea00f37167 --- /dev/null +++ b/nanosoc_board/C_Cxx/srimanth_demo/srimanth_demo.cpp @@ -0,0 +1,592 @@ +#include <string> +#include <math.h> +#include <vector> +#include <stdlib.h> +#include "ft1248x1_sm.pio.h" +#include "hardware/pio.h" +#include "hardware/pll.h" +#include "hardware/clocks.h" +#include "hardware/structs/pll.h" +#include "hardware/structs/clocks.h" +#include "pico/stdlib.h" +#include "hardware/i2c.h" +#include "ff.h" +#include "f_util.h" +#include "diskio.h" /* Declarations of disk functions */ +#include "sd_card.h" +#include "hw_config.h" + +#include "pico/multicore.h" +#include <stdio.h> + +extern "C"{ +#include "nanosoc_board_system.h" +#include "I2C_device_bus.h" +} + + +#include "libraries/pico_display_2/pico_display_2.hpp" +#include "drivers/st7789/st7789.hpp" +#include "libraries/pico_graphics/pico_graphics.hpp" + +using namespace pimoroni; + +// Variables/structs for Graphics control of Pico Display +ST7789 st7789(320, 240, ROTATE_270, false, get_spi_pins(BG_SPI_FRONT)); +PicoGraphics_PenRGB332 graphics(st7789.width, st7789.height, nullptr); +Pen BG = graphics.create_pen(32, 54, 105); +Pen WHITE = graphics.create_pen(255, 255, 255); +Pen Setosa = graphics.create_pen(0xCC, 0, 0xCC); +Pen Versicolor = graphics.create_pen(0, 0xFF, 0x80); +Pen Virginica = graphics.create_pen(0xFF, 0x80, 0); + +bool BUTTON_Y_pressed = false; +bool BUTTON_X_pressed = false; + +// Variables for screen/graphics state +const uint8_t CONSOLE_FIFO_DEPTH=128; +std::string console[CONSOLE_FIFO_DEPTH]; +std::string programs[16]; +Point console_text_location(5,30); +uint8_t n_programs = 3; +uint8_t selected_program = 0; +uint8_t last_selected_program = 1; +uint8_t console_addr_screen = 0; +uint8_t console_addr=0; + +#define WEIGHTS_ADDR 0x80000000 +#define BIAS_ADDR 0x80000010 +#define DATA_ADDR 0x80000014 +#define RESULTS_ADDR 0x90000000 + +uint8_t binary_weights[] = { + 0b00000111, 0b00010111, 0b11011011, 0b11100101, + 0b00000001, 0b00000010, 0b11111100, 0b11110000, + 0b11111100, 0b11111001, 0b00000010, 0b00001110, + 0b11111100, 0b11110100, 0b00000110, 0b00001001 + }; + +uint8_t test_vectors[]= { + 0b01010110,0b00110000,0b01001000,0b00011000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0b01100101,0b00110101,0b01001011,0b00011010, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0b01101011,0b00110010,0b01000110,0b00010110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0b01100010,0b00101101,0b01001011,0b00010011, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0b01101101,0b00100011,0b01100000,0b00011101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0b01011011,0b00101101,0b01001000,0b00010101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0b01100011,0b00101101,0b01001101,0b00011101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0b01111100,0b00111100,0b01010101,0b00101000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0b01100110,0b00110010,0b01011000,0b00011101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0b01101000,0b00110000,0b01011101,0b00100011, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0b01010000,0b00100101,0b00110101,0b00010000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0b01101011,0b00110010,0b01001011,0b00011000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0b01011010,0b00110000,0b01001000,0b00011000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0b01100011,0b00110110,0b01010110,0b00100101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0b01011101,0b00101011,0b00111110,0b00010011, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0b01011011,0b00101110,0b01000011,0b00010101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0b01101011,0b00110101,0b01011011,0b00100010, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0b01101000,0b00101110,0b01011010,0b00101011, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +uint8_t binary_bias[] = {0b00010110, 0b00001011, 0b11110111, 0b11111001}; + +uint8_t labels[] = { + 0b00010000, 0b00010000, 0b00010000, 0b00010000, 0b00110000, + 0b00010000, 0b00100000, 0b00110000, 0b00100000, + 0b00100000, 0b00010000, 0b00010000, 0b00010000, 0b00100000, + 0b00010000, 0b00010000, 0b00100000, 0b00110000}; + +uint8_t results[18]; +uint8_t current_result=0; +uint8_t current_drawn_result=0; + +typedef enum{ + HOME, + PROGRAM, + CONSOLE, + DEMO, + POWER +} screen_state; + +screen_state current_screen_state=HOME; +screen_state last_screen_state=POWER; + +// Global variables for Core 0 program flow +bool DEMO_RUN = false; +bool new_result = false; +bool program_nanosoc; +bool nanosoc_console = false; +bool nanosoc_console_draw = false; +i2c_inst_t *i2c = i2c1; + +static spi_t spis[] = {{ + .hw_inst = spi0, + .miso_gpio = 0, + .mosi_gpio = 19, + .sck_gpio = 18, + .baud_rate = 12500 * 1000 +}}; + + +// Hardware Configuration of the SD Card "objects" +static sd_card_t sd_cards[] = {{ + .pcName = "0:", + .spi = &spis[0], + .ss_gpio = 1, + .use_card_detect = false +}}; + + +void BUTTON_irq(uint gpio, uint32_t events) { + if(gpio==BUTTON_A){ + // if button A is pressed: increment through screen states + switch(current_screen_state) { + case HOME: + current_screen_state=CONSOLE; + break; + case CONSOLE: + current_screen_state=DEMO; + break; + case DEMO: + current_screen_state=POWER; + break; + case POWER: + current_screen_state=HOME; + break; + default: + current_screen_state = HOME; + } + + } + else if (gpio==BUTTON_B){ + // if button B is pressed: decrement through screen states + switch(current_screen_state) { + case HOME: + current_screen_state=POWER; + break; + case CONSOLE: + current_screen_state=HOME; + break; + case DEMO: + current_screen_state=CONSOLE; + break; + case POWER: + current_screen_state=DEMO; + break; + default: + current_screen_state = HOME; + } + } + else if (gpio == BUTTON_X){ + BUTTON_X_pressed = true; + } + else if (gpio == BUTTON_Y){ + BUTTON_Y_pressed = true; + } + +} + +void screen_refresh(){ + graphics.set_pen(BG); + graphics.clear(); + Rect blank(0,302,240,18); + graphics.set_pen(WHITE); + graphics.rectangle(blank); + graphics.set_pen(WHITE); + Rect blank1(0,0,240,18); + graphics.rectangle(blank1); +} + +void HOME_ROUTINE(){ + Point title_location(0, 2); + Point text_location(10,50); + if(current_screen_state!=last_screen_state){ + graphics.set_pen(WHITE); + Rect blank(0,0,240,18); + graphics.rectangle(blank); + graphics.set_pen(BG); + graphics.text(" <- HOME ->", title_location, 600); + graphics.set_pen(WHITE); + graphics.text("Welcome to nanoSoC!",text_location, 230); + text_location.y+=30; + graphics.text("nanoSoC is a re-usable SoC reference design. To use the testboard- press the A button to go one screen forward and B button to go back a screen", text_location, 225); + last_screen_state = HOME; + nanosoc_console = false; + } + if(BUTTON_X_pressed){ + BUTTON_X_pressed=false; + } + if(BUTTON_Y_pressed){ + BUTTON_Y_pressed=false; + } + +} +void CONSOLE_ROUTINE(){ + Point title_location(0, 2); + Point footer_location(10,304); + Rect console_BG(0,18,240,284); + uint32_t data; + nanosoc_console = true; + if(current_screen_state!=last_screen_state){ + console_text_location.x = 5; + console_text_location.y = 30; + graphics.set_pen(BG); + graphics.text(" <- CONSOLE ->", title_location, 600); + graphics.text(" Reset Clear ",footer_location,600); + last_screen_state = CONSOLE; + } + if(current_screen_state==last_screen_state){ + if(nanosoc_console_draw){ + if (console_text_location.y > 298){ + console_text_location.y = 30; + graphics.set_pen(BG); + graphics.rectangle(console_BG); + } + + graphics.set_pen(WHITE); + graphics.text(console[console_addr_screen], console_text_location, 1000); + console_text_location.y += 16; + + // update screen + //st7789.update(&graphics); + console[console_addr_screen].clear(); + console_addr_screen++; + if(console_addr_screen == CONSOLE_FIFO_DEPTH){ + console_addr_screen=0; + } + if(console[console_addr_screen].empty()){ + nanosoc_console_draw=false; + } + } + } + if(BUTTON_X_pressed){ + // Clear console and fifo + graphics.set_pen(BG); + graphics.rectangle(console_BG); + console_text_location.y=30; + for(int i = 0; i<CONSOLE_FIFO_DEPTH; i++){ + console[i].clear(); + } + console_addr = 0; + console_addr_screen=0; + BUTTON_X_pressed=false; + } + if(BUTTON_Y_pressed){ + nanosoc_reset(i2c); + BUTTON_Y_pressed=false; + } +} +void DEMO_ROUTINE(){ + Point title_location(0, 2); + Point footer_location(10,304); + int graph_x = 10; + int graph_y = 150; + int graph_w = 100; + int graph_h = 100; + if(current_screen_state!=last_screen_state){ + graphics.set_pen(BG); + graphics.text(" <- Hell Fire Demo ->", title_location, 600); + graphics.text(" Start ",footer_location,600); + last_screen_state = DEMO; + nanosoc_console = false; + } + if(current_screen_state==last_screen_state){ + if(DEMO_RUN){ + if(new_result){ + if(results[current_drawn_result]==1){ + graphics.set_pen(Setosa); + } else if(results[current_drawn_result]==2){ + graphics.set_pen(Versicolor); + } else if(results[current_drawn_result]==3){ + graphics.set_pen(Virginica); + } else { + printf("ERROR: Result out of bounds\n"); + } + + } + } else{ + graphics.set_pen(WHITE); + Rect y_axis(graph_x, graph_y-graph_h, 1, graph_h); + Rect x_axis(graph_x, graph_y, graph_w, 1); + graphics.rectangle(y_axis); + graphics.rectangle(x_axis); + } + } + if(BUTTON_X_pressed){ + DEMO_RUN=true; + BUTTON_X_pressed=false; + } + if(BUTTON_Y_pressed){ + BUTTON_Y_pressed=false; + } +} +void POWER_ROUTINE(){ + Point title_location(0, 2); + Point footer_location(10,304); + Point text_location(5,50); + Point power_stat_location(185,50); + Rect power_stat_bg(183,48,100,115); + float result; + char print_result[10]; + std::string print_buf; + if(current_screen_state!=last_screen_state){ + graphics.set_pen(BG); + graphics.text(" <- POWER ->", title_location, 600); + graphics.text(" ",footer_location,600); + graphics.set_pen(WHITE); + graphics.text("Core Voltage (V)= ",text_location,600); + text_location.y+=16; + graphics.text("Core Current (mA)= ",text_location,600); + text_location.y+=16; + graphics.text("Core Power (mW)= ",text_location,600); + text_location.y+=16; + text_location.y+=16; + graphics.text("Accel Voltage (V)= ",text_location,600); + text_location.y+=16; + graphics.text("Accel Current(mA)= ",text_location,600); + text_location.y+=16; + graphics.text("Accel Power (mW)= ",text_location,600); + last_screen_state = POWER; + nanosoc_console = false; + } + if(current_screen_state==last_screen_state){ + + power_stat_location.y=50; + + graphics.set_pen(BG); + graphics.rectangle(power_stat_bg); + graphics.set_pen(WHITE); + + result = nanosoc_read_bus_voltage(i2c, VDD_MONITOR); + sprintf(print_result, "%1.3f",result); + print_buf = print_result; + graphics.text(print_buf, power_stat_location, 600); + power_stat_location.y+=16; + + result = 1e3*nanosoc_read_current(i2c, VDD_MONITOR); + sprintf(print_result, "%1.3f",result); + print_buf = print_result; + graphics.text(print_buf, power_stat_location, 600); + power_stat_location.y+=16; + + result = 1e3*nanosoc_read_power(i2c, VDD_MONITOR); + sprintf(print_result, "%1.3f",result); + print_buf = print_result; + graphics.text(print_buf, power_stat_location, 600); + power_stat_location.y+=16; + power_stat_location.y+=16; + + result = nanosoc_read_bus_voltage(i2c, VDDACC_MONITOR); + sprintf(print_result, "%1.3f",result); + print_buf = print_result; + graphics.text(print_buf, power_stat_location, 600); + power_stat_location.y+=16; + + result = 1e3*nanosoc_read_current(i2c, VDDACC_MONITOR); + sprintf(print_result, "%1.3f",result); + print_buf = print_result; + graphics.text(print_buf, power_stat_location, 600); + power_stat_location.y+=16; + + result = 1e3*nanosoc_read_power(i2c, VDDACC_MONITOR); + sprintf(print_result, "%1.3f",result); + print_buf = print_result; + graphics.text(print_buf, power_stat_location, 600); + power_stat_location.y+=16; + } + if(BUTTON_X_pressed){ + BUTTON_X_pressed=false; + } + if(BUTTON_Y_pressed){ + BUTTON_Y_pressed=false; + } +} + +void core1_entry(){ + // Set GPIO for buttons + gpio_init(BUTTON_A); + gpio_set_dir(BUTTON_A, GPIO_IN); + gpio_pull_up(BUTTON_A); + gpio_init(BUTTON_B); + gpio_set_dir(BUTTON_B, GPIO_IN); + gpio_pull_up(BUTTON_B); + gpio_init(BUTTON_X); + gpio_set_dir(BUTTON_X, GPIO_IN); + gpio_pull_up(BUTTON_X); + gpio_init(BUTTON_Y); + gpio_set_dir(BUTTON_Y, GPIO_IN); + gpio_pull_up(BUTTON_Y); + + // Setup interrupts for GPIO + gpio_set_irq_enabled_with_callback(BUTTON_A, GPIO_IRQ_EDGE_RISE, true, &BUTTON_irq); + gpio_set_irq_enabled(BUTTON_B, GPIO_IRQ_EDGE_RISE, true); + gpio_set_irq_enabled(BUTTON_X, GPIO_IRQ_EDGE_RISE, true); + gpio_set_irq_enabled(BUTTON_Y, GPIO_IRQ_EDGE_RISE, true); + + // Set screen backlight (0-255) + st7789.set_backlight(200); + + + Point title_location(100, 0); + + graphics.set_pen(BG); + graphics.clear(); + graphics.set_pen(WHITE); + graphics.set_font(&font8); + while(1){ + if(current_screen_state!=last_screen_state){ + screen_refresh(); + } + switch(current_screen_state) { + case HOME: + HOME_ROUTINE(); + break; + case CONSOLE: + CONSOLE_ROUTINE(); + break; + case DEMO: + DEMO_ROUTINE(); + break; + case POWER: + POWER_ROUTINE(); + break; + default: + current_screen_state = HOME; + } + st7789.update(&graphics); + } +} + + + + +int main() { + // Set GPIO for Data handshaking + gpio_init(26); + gpio_set_dir(26, GPIO_IN); + gpio_pull_up(26); + gpio_init(27); + gpio_set_dir(27, GPIO_OUT); + gpio_put(27,0); + + program_nanosoc = false; + stdio_init_all(); + while(!stdio_usb_connected()){;} + sleep_ms(500); + + // Setup nanosoc + nanosoc_i2c_init(i2c); + + PIO pio = pio0; + uint offset = pio_add_program(pio, &ft1248x1_sm_program); + uint sm = pio_claim_unused_sm(pio, true); + + ft1248x1_sm_program_init(pio, sm, offset); + pio_sm_clear_fifos(pio, sm); + pio_sm_restart(pio, sm); + sleep_ms(500); + + char buf[128]; + int len; + + + + // Mount SD card + sd_card_t *pSD = &sd_cards[0]; + FRESULT fr = f_mount(&pSD->fatfs, pSD->pcName, 1); + if (FR_OK != fr) { + printf("f_mount error: %s (%d)\n", FRESULT_str(fr), fr); + } + else{ + printf("SD Card mounted\n"); + } + + // Read contents of ./programs from SD card + DIR dir; + static FILINFO fno; + uint i; + FRESULT res = f_opendir(&dir, "./programs"); + if (res == FR_OK) { + for (;;) { + res = f_readdir(&dir, &fno); /* Read a directory item */ + if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */ + else { /* It is a file. */ + printf("./programs/%s\n", fno.fname); + programs[i] = fno.fname; + i++; + } + } + f_closedir(&dir); + } + n_programs=i; + + // Main demo Start + FIL fil; + // Download program to nanosoc + f_chdir("./programs"); + fr = f_open(&fil, "hell_fire_demo.hex", FA_READ); + if (FR_OK != fr && FR_EXIST != fr){ + printf("f_open(hell_fire_demo.hex) error: %s (%d)\n", FRESULT_str(fr), fr); + printf("Can't open demo program. Is SD Card inserted?\n"); + return 1; + } + nanosoc_download_program(pio, sm, fil); + fr = f_close(&fil); + if (FR_OK != fr) { + printf("f_close error: %s (%d)\n", FRESULT_str(fr), fr); + } + f_chdir("/"); + + nanosoc_download_buffer(pio,sm,&binary_weights[0], WEIGHTS_ADDR, 16); + nanosoc_download_buffer(pio,sm,&binary_bias[0], BIAS_ADDR, 4); + nanosoc_download_buffer(pio,sm,&test_vectors[0], DATA_ADDR, 288); + + // Launch Core 1 to handle graphics + multicore_launch_core1(core1_entry); + nanosoc_reset(i2c); + + // Main loop for Core 0 + while(1){ + if(gpio_get(26) && DEMO_RUN){ + // Get result from register + results[current_result]=nanosoc_read_reg32(pio,sm,RESULTS_ADDR+4*current_result); + // Handshake with nanosoc + gpio_put(27,1); + while(gpio_get(26)){ + if(!pio_sm_is_rx_fifo_empty(pio,sm)){ + len = pio_ft1248_readline(pio, sm, buf); + //printf("%c", buf); + } + } + gpio_put(27,0); + + new_result=true; + current_result++; + if(current_result>=18){ + current_result=0; + DEMO_RUN=false; + } + + } + + // Always read in and store STDIO from nanosoc + while(!pio_sm_is_rx_fifo_empty(pio,sm)){ + len = pio_ft1248_readline(pio, sm, buf); + + for (int i =0; i <len; i++){ + console[console_addr] += buf[i]; + } + console_addr++; + if(console_addr == CONSOLE_FIFO_DEPTH){ + console_addr = 0; + } + nanosoc_console_draw = true; + if(nanosoc_console!=true){ + break; + } + } + + } + return 0; +} + + diff --git a/nanosoc_board/C_Cxx/system/nanosoc_board_system/nanosoc_board_system.c b/nanosoc_board/C_Cxx/system/nanosoc_board_system/nanosoc_board_system.c index febb8124e671b4efbbc48129d454dd53b6b24cd0..ba98fa8261a55f009f993525094f325894d5b01f 100644 --- a/nanosoc_board/C_Cxx/system/nanosoc_board_system/nanosoc_board_system.c +++ b/nanosoc_board/C_Cxx/system/nanosoc_board_system/nanosoc_board_system.c @@ -309,7 +309,7 @@ void nanosoc_download_program(PIO pio, uint sm, FIL fil){ nanosoc_download_file(pio, sm, fil, 0x20000000); } -int nanosoc_download_buffer(PIO pio, uint sm, int* data, uint32_t base_addr, uint32_t length){ +int nanosoc_download_buffer(PIO pio, uint sm, uint8_t* data, uint32_t base_addr, uint32_t length){ char buf[32]; int len; diff --git a/nanosoc_board/C_Cxx/system/nanosoc_board_system/nanosoc_board_system.h b/nanosoc_board/C_Cxx/system/nanosoc_board_system/nanosoc_board_system.h index ed170bc7fd0ea8e01673c49404944ef5b70bcfc0..36f855566bfcde2349fcdb974ee3608a2de95136 100644 --- a/nanosoc_board/C_Cxx/system/nanosoc_board_system/nanosoc_board_system.h +++ b/nanosoc_board/C_Cxx/system/nanosoc_board_system/nanosoc_board_system.h @@ -28,7 +28,7 @@ int nanosoc_download_file_batch(PIO pio, uint sm, FIL fil, uint32_t base_addr); // nanosoc_download_program: calls nanosoc_download_file with the base address of the instruction memory region void nanosoc_download_program(PIO pio, uint sm, FIL fil); // nanosoc_download_buffer: Download a file to nanosoc from an integer array (data) of a specified length -int nanosoc_download_buffer(PIO pio, uint sm, int* data, uint32_t base_addr, uint32_t length); +int nanosoc_download_buffer(PIO pio, uint sm, uint8_t* data, uint32_t base_addr, uint32_t length); // nansoc_read_reg32: read a 32 bit register from nanosoc using the ADP interface int nanosoc_read_reg32(PIO pio, uint sm, uint32_t addr); \ No newline at end of file diff --git a/nanosoc_board/C_Cxx/system/nanosoc_graphics/nanosoc_graphics.cpp b/nanosoc_board/C_Cxx/system/nanosoc_graphics/nanosoc_graphics.cpp index de6c14ed3cd2d99cfbc00d2d38114d60963326b9..a354b2714094b467589884a4b686d48ae1cfd27f 100644 --- a/nanosoc_board/C_Cxx/system/nanosoc_graphics/nanosoc_graphics.cpp +++ b/nanosoc_board/C_Cxx/system/nanosoc_graphics/nanosoc_graphics.cpp @@ -1,7 +1,7 @@ #include "nanosoc_graphics.hpp" -int screen_draw_vector(pimoroni::PicoGraphics_PenRGB332 graphics, pimoroni::ST7789 st7789, int* data, int x, int y, int width, int height, int scale){ +int screen_draw_vector(pimoroni::PicoGraphics_PenRGB332 graphics, pimoroni::ST7789 st7789, uint8_t* data, int x, int y, int width, int height, int scale){ pimoroni::Rect bmap_point(x,y,scale,scale); for (int i = 0; i<(width*height); i++){ diff --git a/nanosoc_board/C_Cxx/system/nanosoc_graphics/nanosoc_graphics.hpp b/nanosoc_board/C_Cxx/system/nanosoc_graphics/nanosoc_graphics.hpp index 298193104684ff6f07862250ebee8da664f3a6ea..34fdce6fdc84d6aa25e1536c5fb06be62bb7a54f 100644 --- a/nanosoc_board/C_Cxx/system/nanosoc_graphics/nanosoc_graphics.hpp +++ b/nanosoc_board/C_Cxx/system/nanosoc_graphics/nanosoc_graphics.hpp @@ -2,4 +2,4 @@ #include "drivers/st7789/st7789.hpp" #include "libraries/pico_graphics/pico_graphics.hpp" -int screen_draw_vector(pimoroni::PicoGraphics_PenRGB332 graphics, pimoroni::ST7789 st7789, int* data, int x, int y, int width, int height, int scale); \ No newline at end of file +int screen_draw_vector(pimoroni::PicoGraphics_PenRGB332 graphics, pimoroni::ST7789 st7789, uint8_t* data, int x, int y, int width, int height, int scale); \ No newline at end of file