Load image from flash instead
This commit is contained in:
parent
c3166e54b2
commit
88a6671d37
@ -8,6 +8,8 @@ add_executable(mtgcard
|
||||
src/main.cpp
|
||||
src/display.cpp
|
||||
src/pixelstream.cpp
|
||||
src/lib.cpp
|
||||
src/flash.cpp
|
||||
|
||||
src/usb_descriptors.c
|
||||
)
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
#include <hardware/spi.h>
|
||||
|
||||
namespace display
|
||||
namespace lib
|
||||
{
|
||||
|
||||
class PixelStream;
|
||||
|
||||
58
include/flash.h
Normal file
58
include/flash.h
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef FLASH_H
|
||||
#define FLASH_H
|
||||
|
||||
#include <hardware/spi.h>
|
||||
|
||||
namespace lib
|
||||
{
|
||||
|
||||
class Flash
|
||||
{
|
||||
public:
|
||||
class Page
|
||||
{
|
||||
public:
|
||||
static constexpr size_t SIZE = 256;
|
||||
static constexpr size_t COUNT_PER_SECTOR = 4096 / SIZE;
|
||||
|
||||
operator uint8_t*();
|
||||
operator const uint8_t*() const;
|
||||
|
||||
uint8_t& operator[](int address);
|
||||
uint8_t operator[](int address) const;
|
||||
|
||||
private:
|
||||
uint8_t buffer[SIZE];
|
||||
};
|
||||
|
||||
Flash(uint8_t sck, uint8_t tx, uint8_t rx, uint8_t cs, int baudrate);
|
||||
|
||||
void read_page(uint16_t page_index);
|
||||
void write_page(uint16_t page_index);
|
||||
|
||||
void erase_sector(uint16_t page_index);
|
||||
|
||||
Page& page();
|
||||
const Page& page() const;
|
||||
|
||||
private:
|
||||
uint8_t sck, tx, rx, cs;
|
||||
spi_inst_t* spi;
|
||||
|
||||
Page page_buffer;
|
||||
|
||||
void write_enable();
|
||||
void wait_done();
|
||||
|
||||
static constexpr uint8_t CMD_PAGE_PROGRAM = 0x02;
|
||||
static constexpr uint8_t CMD_READ = 0x03;
|
||||
static constexpr uint8_t CMD_STATUS = 0x05;
|
||||
static constexpr uint8_t CMD_WRITE_EN = 0x06;
|
||||
static constexpr uint8_t CMD_SECTOR_ERASE = 0x20;
|
||||
|
||||
static constexpr uint8_t STATUS_BUSY_MASK = 0x01;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FLASH_H
|
||||
13
include/lib.h
Normal file
13
include/lib.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef LIB_H
|
||||
#define LIB_H
|
||||
|
||||
#include <hardware/spi.h>
|
||||
|
||||
namespace lib::detail
|
||||
{
|
||||
|
||||
spi_inst_t* get_spi_instance(uint8_t gpio);
|
||||
|
||||
}
|
||||
|
||||
#endif // LIB_H
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
#include <pico/stdlib.h>
|
||||
|
||||
namespace display
|
||||
namespace lib
|
||||
{
|
||||
|
||||
class Display;
|
||||
@ -17,6 +17,8 @@ public:
|
||||
PixelStream& operator=(const PixelStream&) = delete;
|
||||
~PixelStream();
|
||||
|
||||
// prefer other overload when possible
|
||||
void write(uint8_t data);
|
||||
void write(uint8_t red, uint8_t green, uint8_t blue);
|
||||
|
||||
private:
|
||||
|
||||
@ -1,21 +1,12 @@
|
||||
#include "display.h"
|
||||
|
||||
#include "lib.h"
|
||||
#include "pixelstream.h"
|
||||
|
||||
#include <hardware/spi.h>
|
||||
#include <pico/stdlib.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
spi_inst_t* get_spi_instance(uint8_t gpio)
|
||||
{
|
||||
return gpio % 16 < 8 ? spi0 : spi1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using namespace display;
|
||||
using namespace lib;
|
||||
|
||||
Display::Display(uint8_t sck, uint8_t tx, uint8_t cs, uint8_t dc,
|
||||
int baudrate) :
|
||||
@ -24,8 +15,8 @@ Display::Display(uint8_t sck, uint8_t tx, uint8_t cs, uint8_t dc,
|
||||
cs(cs),
|
||||
dc(dc)
|
||||
{
|
||||
spi_inst_t* sck_spi = get_spi_instance(sck);
|
||||
spi_inst_t* tx_spi = get_spi_instance(tx);
|
||||
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;
|
||||
@ -68,7 +59,7 @@ Display::Display(uint8_t sck, uint8_t tx, uint8_t cs, uint8_t dc,
|
||||
sleep_ms(10);
|
||||
|
||||
// set display brightness
|
||||
send_command(0x51, 0xFF);
|
||||
send_command(0x51, 0x00);
|
||||
|
||||
// clear display to black
|
||||
{
|
||||
|
||||
102
src/flash.cpp
Normal file
102
src/flash.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
#include "flash.h"
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
#include <pico/stdlib.h>
|
||||
|
||||
using namespace lib;
|
||||
|
||||
Flash::Page::operator unsigned char*() { return buffer; }
|
||||
Flash::Page::operator const unsigned char*() const { return buffer; }
|
||||
|
||||
uint8_t& Flash::Page::operator[](int address) { return buffer[address]; }
|
||||
uint8_t Flash::Page::operator[](int address) const { return buffer[address]; }
|
||||
|
||||
Flash::Flash(uint8_t sck, uint8_t tx, uint8_t rx, uint8_t cs, int baudrate) :
|
||||
sck(sck),
|
||||
tx(tx),
|
||||
rx(rx),
|
||||
cs(cs)
|
||||
{
|
||||
spi_inst_t* sck_spi = detail::get_spi_instance(sck);
|
||||
spi_inst_t* tx_spi = detail::get_spi_instance(tx);
|
||||
spi_inst_t* rx_spi = detail::get_spi_instance(rx);
|
||||
|
||||
hard_assert(sck_spi == tx_spi && tx_spi == rx_spi, "Invalid configuration");
|
||||
spi = sck_spi;
|
||||
|
||||
gpio_set_function(sck, GPIO_FUNC_SPI);
|
||||
gpio_set_function(tx, GPIO_FUNC_SPI);
|
||||
gpio_set_function(rx, GPIO_FUNC_SPI);
|
||||
|
||||
gpio_set_function(cs, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(cs, GPIO_OUT);
|
||||
gpio_put(cs, true);
|
||||
|
||||
spi_init(spi, baudrate);
|
||||
}
|
||||
|
||||
void Flash::read_page(uint16_t page_index)
|
||||
{
|
||||
const uint8_t cmd[5] = { CMD_READ, static_cast<uint8_t>(page_index >> 8),
|
||||
static_cast<uint8_t>(page_index), 0, 0 };
|
||||
|
||||
gpio_put(cs, false);
|
||||
spi_write_blocking(spi, cmd, 4);
|
||||
spi_read_blocking(spi, 0, page_buffer, Page::SIZE);
|
||||
gpio_put(cs, true);
|
||||
}
|
||||
|
||||
void Flash::write_page(uint16_t page_index)
|
||||
{
|
||||
write_enable();
|
||||
|
||||
uint8_t cmd[4] = { CMD_PAGE_PROGRAM, static_cast<uint8_t>(page_index >> 8),
|
||||
static_cast<uint8_t>(page_index), 0 };
|
||||
|
||||
gpio_put(cs, false);
|
||||
spi_write_blocking(spi, cmd, 4);
|
||||
spi_write_blocking(spi, page_buffer, Page::SIZE);
|
||||
gpio_put(cs, true);
|
||||
|
||||
wait_done();
|
||||
}
|
||||
|
||||
void Flash::erase_sector(uint16_t page_index)
|
||||
{
|
||||
write_enable();
|
||||
|
||||
uint8_t cmd[4] = { CMD_SECTOR_ERASE, static_cast<uint8_t>(page_index >> 8),
|
||||
static_cast<uint8_t>(page_index), 0 };
|
||||
|
||||
gpio_put(cs, false);
|
||||
spi_write_blocking(spi, cmd, 4);
|
||||
gpio_put(cs, true);
|
||||
|
||||
wait_done();
|
||||
}
|
||||
|
||||
Flash::Page& Flash::page() { return page_buffer; }
|
||||
const Flash::Page& Flash::page() const { return page_buffer; }
|
||||
|
||||
void Flash::write_enable()
|
||||
{
|
||||
uint8_t cmd = CMD_WRITE_EN;
|
||||
|
||||
gpio_put(cs, false);
|
||||
spi_write_blocking(spi, &cmd, 1);
|
||||
gpio_put(cs, true);
|
||||
}
|
||||
|
||||
void Flash::wait_done()
|
||||
{
|
||||
for (uint8_t status = STATUS_BUSY_MASK; status & STATUS_BUSY_MASK;)
|
||||
{
|
||||
uint8_t cmd = CMD_STATUS;
|
||||
|
||||
gpio_put(cs, false);
|
||||
spi_write_blocking(spi, &cmd, 1);
|
||||
spi_read_blocking(spi, 0, &status, 1);
|
||||
gpio_put(cs, true);
|
||||
}
|
||||
}
|
||||
8
src/lib.cpp
Normal file
8
src/lib.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
#include "lib.h"
|
||||
|
||||
using namespace lib;
|
||||
|
||||
spi_inst_t* detail::get_spi_instance(uint8_t gpio)
|
||||
{
|
||||
return gpio % 16 < 8 ? spi0 : spi1;
|
||||
}
|
||||
70
src/main.cpp
70
src/main.cpp
@ -1,16 +1,17 @@
|
||||
#include "display.h"
|
||||
#include "flash.h"
|
||||
#include "pixelstream.h"
|
||||
#include "tusb.h"
|
||||
|
||||
#include <pico/stdlib.h>
|
||||
#include <tusb.h>
|
||||
|
||||
using namespace lib;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
display::Display disp(2, 3, 5, 6, 5000000);
|
||||
uint16_t row = 0;
|
||||
uint16_t column = 0;
|
||||
uint8_t row_data[240 * 3];
|
||||
Display disp(2, 3, 5, 6, 120000000);
|
||||
Flash flash(26, 27, 28, 29, 70000000);
|
||||
|
||||
}
|
||||
|
||||
@ -20,6 +21,20 @@ int main()
|
||||
= { .role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_AUTO };
|
||||
tud_init(0);
|
||||
|
||||
{
|
||||
auto pixels = disp.pixels();
|
||||
for (int page_index = 0; page_index < 900; page_index++)
|
||||
{
|
||||
flash.read_page(page_index);
|
||||
const auto& page = flash.page();
|
||||
|
||||
for (int i = 0; i < Flash::Page::SIZE; i++)
|
||||
{
|
||||
pixels.write(page[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
tud_task();
|
||||
@ -28,32 +43,37 @@ int main()
|
||||
|
||||
void tud_vendor_rx_cb(uint8_t itf, const uint8_t* buffer, uint16_t bufsize)
|
||||
{
|
||||
size_t written = 0;
|
||||
static size_t written = 0;
|
||||
static uint16_t page_index = 0;
|
||||
|
||||
while (written < bufsize)
|
||||
if (written == 0 && page_index == 0)
|
||||
{
|
||||
size_t copy_size = bufsize - written < (240 * 3) - column
|
||||
? bufsize - written
|
||||
: (240 * 3) - column;
|
||||
memcpy(row_data + column, buffer + written, copy_size);
|
||||
column += copy_size;
|
||||
written += copy_size;
|
||||
|
||||
if (column >= 240 * 3)
|
||||
for (int i = 0; i < 320 * 240 * 3 / 256; i += 4096 / 256)
|
||||
{
|
||||
disp.set_update_area(0, row, 240, 320);
|
||||
auto pixels = disp.pixels();
|
||||
for (int i = 0; i < 240; i++)
|
||||
{
|
||||
pixels.write(row_data[i * 3], row_data[i * 3 + 1],
|
||||
row_data[i * 3 + 2]);
|
||||
flash.erase_sector(i);
|
||||
}
|
||||
}
|
||||
|
||||
column -= 240 * 3;
|
||||
row += 1;
|
||||
if (row == 320)
|
||||
for (size_t read = 0; read < bufsize;)
|
||||
{
|
||||
row = 0;
|
||||
size_t copy_size = bufsize - read < Flash::Page::SIZE - written
|
||||
? bufsize - read
|
||||
: Flash::Page::SIZE - written;
|
||||
|
||||
memcpy(flash.page() + written, buffer + read, copy_size);
|
||||
read += copy_size;
|
||||
|
||||
written += copy_size;
|
||||
|
||||
if (written == 256)
|
||||
{
|
||||
flash.write_page(page_index);
|
||||
page_index += 1;
|
||||
written = 0;
|
||||
|
||||
if (page_index == 900)
|
||||
{
|
||||
page_index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
#include "display.h"
|
||||
|
||||
using namespace display;
|
||||
using namespace lib;
|
||||
|
||||
PixelStream::PixelStream(Display& display) :
|
||||
display(display)
|
||||
@ -10,6 +10,8 @@ PixelStream::PixelStream(Display& display) :
|
||||
display.send_command_and_begin_data_stream(0x2C);
|
||||
}
|
||||
|
||||
void PixelStream::write(uint8_t data) { display.send_data(data); }
|
||||
|
||||
void PixelStream::write(uint8_t red, uint8_t green, uint8_t blue)
|
||||
{
|
||||
display.send_data(red);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user