pimoroni-pico/drivers/psram_display/psram_display.hpp

129 lines
3.6 KiB
C++

#pragma once
#include <cstring>
#include "pico/stdlib.h"
#include "hardware/spi.h"
#include "hardware/gpio.h"
#include "common/pimoroni_common.hpp"
#include "common/pimoroni_bus.hpp"
#include "libraries/pico_graphics/pico_graphics.hpp"
// 8 MB PSRam
namespace pimoroni {
class PSRamDisplay : public IDirectDisplayDriver<uint8_t> {
//--------------------------------------------------
// Variables
//--------------------------------------------------
private:
spi_inst_t *spi = PIMORONI_SPI_DEFAULT_INSTANCE;
// interface pins with our standard defaults where appropriate
uint CS = 3;
uint DC = PIN_UNUSED;
uint SCK = SPI_DEFAULT_SCK;
uint MOSI = SPI_DEFAULT_MOSI;
uint MISO = SPI_DEFAULT_MISO;
uint32_t start_address = 0;
uint16_t width = 0;
uint16_t height = 0;
absolute_time_t timeout;
bool blocking = false;
public:
enum colour : uint8_t {
BLACK = 0,
WHITE = 1,
GREEN = 2,
BLUE = 3,
RED = 4,
YELLOW = 5,
ORANGE = 6,
CLEAN = 7
};
PSRamDisplay(uint16_t width, uint16_t height) : PSRamDisplay(width, height, {PIMORONI_SPI_DEFAULT_INSTANCE, 3, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, PIN_UNUSED, PIN_UNUSED, PIN_UNUSED}) {};
PSRamDisplay(uint16_t width, uint16_t height, SPIPins pins) :
spi(pins.spi),
CS(pins.cs), DC(pins.dc), SCK(pins.sck), MOSI(pins.mosi),
width(width), height(height) {
init();
}
//--------------------------------------------------
// Methods
//--------------------------------------------------
public:
void test(void){
char writeBuffer[1024];
char readBuffer[1024];
uint mb = 8;
for(uint k = 0; k < 1024*mb; k++)
{
sprintf(writeBuffer, "%u", k);
write(k*1024, strlen(writeBuffer)+1, (uint8_t *)writeBuffer);
}
bool bSame = true;
for(uint k = 0; k < 1024*mb && bSame; k++)
{
sprintf(writeBuffer, "%u", k);
read(k*1024, strlen(writeBuffer)+1, (uint8_t *)readBuffer);
bSame = strcmp(writeBuffer, readBuffer) ==0;
printf("[%u] %s == %s ? %s\n", k, writeBuffer, readBuffer, bSame ? "Success" : "Failure");
}
}
void write_pixel(const Point &p, uint8_t colour) override;
void write_pixel_span(const Point &p, uint l, uint8_t colour) override;
void read_pixel_span(const Point &p, uint l, uint8_t *data) override;
int __not_in_flash_func(SpiSetBlocking)(const uint16_t uSrc, size_t uLen)
{
invalid_params_if(SPI, 0 > (int)uLen);
// Deliberately overflow FIFO, then clean up afterward, to minimise amount
// of APB polling required per halfword
for (size_t i = 0; i < uLen; ++i) {
while (!spi_is_writable(spi))
tight_loop_contents();
spi_get_hw(spi)->dr = uSrc;
}
while (spi_is_readable(spi))
(void)spi_get_hw(spi)->dr;
while (spi_get_hw(spi)->sr & SPI_SSPSR_BSY_BITS)
tight_loop_contents();
while (spi_is_readable(spi))
(void)spi_get_hw(spi)->dr;
// Don't leave overrun flag set
spi_get_hw(spi)->icr = SPI_SSPICR_RORIC_BITS;
return (int)uLen;
}
private:
void init();
void write(uint32_t address, size_t len, const uint8_t *data);
void write(uint32_t address, size_t len, const uint8_t byte);
void read(uint32_t address, size_t len, uint8_t *data);
uint32_t pointToAddress(const Point &p)
{
return start_address + (p.y * width) + p.x;
}
};
}