summaryrefslogblamecommitdiffstats
path: root/src/modchipfw/utglitcher.c
blob: 5ba5c94cc7585c6ef3a7e9b090c2035e3c341b97 (plain) (tree)





























































































































































                                                                                                                   
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/uart.h"
#include "hardware/gpio.h"
#include "hardware/pio.h"
#include "hardware/clocks.h"
#include "hardware/vreg.h"
#include "pulsegen.pio.h"

#define PIN_NRST   7
#define PIN_TRIG   6
#define PIN_PULSE  0
#define PIN_CAPS   1

#define PIN_LED1   16
#define PIN_LED2   17

int main()
{
    /* 
     * For some reason the serial communication fails after some time when running at 200MHz
     * For me everything worked fine at 250 MHz without changing the core voltage (vreg_set_voltage)
    */
    set_sys_clock_khz(250000, true);
    
    stdio_init_all();

    // GPIO initialisation.
    gpio_init(PIN_NRST);
    gpio_init(PIN_TRIG);
    gpio_init(PIN_PULSE);
    gpio_init(PIN_CAPS);
    gpio_init(PIN_LED1);
    gpio_init(PIN_LED2);
    gpio_set_dir(PIN_NRST, GPIO_OUT);
    gpio_set_dir(PIN_TRIG, GPIO_IN);
    gpio_set_dir(PIN_PULSE, GPIO_OUT);
    gpio_set_dir(PIN_CAPS, GPIO_OUT);
    gpio_set_dir(PIN_LED1, GPIO_OUT);
    gpio_set_dir(PIN_LED2, GPIO_OUT);
    gpio_set_pulls(PIN_CAPS, true, false);
    gpio_set_drive_strength(PIN_PULSE, GPIO_DRIVE_STRENGTH_12MA);
    gpio_set_drive_strength(PIN_CAPS, GPIO_DRIVE_STRENGTH_12MA);
    gpio_set_slew_rate(PIN_PULSE, GPIO_SLEW_RATE_FAST);

    // Setup PIO
    PIO pio = pio0;
    uint32_t sm = pio_claim_unused_sm(pio, true);
    uint32_t pio_offset = pio_add_program(pio, &pulsegen_program);
    pulsegen_program_init(pio, sm, pio_offset, PIN_TRIG, PIN_PULSE, PIN_CAPS);

    // Wait for serial connection
    while (!stdio_usb_connected()) {
      sleep_ms(500);
    }

    gpio_put(PIN_LED1, true);
    gpio_put(PIN_NRST, false);

    char cmd;
    uint32_t pulse_offset = 0;
    uint32_t pulse_width = 0;
    uint32_t trig_edges = 1;
    uint32_t gpio_states = 0;

    uint8_t gpio_pin = 0;
    uint8_t gpio_state = 0;

    while (true) {
        cmd = getchar();
        
        switch (cmd)
        {
            // Enable glitch SM
            case 'A':
                gpio_put(PIN_LED2, true);
                pio_sm_put_blocking(pio, sm, trig_edges);
                pio_sm_put_blocking(pio, sm, pulse_offset);
                pio_sm_put_blocking(pio, sm, pulse_width);

                gpio_put(PIN_NRST, true);
                sleep_ms(46); // Delay to make sure all UT signals are stable

                pio_sm_set_enabled(pio, sm, true);
                printf("A\n");
                break;

            // Wait for trigger
            case 'B':
                while(!pio_interrupt_get(pio0, 0)) {
                    cmd = getchar_timeout_us(1);
                    if (cmd == 'D') break; // Disarm
                };

                pio_sm_set_enabled(pio, sm, false);
                pio_interrupt_clear(pio, 0);
                pio_sm_clear_fifos(pio, sm);
                pio_sm_drain_tx_fifo(pio, sm);
                pio_sm_restart(pio, sm);
                pio_sm_set_enabled(pio, sm, false);
                
                pio_sm_exec_wait_blocking(pio, sm, pio_encode_set(pio_x, pio_offset));
                pio_sm_exec_wait_blocking(pio, sm, pio_encode_mov(pio_pc, pio_x));
                printf("T\n");
                gpio_put(PIN_LED2, false);
                break;
            
            // Set the number of edges before inserting a pulse
            case 'E':
                fread(&trig_edges, 1, 4, stdin);
                printf("%d\n", trig_edges);
                break;

            // Set the pulse offset
            case 'O':
                fread(&pulse_offset, 1, 4, stdin);
                printf("%d\n", pulse_offset);
                break;
            
            // Set the pulse width
            case 'W':
                fread(&pulse_width, 1, 4, stdin);
                printf("%d\n", pulse_width);
                break;

            // print the current pulse offset and width
            case 'S':
                printf("PulseGenerator offset: %d, width: %d, edges: %d\n", pulse_offset, pulse_width, trig_edges);
                break;

            // control a gpio pin, can be expanded to handle multiple pins
            case 'G':
                fread(&gpio_pin, 1, 1, stdin);
                fread(&gpio_state, 1, 1, stdin);

                if (gpio_pin == PIN_NRST) {
                    if (gpio_state == 0) {
                        gpio_put(PIN_NRST, false);
                    } else {
                        gpio_put(PIN_NRST, true);
                    }    
                }
                printf("G\n");
                break;

            // Read state of GPIOs
            case 'R':
                gpio_states = gpio_get_all();
                printf("%d\n", gpio_states);
                break;

            default:
                break;
        }
    }

    return 0;
}