// 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/framebuffer.h"
#include "pw_spin_delay/delay.h"

using pw::color::color_rgb565_t;
using pw::digital_io::State;
using pw::framebuffer::Framebuffer;
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();
}

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

Status DisplayDriverILI9341::ReleaseFramebuffer(Framebuffer 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
