#include <ch32fun.h>
#include <rand.h>
#include <rsa.h>
#include <stdint.h>
#include <stdio.h>

#define LED_PIN PD6

void exit_blink() {
    for (int i = 0; i < 4; i++) {
        funDigitalWrite(LED_PIN, FUN_HIGH);
        Delay_Ms(50);
        funDigitalWrite(LED_PIN, FUN_LOW);
        Delay_Ms(50);
    }
}

void enter_blink() {
    for (int i = 0; i < 2; i++) {
        funDigitalWrite(LED_PIN, FUN_HIGH);
        Delay_Ms(200);
        funDigitalWrite(LED_PIN, FUN_LOW);
        Delay_Ms(200);
    }
}

int main() {
    SystemInit();

    printf("Entering...\n");

    funGpioInitAll();
    funPinMode(LED_PIN, GPIO_Speed_10MHz | GPIO_CNF_OUT_PP);

    enter_blink();

    uint64_t p = gen_prime(1 << 15, 1 << 16);
    uint64_t q = gen_prime(1 << 15, 1 << 16);

    while (p == q) p = gen_prime(1 << 15, 1 << 16);

    uint64_t n = p * q;

    int before = SysTick->CNT;
    bool check_a = miller_rabin(p, 10);
    int miller = SysTick->CNT - before;

    before = SysTick->CNT;
    bool check_b = is_prime(p);
    int isprime = SysTick->CNT - before;

    printf("Is prime: %s %s\n", check_a ? "true" : "false",
           check_b ? "true" : "false");

    printf("Miller took %d ticks\n", miller);
    printf("Is_prime took %d ticks\n", isprime);

    // Make these work by patching printf
    printf("P: %u\n", (uint32_t)p);
    printf("Q: %u\n", (uint32_t)q);
    printf("N: %u\n", (uint32_t)n);

    for (int idx = 0; idx < 16; idx++) {
        funDigitalWrite(LED_PIN, p >> idx & 1);
        Delay_Ms(200);
    }
    for (int idx = 0; idx < 16; idx++) {
        funDigitalWrite(LED_PIN, q >> idx & 1);
        Delay_Ms(200);
    }
    for (int idx = 0; idx < 16; idx++) {
        funDigitalWrite(LED_PIN, n >> idx & 1);
        Delay_Ms(200);
    }

    // Exit and hang forever
    exit_blink();
    while (1);
}