// Copyright 2022 The Pigweed Authors
//
// 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
//
//     https://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 "pw_spi_pico/initiator.h"

#include <algorithm>

#include "hardware/spi.h"
#include "pico/stdlib.h"
#include "pw_assert/check.h"
#include "pw_log/log.h"
#include "pw_status/try.h"

namespace pw::spi {

namespace {

constexpr spi_order_t GetBitOrder(BitOrder bit_order) {
  switch (bit_order) {
    case BitOrder::kLsbFirst:
      return SPI_LSB_FIRST;
    case BitOrder::kMsbFirst:
      return SPI_MSB_FIRST;
  }
  PW_CRASH("Unknown bit order");
  return SPI_LSB_FIRST;
}

constexpr spi_cpha_t GetPhase(ClockPhase phase) {
  switch (phase) {
    case ClockPhase::kFallingEdge:
      return SPI_CPHA_1;
    case ClockPhase::kRisingEdge:
      return SPI_CPHA_0;
  }
  PW_CRASH("Unknown phase");
  return SPI_CPHA_0;
}

constexpr spi_cpol_t GetPolarity(ClockPolarity polarity) {
  switch (polarity) {
    case ClockPolarity::kActiveHigh:
      return SPI_CPOL_1;
    case ClockPolarity::kActiveLow:
      return SPI_CPOL_0;
  }
  PW_CRASH("Unknown polarity");
  return SPI_CPOL_0;
}

}  // namespace

PicoInitiator::PicoInitiator(spi_inst_t* spi, uint32_t baud_rate)
    : spi_(spi),
      baud_rate_(baud_rate),
      config_{
          .polarity = ClockPolarity::kActiveHigh,
          .phase = ClockPhase::kRisingEdge,
          .bits_per_word = BitsPerWord(8),
          .bit_order = BitOrder::kMsbFirst,
      },
      desired_bits_per_word_(8) {}

void PicoInitiator::SetOverrideBitsPerWord(BitsPerWord bits_per_word) {
  // TODO(b/251033990): Remove once changing SPI device config is added.
  desired_bits_per_word_ = bits_per_word;
  override_bits_per_word_ = true;
}

Status PicoInitiator::LazyInit() {
  // Already initialized - nothing to do.
  // The Pico SDK needs to call spi_init() earlier so that the
  // various GPIO pins (MISO, etc.) can be assigned to the SPI
  // bus.
  return OkStatus();
}

Status PicoInitiator::Configure(const Config& config) {
  config_ = config;
  // TODO(b/251033990): Remove once changing SPI device config is added.
  if (override_bits_per_word_) {
    config_.bits_per_word = desired_bits_per_word_;
  }
  spi_set_format(spi_,
                 config_.bits_per_word(),
                 GetPolarity(config_.polarity),
                 GetPhase(config_.phase),
                 GetBitOrder(config_.bit_order));

  return OkStatus();
}

Status PicoInitiator::WriteRead(ConstByteSpan write_buffer,
                                ByteSpan read_buffer) {
  PW_TRY(LazyInit());

  if (!write_buffer.empty()) {
    if (!read_buffer.empty()) {
      PW_CRASH("Not implemented");
    } else {
      if (config_.bits_per_word() == 16) {
        spi_write16_blocking(
            spi_,
            reinterpret_cast<const uint16_t*>(write_buffer.data()),
            write_buffer.size());
      } else {
        spi_write_blocking(
            spi_,
            reinterpret_cast<const uint8_t*>(write_buffer.data()),
            write_buffer.size());
      }
    }
  } else {
    spi_read_blocking(spi_,
                      /*repeated_tx_data=*/0,
                      reinterpret_cast<uint8_t*>(read_buffer.data()),
                      read_buffer.size());
  }

  return OkStatus();
}

}  // namespace pw::spi
