#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/printk.h>
#include "nrfx_pdm.h"
#include <nrfx_clock.h>
#include <math.h>

LOG_MODULE_REGISTER(pdm_mic, LOG_LEVEL_INF);

#define PDM_BUF_SIZE_SAMPLES 1024
#define PDM_BUF_COUNT 2
nrfx_pdm_t const *p_instance;

static int16_t pdm_buf[PDM_BUF_COUNT][PDM_BUF_SIZE_SAMPLES];
static volatile bool data_ready = false;

static void pdm_event_handler(nrfx_pdm_evt_t const *p_evt)
{
        if (p_evt->error != NRFX_PDM_NO_ERROR)
        {
                LOG_ERR("PDM error occurred: %d", p_evt->error);
                return;
        }

        if (p_evt->buffer_released != NULL)
        {
                data_ready = true;
        }

        if (p_evt->buffer_requested)
        {
                // You must provide the next buffer to continue receiving
                static int active_buf = 0;
                nrfx_err_t err = nrfx_pdm_buffer_set(p_instance, pdm_buf[active_buf], PDM_BUF_SIZE_SAMPLES);
                if (err != NRFX_SUCCESS)
                {
                        LOG_ERR("Failed to set buffer: %d", err);
                }
                active_buf = (active_buf + 1) % PDM_BUF_COUNT;
        }
}

static void process_audio_data(int16_t *buffer, size_t samples)
{
        uint64_t sum = 0;
        for (size_t i = 0; i < samples; i++)
        {
                int32_t sample = buffer[i];
                sum += sample * sample;
        }
        uint32_t rms = (uint32_t)sqrt((double)sum / samples);
        printk("Audio RMS: %u\n", rms);
}

int main(void)
{
        LOG_INF("Starting PDM Microphone Example");

        nrfx_clock_hfclk_start();
        while (!nrfx_clock_hfclk_is_running())
        {
                k_sleep(K_MSEC(1));
        }

        nrfx_pdm_config_t config = NRFX_PDM_DEFAULT_CONFIG(25, 26); // CLK=25, DIN=26
        config.gain_l = NRF_PDM_GAIN_DEFAULT;
        config.gain_r = NRF_PDM_GAIN_DEFAULT;
        config.mode = NRF_PDM_MODE_MONO;
        config.clock_freq = NRF_PDM_FREQ_1000K;

        if (nrfx_pdm_init(p_instance, &config, pdm_event_handler) != NRFX_SUCCESS)
        {
                LOG_ERR("PDM init failed");
                return -1;
        }

        LOG_INF("PDM initialized");

        if (nrfx_pdm_start(p_instance) != NRFX_SUCCESS)
        {
                LOG_ERR("PDM start failed");
                return -1;
        }

        LOG_INF("PDM started");

        int active_buf = 0;

        while (1)
        {
                nrfx_err_t err = nrfx_pdm_buffer_set(p_instance, pdm_buf[active_buf], PDM_BUF_SIZE_SAMPLES);
                if (err != NRFX_SUCCESS)
                {
                        LOG_ERR("Failed to set buffer");
                        k_sleep(K_MSEC(10));
                        continue;
                }

                while (!data_ready)
                {
                        k_sleep(K_MSEC(1));
                }
                data_ready = false;

                process_audio_data(pdm_buf[active_buf], PDM_BUF_SIZE_SAMPLES);
                active_buf = (active_buf + 1) % PDM_BUF_COUNT;
        }
        return 0;
}
// #include <zephyr/kernel.h>
// #include <zephyr/logging/log.h>
// #include <nrfx_pdm.h>
// #include <nrfx_clock.h>
// #include <zephyr/irq.h>
// #include <stdio.h>

// LOG_MODULE_REGISTER(pdm_test, LOG_LEVEL_INF);

// #define PDM_BUF_SIZE 1024

// static int16_t pdm_buf[PDM_BUF_SIZE];
// static volatile bool data_ready = false;

// void nrfx_pdm_event_handler(nrfx_pdm_evt_t const * const p_evt)
// {
//     if (p_evt->buffer_requested) {
//         nrfx_pdm_buffer_set(pdm_buf, PDM_BUF_SIZE);
//     }

//     if (p_evt->buffer_released != NULL) {
//         data_ready = true;
//     }
// }

// static void pdm_init(void)
// {
//     nrfx_pdm_config_t config = NRFX_PDM_DEFAULT_CONFIG(20, 21); // CLK, DIN

//     config.clock_freq = NRF_PDM_FREQ_1032K;
//     config.mode = NRF_PDM_MODE_MONO;
//     config.edge = NRF_PDM_EDGE_LEFTFALLING;

//     config.gain_l = NRF_PDM_GAIN_DEFAULT;
//     config.gain_r = NRF_PDM_GAIN_DEFAULT;

//     if (nrfx_pdm_init(&config, nrfx_pdm_event_handler) != NRFX_SUCCESS) {
//         LOG_ERR("PDM init failed");
//         return;
//     }

//     LOG_INF("PDM Initialized");
// }

// ISR_DIRECT_DECLARE(pdm_isr_handler)
// {
//     nrfx_pdm_irq_handler();
//     ISR_DIRECT_PM();
//     return 1;
// }

// void main(void)
// {
//     LOG_INF("Starting PDM example");

//     IRQ_DIRECT_CONNECT(PDM_IRQn, 0, pdm_isr_handler, 0);

//     nrfx_clock_hfclk_start();
//     while (!nrfx_clock_hfclk_is_running()) {
//         k_sleep(K_MSEC(1));
//     }

//     LOG_INF("HFCLK started");

//     pdm_init();

//     nrfx_err_t err = nrfx_pdm_start();
//     if (err != NRFX_SUCCESS) {
//         LOG_ERR("PDM start failed: %d", err);
//         return;
//     }

//     LOG_INF("PDM started");

//     while (1) {
//         if (data_ready) {
//             data_ready = false;

//             // Process audio sample
//             uint32_t avg = 0;
//             for (int i = 0; i < PDM_BUF_SIZE; i++) {
//                 avg += abs(pdm_buf[i]);
//             }
//             avg /= PDM_BUF_SIZE;
//             printk("Avg sample: %lu\n", avg);
//         }

//         k_sleep(K_MSEC(10));
//     }
// }
