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