// 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_display_driver_ili9341/display_driver.h"

#include <algorithm>

#include "pw_digital_io/digital_io.h"
#include "pw_framebuffer/rgb565.h"
#include "pw_spin_delay/delay.h"

using pw::color::color_rgb565_t;
using pw::digital_io::State;
using pw::framebuffer::FramebufferRgb565;
using pw::spi::ChipSelectBehavior;
using pw::spi::Device;

namespace pw::display_driver {

namespace {

constexpr std::array<std::byte, 0> kEmptyByteArray = {};
constexpr uint16_t ILI9341_MADCTL = 0x36;
constexpr std::byte MADCTL_MY = std::byte{0x80};
constexpr std::byte MADCTL_MX = std::byte{0x40};
constexpr std::byte MADCTL_MV = std::byte{0x20};
constexpr std::byte MADCTL_ML = std::byte{0x10};
constexpr std::byte MADCTL_RGB = std::byte{0x00};
constexpr std::byte MADCTL_BGR = std::byte{0x08};
constexpr std::byte MADCTL_MH = std::byte{0x04};

constexpr uint8_t ILI9341_CASET = 0x2a;  // Column address set.
constexpr uint8_t ILI9341_PASET = 0x2b;  // Page address set.
constexpr uint8_t ILI9341_RAMWR = 0x2c;  // Memory write.
constexpr uint16_t ILI9341_PIXEL_FORMAT_SET = 0x3A;

// The ILI9341 is hard-coded at 320x240;
constexpr int kDisplayWidth = 320;
constexpr int kDisplayHeight = 240;
constexpr int kDisplayNumPixels = kDisplayWidth * kDisplayHeight;

constexpr std::byte kMode0 = MADCTL_MX | MADCTL_BGR;
constexpr std::byte kMode1 = MADCTL_MV | MADCTL_BGR;
constexpr std::byte kMode2 = MADCTL_MY | MADCTL_BGR;
constexpr std::byte kMode3 = MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR;

// Frame Control (Normal Mode)
constexpr std::byte kFrameRate61 = std::byte{0x1F};
constexpr std::byte kFrameRate70 = std::byte{0x1B};
constexpr std::byte kFrameRate79 = std::byte{0x18};
constexpr std::byte kFrameRate119 = std::byte{0x10};

constexpr std::byte kPixelFormat16bits = std::byte(0x55);
constexpr std::byte kPixelFormat18bits = std::byte(0x36);

constexpr uint8_t HighByte(uint16_t val) { return val >> 8; }

constexpr uint8_t LowByte(uint16_t val) { return val & 0xff; }

}  // namespace

DisplayDriverILI9341::DisplayDriverILI9341(const Config& config)
    : config_(config) {}

void DisplayDriverILI9341::SetMode(Mode mode) {
  // Set the D/CX pin to indicate data or command values.
  if (mode == Mode::kData) {
    config_.data_cmd_gpio.SetState(State::kActive);
  } else {
    config_.data_cmd_gpio.SetState(State::kInactive);
  }
}

Status DisplayDriverILI9341::WriteCommand(Device::Transaction& transaction,
                                          const Command& command) {
  SetMode(Mode::kCommand);
  std::byte buff[1]{static_cast<std::byte>(command.command)};
  auto s = transaction.Write(buff);
  if (!s.ok())
    return s;

  SetMode(Mode::kData);
  if (command.command_data.empty())
    return OkStatus();
  return transaction.Write(command.command_data);
}

Status DisplayDriverILI9341::Init() {
  Reset().IgnoreError();

  // TODO(cmumford): Figure out why kPerTransaction is flakey for this.
  // Seems to be OK on the Pico's display, but not the STM32F429I-DISC1.
  auto transaction = config_.spi_device_8_bit.StartTransaction(
      ChipSelectBehavior::kPerWriteRead);

  // ?
  WriteCommand(transaction,
               {0xEF,
                std::array<std::byte, 3>{
                    std::byte{0x03},
                    std::byte{0x80},
                    std::byte{0x02},
                }});

  // ?
  WriteCommand(transaction,
               {0xCF,
                std::array<std::byte, 3>{
                    std::byte{0x00},
                    std::byte{0xC1},
                    std::byte{0x30},
                }});

  // ?
  WriteCommand(transaction,
               {0xED,
                std::array<std::byte, 4>{
                    std::byte{0x64},
                    std::byte{0x03},
                    std::byte{0x12},
                    std::byte{0x81},
                }});

  // ?
  WriteCommand(transaction,
               {0xE8,
                std::array<std::byte, 3>{
                    std::byte{0x85},
                    std::byte{0x00},
                    std::byte{0x78},
                }});

  // ?
  WriteCommand(transaction,
               {0xCB,
                std::array<std::byte, 5>{
                    std::byte{0x39},
                    std::byte{0x2C},
                    std::byte{0x00},
                    std::byte{0x34},
                    std::byte{0x02},
                }});

  // ?
  WriteCommand(transaction, {0xF7, std::array<std::byte, 1>{std::byte{0x20}}});

  // ?
  WriteCommand(transaction,
               {0xEA,
                std::array<std::byte, 2>{
                    std::byte{0x00},
                    std::byte{0x00},
                }});

  // Power control
  WriteCommand(transaction, {0xC0, std::array<std::byte, 1>{std::byte{0x23}}});

  // Power control
  WriteCommand(transaction, {0xC1, std::array<std::byte, 1>{std::byte{0x10}}});

  // VCM control
  WriteCommand(transaction,
               {0xC5,
                std::array<std::byte, 2>{
                    std::byte{0x3e},
                    std::byte{0x28},
                }});

  // VCM control
  WriteCommand(transaction, {0xC7, std::array<std::byte, 1>{std::byte{0x86}}});

  WriteCommand(transaction, {ILI9341_MADCTL, std::array<std::byte, 1>{kMode3}});

  WriteCommand(
      transaction,
      {ILI9341_PIXEL_FORMAT_SET, std::array<std::byte, 1>{kPixelFormat16bits}});

  WriteCommand(transaction,
               {0xB1,
                std::array<std::byte, 2>{
                    std::byte{0x00},  // division ratio
                    kFrameRate61,
                }});

  // Display Function Control
  WriteCommand(transaction,
               {0xB6,
                std::array<std::byte, 3>{
                    std::byte{0x08},
                    std::byte{0x82},
                    std::byte{0x27},
                }});

  // Gamma Function Disable?
  WriteCommand(transaction, {0xF2, std::array<std::byte, 1>{std::byte{0x00}}});

  // Gamma Set
  WriteCommand(transaction, {0x26, std::array<std::byte, 1>{std::byte{0x01}}});

  // Positive Gamma Correction
  WriteCommand(transaction,
               {0xE0,
                std::array<std::byte, 15>{
                    std::byte{0x0F},
                    std::byte{0x31},
                    std::byte{0x2B},
                    std::byte{0x0C},
                    std::byte{0x0E},
                    std::byte{0x08},
                    std::byte{0x4E},
                    std::byte{0xF1},
                    std::byte{0x37},
                    std::byte{0x07},
                    std::byte{0x10},
                    std::byte{0x03},
                    std::byte{0x0E},
                    std::byte{0x09},
                    std::byte{0x00},
                }});

  // Negative Gamma Correction
  WriteCommand(transaction,
               {0xE1,
                std::array<std::byte, 15>{
                    std::byte{0x00},
                    std::byte{0x0E},
                    std::byte{0x14},
                    std::byte{0x03},
                    std::byte{0x11},
                    std::byte{0x07},
                    std::byte{0x31},
                    std::byte{0xC1},
                    std::byte{0x48},
                    std::byte{0x08},
                    std::byte{0x0F},
                    std::byte{0x0C},
                    std::byte{0x31},
                    std::byte{0x36},
                    std::byte{0x0F},
                }});

  // Exit Sleep
  WriteCommand(transaction, {0x11, std::array<std::byte, 0>{}});
  pw::spin_delay::WaitMillis(100);

  // Display On
  WriteCommand(transaction, {0x29, std::array<std::byte, 0>{}});
  pw::spin_delay::WaitMillis(100);

  // Normal display mode on
  WriteCommand(transaction, {0x13, std::array<std::byte, 0>{}});

  // Setup drawing full framebuffers

  // Landscape drawing Column Address Set
  constexpr uint16_t kMaxColumn = kDisplayWidth - 1;
  WriteCommand(transaction,
               {0x2A,
                std::array<std::byte, 4>{
                    std::byte{0x0},
                    std::byte{0x0},
                    std::byte{kMaxColumn >> 8},    // high byte of short.
                    std::byte{kMaxColumn & 0xff},  // low byte of short.
                }});

  // Page Address Set
  constexpr uint16_t kMaxRow = kDisplayHeight - 1;
  WriteCommand(transaction,
               {0x2B,
                std::array<std::byte, 4>{
                    std::byte{0x0},
                    std::byte{0x0},
                    std::byte{kMaxRow >> 8},    // high byte of short.
                    std::byte{kMaxRow & 0xff},  // low byte of short.
                }});

  pw::spin_delay::WaitMillis(10);
  WriteCommand(transaction, {0x2C, std::array<std::byte, 0>{}});

  SetMode(Mode::kData);
  pw::spin_delay::WaitMillis(100);

  return OkStatus();
}

FramebufferRgb565 DisplayDriverILI9341::GetFramebuffer() {
  return FramebufferRgb565(config_.pool_data.fb_addr[0],
                           config_.pool_data.size.width,
                           config_.pool_data.size.height,
                           config_.pool_data.row_bytes);
}

Status DisplayDriverILI9341::ReleaseFramebuffer(
    FramebufferRgb565 frame_buffer) {
  auto transaction = config_.spi_device_16_bit.StartTransaction(
      ChipSelectBehavior::kPerTransaction);
  const uint16_t* fb_data = frame_buffer.GetFramebufferData();
  Status s;
  // TODO(cmumford): Figure out why the STM32F429I cannot send the entire
  // framebuffer in a single write, but another display can.
#if 1
  constexpr int kNumRowsPerSend = 10;
  static_assert(!(kDisplayHeight % kNumRowsPerSend),
                "Cannot send fractional number of rows");
  constexpr int kNumSends = kDisplayHeight / kNumRowsPerSend;
  constexpr size_t kNumPixelsInSend = kDisplayWidth * kNumRowsPerSend;

  for (int i = 0; i < kNumSends && s.ok(); i++) {
    const uint8_t* data = reinterpret_cast<const uint8_t*>(
        &fb_data[kDisplayWidth * (kNumRowsPerSend * i)]);
    // At this point the SPI bus is in 16-bit mode, so we send the number
    // of 16-bit values (i.e. pixels).
    s = transaction.Write(ConstByteSpan(
        reinterpret_cast<const std::byte*>(data), kNumPixelsInSend));
  }
#else
  s = transaction.Write(ConstByteSpan(
      reinterpret_cast<const std::byte*>(fb_data), kDisplayNumPixels));
#endif
  return s;
}

Status DisplayDriverILI9341::WriteRow(span<uint16_t> row_pixels,
                                      int row_idx,
                                      int col_idx) {
  {
    // Let controller know a write is coming.
    auto transaction = config_.spi_device_8_bit.StartTransaction(
        ChipSelectBehavior::kPerWriteRead);
    // Landscape drawing Column Address Set
    const uint16_t max_col_idx = std::max(
        kDisplayWidth - 1, col_idx + static_cast<int>(row_pixels.size()));
    WriteCommand(transaction,
                 {ILI9341_CASET,
                  std::array<std::byte, 4>{
                      std::byte{HighByte(col_idx)},
                      std::byte{LowByte(col_idx)},
                      std::byte{HighByte(max_col_idx)},
                      std::byte{LowByte(max_col_idx)},
                  }});

    // Page Address Set
    uint16_t max_row_idx = row_idx;
    WriteCommand(transaction,
                 {ILI9341_PASET,
                  std::array<std::byte, 4>{
                      std::byte{HighByte(row_idx)},
                      std::byte{LowByte(row_idx)},
                      std::byte{HighByte(max_row_idx)},
                      std::byte{LowByte(max_row_idx)},
                  }});
    PW_TRY(WriteCommand(transaction, {ILI9341_RAMWR, kEmptyByteArray}));
  }

  auto transaction = config_.spi_device_16_bit.StartTransaction(
      ChipSelectBehavior::kPerTransaction);
  return transaction.Write(
      ConstByteSpan(reinterpret_cast<const std::byte*>(row_pixels.data()),
                    row_pixels.size()));
}

int DisplayDriverILI9341::GetWidth() const { return kDisplayWidth; }

int DisplayDriverILI9341::GetHeight() const { return kDisplayHeight; }

Status DisplayDriverILI9341::Reset() {
  if (!config_.reset_gpio)
    return Status::Unavailable();
  auto s = config_.reset_gpio->SetStateInactive();
  if (!s.ok())
    return s;
  pw::spin_delay::WaitMillis(100);
  s = config_.reset_gpio->SetStateActive();
  pw::spin_delay::WaitMillis(100);
  return s;
}

}  // namespace pw::display_driver
