/*
 * Copyright 2023 Google LLC
 *
 * 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.
 */

#include "soundstream.h"

#include <fail-simulator-on-error.h>
#include <thread.h>

#include <debug.hh>

#include "hw/top_matcha/sw/autogen/top_matcha.h"

/// Expose debugging features unconditionally for this compartment.
using Debug = ConditionalDebug<true, "SOUNDSTREAM">;

#define ABS(x) (x > 0 ? x : -x)

//#define kSamples (5 * 16000)
#define kSamples (2000) // NB: reduced sample count for slow renode
#define kFilterSamples (256)

void __cheri_compartment("soundstream") entry(void) {
  Debug::log("soundstream (Thread {})", thread_id_get());

  i2s_init();
  ml_top_init();
  mailbox_init();

  i2s_rxfifo_clear();
  i2s_irq_acknowledge_all();
  i2s_irq_set_enabled(kI2sIrqRxWatermark, /*enabled=*/true);

  // NB: the stack is 4KiB so this uses 1/4 of it
  int16_t samples_left[kFilterSamples] = {0};
  int16_t samples_right[kFilterSamples] = {0};
  size_t index_left = 0;
  size_t index_right = 0;
  int32_t total_left = 0;
  int32_t total_right = 0;

  static int32_t samples[kSamples];
  memset(samples, 0xa5, sizeof(int32_t) * kSamples);

  Debug::log("Setup complete");

  while (true) {
    // TODO(sleffler): need custom security core code running and
    //   a way to toggle the gpio associated with the button; for now
    //   just force it to appear as though the button has been pressed.
    mailbox_set_button_pressed(true);

    // Wait until the record switch is pushed
    Debug::log("Wait for button press...");
    mailbox_wait_for_button_pressed();

    mailbox_set_led(/*enabled=*/true);
    Debug::log("Start recording (max {} samples)...", kSamples);
    i2s_record_begin();

    // Record until our buffer is full or the switch is released.
    int sample = 0;
    while (sample < kSamples && mailbox_button_pressed()) {
      i2s_irq_set_enabled(kI2sIrqRxWatermark, /*enabled=*/true);

      i2s_wait_for_rx_watermark();

      while (!i2s_rxfifo_is_empty()) {
        uint32_t reg_val = i2s_get_rdata();
        // For each sample, split into left and right channel values,
        // and update the moving average.
        int16_t left = reg_val >> 16;
        int16_t right = reg_val & 0xFFFF;
        total_left -= samples_left[index_left];
        total_right -= samples_right[index_right];
        total_left += left;
        samples_left[index_left] = left;
        total_right += right;
        samples_right[index_right] = right;
        index_left = (index_left + 1) % kFilterSamples;
        index_right = (index_right + 1) % kFilterSamples;
        int16_t mean_left = total_left / kFilterSamples;
        int16_t mean_right = total_right / kFilterSamples;

        // Subtract the moving average from each channel, and repack into the
        // sample buffer.
        uint32_t offset_reg_val = (((left - mean_left) & 0xFFFF) << 16) |
                                  ((right - mean_right) & 0xFFFF);
        samples[sample++] = offset_reg_val;
        if (sample == kSamples || !mailbox_button_pressed()) {
          break;
        }
      }
    }

    i2s_record_end();
    mailbox_set_led(/*enabled=*/false);

    Debug::log("Done recording {} samples", sample);
    int samples_captured = sample;

    // Calculate the min/max of the audio, after correcting DC offsets
    int32_t max = INT16_MIN;
    int32_t min = INT16_MAX;
    for (int i = 1; i < (samples_captured * 2); i += 2) {
      int16_t* samples_s16 = (int16_t*)samples;
      int32_t sample = samples_s16[i];
      if (sample < min) {
        min = sample;
      }
      if (sample > max) {
        max = sample;
      }
    }

    // Calculate a scaling factor, and use this to scale the waveform
    // to a peak of 75% amplitude.
    int32_t scale_max = ((int32_t)max * 100) / ((int32_t)INT16_MAX);
    int32_t scale_min = ABS(((int32_t)min * 100) / ((int32_t)INT16_MIN));
    int32_t scale = scale_max > scale_min ? scale_max : scale_min;
    for (int i = 1; i < (samples_captured * 2); i += 2) {
      int16_t* samples_s16 = (int16_t*)samples;
      int16_t sample = samples_s16[i];
      int16_t scaled_sample = (int16_t)(((int32_t)sample * 100) / scale);
      scaled_sample = (((int32_t)scaled_sample * 75) / 100);
      samples_s16[i] = scaled_sample;
    }

    Debug::log("Processing recorded audio...");

    // 320 x int16
    int iterations_to_process = samples_captured / 320;
    int16_t process_buffer[320];
    int16_t result_buffer[64];
    char result_buffer_encoded[ENCODE_OUT_SIZE(sizeof(result_buffer))];

    struct output_header header;
    memset(&header, 0, sizeof(header));  // NB: resume_pc = 0

    for (int i = 0; i < iterations_to_process; ++i) {
      Debug::log("Iteration {}", i);
      int16_t* samples_s16 = (int16_t*)samples;
      // Extract left channel audio
      for (int j = 0; j < 320; ++j) {
        process_buffer[j] = samples_s16[(i * 320 * 2) + (j * 2) + 1];
      }
      ml_top_set_input(process_buffer, sizeof(process_buffer));

      // Start/resume kelvin
      (void) ml_top_finish_done();  // NB: reset state
      ml_top_resume_ctrl_en(header.resume_pc);

      ml_top_wait_for_finish();

      ml_top_get_output_header(&header);
      Debug::Assert(header.length == sizeof(result_buffer), "Unexpected ML result size");
      ml_top_get_output_data(&header, result_buffer);

      encode((const unsigned char*)result_buffer, sizeof(result_buffer),
             result_buffer_encoded);
      Debug::log("[sound]::ENCODER:{}",
        std::string_view(result_buffer_encoded, sizeof(result_buffer_encoded)));
    }

    Debug::log("[sound]::ENCODER: done");
    Debug::log("Done with processing.");
  }
  panic();
}
