mtgcard-firmware/src/display.cpp

144 lines
3.1 KiB
C++

#include "display.h"
#include "lib.h"
#include "pixelstream.h"
#include <hardware/spi.h>
#include <pico/stdlib.h>
using namespace lib;
Display::Display(uint8_t sck, uint8_t tx, uint8_t cs, uint8_t dc,
int baudrate) :
sck(sck),
tx(tx),
cs(cs),
dc(dc)
{
spi_inst_t* sck_spi = detail::get_spi_instance(sck);
spi_inst_t* tx_spi = detail::get_spi_instance(tx);
hard_assert(sck_spi == tx_spi, "Invalid configuration");
spi = sck_spi;
gpio_set_function(sck, GPIO_FUNC_SPI);
gpio_set_function(tx, GPIO_FUNC_SPI);
// chip select and data/command controlled manually
gpio_set_function(cs, GPIO_FUNC_SIO);
gpio_set_dir(cs, GPIO_OUT);
gpio_set_function(dc, GPIO_FUNC_SIO);
gpio_set_dir(dc, GPIO_OUT);
spi_init(spi, baudrate);
// initialize display command sequence
// -----------------------------------
// reset device
send_command(0x01);
sleep_ms(150);
// take device out of sleep mode
send_command(0x11);
sleep_ms(10);
// set display format to 18-bit color
send_command(0x3A, 0x66);
sleep_ms(10);
set_update_area(0, 0, 240, 320);
// set memory addressing mode
send_command(0x36, 0b11000000);
// turn on display inversion
send_command(0x21);
// set display to normal mode
send_command(0x13);
sleep_ms(10);
// set display brightness
send_command(0x51, 0x00);
// clear display to black
{
auto p = pixels();
for (int i = 0; i < 320 * 240; i++)
{
p.write(0, 0, 0);
}
}
// turn on display
send_command(0x29);
sleep_ms(10);
}
void Display::set_update_area(uint16_t left, uint16_t top, uint16_t width,
uint16_t height)
{
const uint16_t right = left + width;
const uint16_t bottom = top + height;
{
uint8_t params[4]
= { static_cast<uint8_t>(left >> 8), static_cast<uint8_t>(left & 0xFF),
static_cast<uint8_t>(right >> 8),
static_cast<uint8_t>(right & 0xFF) };
send_command(0x2A, params, 4);
}
{
uint8_t params[4]
= { static_cast<uint8_t>(top >> 8), static_cast<uint8_t>(top & 0xFF),
static_cast<uint8_t>(bottom >> 8),
static_cast<uint8_t>(bottom & 0xFF) };
send_command(0x2B, params, 4);
}
}
PixelStream Display::pixels() { return PixelStream(*this); }
void Display::send_command(uint8_t command)
{
send_command(command, nullptr, 0);
}
void Display::send_command(uint8_t command, uint8_t param)
{
send_command(command, &param, 1);
}
void Display::send_command(uint8_t command, const uint8_t* params,
size_t param_count)
{
gpio_put(cs, false);
gpio_put(dc, false);
spi_write_blocking(spi, &command, 1);
if (param_count > 0)
{
// parameters are sent via data mode
gpio_put(dc, true);
spi_write_blocking(spi, params, param_count);
}
gpio_put(cs, true);
}
void Display::send_command_and_begin_data_stream(uint8_t command)
{
gpio_put(cs, false);
gpio_put(dc, false);
spi_write_blocking(spi, &command, 1);
gpio_put(dc, true);
}
void Display::send_data(uint8_t data) { spi_write_blocking(spi, &data, 1); }
void Display::end_data_stream() { gpio_put(cs, true); }