Only 2 buttons are actually connected, but they work well.

The duo comes without the connectors, so I had to solder some into it. It was a fun experience!

For the people who don’t know the duo, it is a very little board (something like an alternative to the RPi Pico) that runs a RISC-V chip! I bought mine from Aliexpress in a pack with other stuff for like 10€.

Here is the underside of the gamepad thingy:

A picture showing the underside of the gamepad. It has wires soldered into it.

Not the best soldering job but it’s to be expected since I don’t have experience.

I also made a little program in C to test the buttons:

A picture showing a terminal window with " 'A' button has been pressed! " written several times on it.

Every time I press a specific button the program prints a string to the screen. When pressing the other wired button the program ends.


Here is the source code in case anyone is curious
#include 
#include 
#include 

#include 
#include 



/// It's t1 - t2, in seconds
double get_time_diff(struct timespec t1, struct timespec t2) {
    double a = (double)t1.tv_sec + (t1.tv_nsec / 1000000000.0);
    double b = (double)t2.tv_sec + (t2.tv_nsec / 1000000000.0);

    return a-b;
}

int main() {
    
    const int DEFAULT_COUNTER = 1;
    const double FRAME_TIME = 1.0 / 60.0;

    int BUTTON_A = 7;
    int BUTTON_B = 8;


    int A_high = 0;

    int A_pressed = 0;
    int A_just_pressed = 0;

    int A_counter = 0;


    int B_high = 0;

    int B_pressed = 0;
    int B_just_pressed = 0;

    int B_counter = 0;


    if(wiringXSetup("duo", NULL) == -1) {
        wiringXGC();
        return -1;
    }

    if(wiringXValidGPIO(BUTTON_A) != 0) {
        printf("Invalid GPIO %d\n", BUTTON_A);
    }
    if(wiringXValidGPIO(BUTTON_B) != 0) {
        printf("Invalid GPIO %d\n", BUTTON_B);
    }

    pinMode(BUTTON_A, PINMODE_INPUT);
    pinMode(BUTTON_B, PINMODE_INPUT);



    time_t init_time;
    time(&init_time);

    printf("Init time: %s\n", ctime(&init_time));

    struct timespec tick_start_time;
    timespec_get(&tick_start_time, TIME_UTC);
    struct timespec tick_end_time;
    timespec_get(&tick_end_time, TIME_UTC);


    // Start ncurses
    initscr();


    while(1) {
        
        timespec_get(&tick_start_time, TIME_UTC);

        if (get_time_diff(tick_start_time, tick_end_time) >= FRAME_TIME ) {
            
            // INPUT
            if (digitalRead(BUTTON_A) == HIGH) {

                if (A_high == 0) {
                    A_counter = DEFAULT_COUNTER;
                } else if (A_counter > 0) {
                    A_counter--;
                }
                
                A_high = 1;

                if (A_just_pressed == 1) {
                    A_just_pressed = 0;
                }

                if (A_counter <= 0) {

                    if (A_pressed == 0) {
                        A_just_pressed = 1;
                    }

                    A_pressed = 1;

                }
                
            } else {

                if (A_high == 1) {
                    A_counter = DEFAULT_COUNTER;
                } else if (A_counter > 0) {
                    A_counter--;
                }

                A_high = 0;

                if (A_counter <= 0) {
                    A_just_pressed = 0;
                    A_pressed = 0;
                }

            }

            if (digitalRead(BUTTON_B) == HIGH) {

                if (B_high == 0) {
                    B_counter = DEFAULT_COUNTER;
                } else if (B_counter > 0) {
                    B_counter--;
                }
                
                B_high = 1;

                if (B_just_pressed == 1) {
                    B_just_pressed = 0;
                }

                if (B_counter <= 0) {

                    if (B_pressed == 0) {
                        B_just_pressed = 1;
                    }

                    B_pressed = 1;

                }
                
            } else {

                if (B_high == 1) {
                    B_counter = DEFAULT_COUNTER;
                } else if (B_counter > 0) {
                    B_counter--;
                }

                B_high = 0;

                if (B_counter <= 0) {
                    B_just_pressed = 0;
                    B_pressed = 0;
                }

            }

            
            // UPDATE
            if (A_just_pressed == 1) {
                printw("'A' has just been pressed!\n");
            }
            if (B_just_pressed == 1) {
                // Exit the loop, which will end the program
                break;
            }

            refresh();
            timespec_get(&tick_end_time, TIME_UTC);
        }

    }

    // Stop ncurses
    endwin();

    return 0;
}


I hope someone finds this interesting! Thanks for reading.