Started with font rendering
This commit is contained in:
@@ -26,7 +26,7 @@ pico_generate_pio_header(${PROJECT_NAME}
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/video_dma.pio
|
${CMAKE_CURRENT_LIST_DIR}/video_dma.pio
|
||||||
)
|
)
|
||||||
|
|
||||||
target_sources(picopal PRIVATE main.c)
|
target_sources(picopal PRIVATE main.c cvideo.c)
|
||||||
|
|
||||||
|
|
||||||
pico_set_program_name(picopal "picopal")
|
pico_set_program_name(picopal "picopal")
|
||||||
@@ -44,6 +44,7 @@ target_link_libraries(picopal
|
|||||||
hardware_pio
|
hardware_pio
|
||||||
hardware_timer
|
hardware_timer
|
||||||
hardware_clocks
|
hardware_clocks
|
||||||
|
pico_multicore
|
||||||
)
|
)
|
||||||
|
|
||||||
pico_add_extra_outputs(picopal)
|
pico_add_extra_outputs(picopal)
|
||||||
|
|||||||
196
cvideo.c
Normal file
196
cvideo.c
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
#include "cvideo.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#include "hardware/clocks.h"
|
||||||
|
#include "hardware/dma.h"
|
||||||
|
#include "hardware/irq.h"
|
||||||
|
#include "hardware/pio.h"
|
||||||
|
|
||||||
|
#include "video_dma.pio.h"
|
||||||
|
|
||||||
|
// ---------------------------
|
||||||
|
// User-adjustable pins
|
||||||
|
// ---------------------------
|
||||||
|
#define VIDEO_PIO pio0
|
||||||
|
#define DATA_SM 0
|
||||||
|
#define SYNC_SM 1
|
||||||
|
|
||||||
|
#define DATA_PIN 2 // pixel / luma bit pin
|
||||||
|
#define SYNC_PIN 3 // sync pin
|
||||||
|
|
||||||
|
#define SYNC_INTERVAL_S 0.000002f // 2 us per sync-SM instruction
|
||||||
|
#define ACTIVE_VIDEO_S 0.000052f // 52 us active video per line
|
||||||
|
|
||||||
|
// Match the .pio program's published constant.
|
||||||
|
// pioasm will emit CLOCKS_PER_BIT in the generated header.
|
||||||
|
#ifndef CLOCKS_PER_BIT
|
||||||
|
#define CLOCKS_PER_BIT 6
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Field/line tracking for line-based DMA.
|
||||||
|
// This is intentionally kept in software to match the sync SM's 288 active
|
||||||
|
// lines per field.
|
||||||
|
static volatile bool even_field = true;
|
||||||
|
static volatile uint line_in_field = 0;
|
||||||
|
|
||||||
|
// DMA channel that feeds the PIO TX FIFO
|
||||||
|
static int video_dma_chan;
|
||||||
|
|
||||||
|
static video_framebuffer_ptr_t framebuffer;
|
||||||
|
static volatile video_framebuffer_ptr_t pending_framebuffer;
|
||||||
|
static void (*framebuffer_switched_cb)() = NULL;
|
||||||
|
|
||||||
|
// ---------------------------
|
||||||
|
// PIO init helpers
|
||||||
|
// ---------------------------
|
||||||
|
static void init_cvdata_program(PIO pio, uint sm, uint offset, float clkdiv, uint data_pin) {
|
||||||
|
pio_sm_config c = cvdata_program_get_default_config(offset);
|
||||||
|
|
||||||
|
sm_config_set_set_pins(&c, data_pin, 1);
|
||||||
|
sm_config_set_out_pins(&c, data_pin, 1);
|
||||||
|
sm_config_set_clkdiv(&c, clkdiv);
|
||||||
|
|
||||||
|
// Shift left, autopull every 32 bits.
|
||||||
|
// If the image is mirrored, change this to shift-right and/or change bit packing.
|
||||||
|
sm_config_set_out_shift(&c, false, true, 32);
|
||||||
|
|
||||||
|
pio_gpio_init(pio, data_pin);
|
||||||
|
pio_sm_set_consecutive_pindirs(pio, sm, data_pin, 1, true);
|
||||||
|
|
||||||
|
pio_sm_init(pio, sm, offset, &c);
|
||||||
|
|
||||||
|
// Preload X = VIDEO_WIDTH - 1
|
||||||
|
pio_sm_put_blocking(pio, sm, VIDEO_WIDTH - 1);
|
||||||
|
pio_sm_exec(pio, sm, pio_encode_pull(false, false));
|
||||||
|
pio_sm_exec(pio, sm, pio_encode_mov(pio_x, pio_osr));
|
||||||
|
pio_sm_exec(pio, sm, pio_encode_out(pio_null, 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_cvsync_program(PIO pio, uint sm, uint offset, float clkdiv, uint sync_pin) {
|
||||||
|
pio_sm_config c = cvsync_program_get_default_config(offset);
|
||||||
|
|
||||||
|
sm_config_set_sideset_pins(&c, sync_pin);
|
||||||
|
sm_config_set_clkdiv(&c, clkdiv);
|
||||||
|
|
||||||
|
pio_gpio_init(pio, sync_pin);
|
||||||
|
pio_sm_set_consecutive_pindirs(pio, sm, sync_pin, 1, true);
|
||||||
|
|
||||||
|
pio_sm_init(pio, sm, offset, &c);
|
||||||
|
|
||||||
|
// Preload OSR = lines_per_field - 1
|
||||||
|
pio_sm_put_blocking(pio, sm, LINES_PER_FIELD - 1);
|
||||||
|
pio_sm_exec(pio, sm, pio_encode_pull(false, false));
|
||||||
|
|
||||||
|
// Start with Y = 0, meaning "even field" in this program.
|
||||||
|
pio_sm_exec(pio, sm, pio_encode_set(pio_y, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------
|
||||||
|
// DMA setup
|
||||||
|
// ---------------------------
|
||||||
|
static void init_video_dma(PIO pio, uint data_sm) {
|
||||||
|
video_dma_chan = dma_claim_unused_channel(true);
|
||||||
|
|
||||||
|
dma_channel_config cfg = dma_channel_get_default_config(video_dma_chan);
|
||||||
|
channel_config_set_transfer_data_size(&cfg, DMA_SIZE_32);
|
||||||
|
channel_config_set_read_increment(&cfg, true);
|
||||||
|
channel_config_set_write_increment(&cfg, false);
|
||||||
|
|
||||||
|
// Pace the DMA from the data SM TX FIFO DREQ
|
||||||
|
channel_config_set_dreq(&cfg, pio_get_dreq(pio, data_sm, true));
|
||||||
|
|
||||||
|
dma_channel_configure(
|
||||||
|
video_dma_chan,
|
||||||
|
&cfg,
|
||||||
|
&pio->txf[data_sm], // write address
|
||||||
|
NULL, // read address set per line
|
||||||
|
0, // transfer count set per line
|
||||||
|
false // don't start yet
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------
|
||||||
|
// Start DMA for one scanline
|
||||||
|
// ---------------------------
|
||||||
|
static inline void start_dma_for_current_line(void) {
|
||||||
|
if (line_in_field == 0 && even_field && pending_framebuffer) {
|
||||||
|
framebuffer = (video_framebuffer_ptr_t)pending_framebuffer;
|
||||||
|
pending_framebuffer = NULL;
|
||||||
|
if(framebuffer_switched_cb)
|
||||||
|
framebuffer_switched_cb();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint src_line = even_field ? (line_in_field * 2u) : (line_in_field * 2u + 1u);
|
||||||
|
|
||||||
|
dma_channel_set_read_addr(video_dma_chan, framebuffer[src_line], false);
|
||||||
|
dma_channel_set_trans_count(video_dma_chan, WORDS_PER_LINE, true);
|
||||||
|
|
||||||
|
line_in_field++;
|
||||||
|
if (line_in_field >= LINES_PER_FIELD) {
|
||||||
|
line_in_field = 0;
|
||||||
|
even_field = !even_field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------
|
||||||
|
// PIO IRQ handler:
|
||||||
|
// The sync SM pushes one token into its RX FIFO during each line's back porch.
|
||||||
|
// As soon as the previous line DMA has finished, consume one token and arm the
|
||||||
|
// next scanline so the data FIFO is primed before visible pixels start.
|
||||||
|
// ---------------------------
|
||||||
|
static void pio0_irq0_handler(void) {
|
||||||
|
if (!pio_sm_is_rx_fifo_empty(VIDEO_PIO, SYNC_SM) && !dma_channel_is_busy(video_dma_chan)) {
|
||||||
|
(void)pio_sm_get(VIDEO_PIO, SYNC_SM);
|
||||||
|
start_dma_for_current_line();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void video_init(video_framebuffer_t fb) {
|
||||||
|
if ((VIDEO_WIDTH % 32) != 0) {
|
||||||
|
panic("VIDEO_WIDTH must be a multiple of 32");
|
||||||
|
}
|
||||||
|
|
||||||
|
framebuffer = fb;
|
||||||
|
pending_framebuffer = NULL;
|
||||||
|
|
||||||
|
uint sync_offset = pio_add_program(VIDEO_PIO, &cvsync_program);
|
||||||
|
uint data_offset = pio_add_program(VIDEO_PIO, &cvdata_program);
|
||||||
|
|
||||||
|
// Same timing idea as the original repo:
|
||||||
|
// sync SM: 1 instruction every 2 us
|
||||||
|
// data SM: enough PIO cycles to emit VIDEO_WIDTH bits in 52 us
|
||||||
|
float sys_hz = (float)clock_get_hz(clk_sys);
|
||||||
|
float data_clkdiv = (sys_hz / ((float)VIDEO_WIDTH / ACTIVE_VIDEO_S)) / (float)CLOCKS_PER_BIT;
|
||||||
|
float sync_clkdiv = sys_hz * SYNC_INTERVAL_S;
|
||||||
|
|
||||||
|
init_cvdata_program(VIDEO_PIO, DATA_SM, data_offset, data_clkdiv, DATA_PIN);
|
||||||
|
init_cvsync_program(VIDEO_PIO, SYNC_SM, sync_offset, sync_clkdiv, SYNC_PIN);
|
||||||
|
init_video_dma(VIDEO_PIO, DATA_SM);
|
||||||
|
|
||||||
|
// Route sync-SM RX FIFO notifications to CPU IRQ 0.
|
||||||
|
pio_set_irq0_source_enabled(VIDEO_PIO, pis_sm1_rx_fifo_not_empty, true);
|
||||||
|
irq_set_exclusive_handler(PIO0_IRQ_0, pio0_irq0_handler);
|
||||||
|
irq_set_enabled(PIO0_IRQ_0, true);
|
||||||
|
|
||||||
|
// Start with the first line of the even field
|
||||||
|
even_field = true;
|
||||||
|
line_in_field = 0;
|
||||||
|
|
||||||
|
// Prime the FIFO so the very first active line does not depend on IRQ latency.
|
||||||
|
start_dma_for_current_line();
|
||||||
|
|
||||||
|
pio_sm_set_enabled(VIDEO_PIO, DATA_SM, true);
|
||||||
|
pio_sm_set_enabled(VIDEO_PIO, SYNC_SM, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void video_set_framebuffer(video_framebuffer_t fb) {
|
||||||
|
pending_framebuffer = fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void video_set_framebuffer_switched_cb(void (*cb)()){
|
||||||
|
framebuffer_switched_cb = cb;
|
||||||
|
}
|
||||||
18
cvideo.h
Normal file
18
cvideo.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// ---------------------------
|
||||||
|
// Video format
|
||||||
|
// ---------------------------
|
||||||
|
#define VIDEO_WIDTH 768
|
||||||
|
#define VIDEO_HEIGHT 576
|
||||||
|
#define WORDS_PER_LINE (VIDEO_WIDTH / 32)
|
||||||
|
#define LINES_PER_FIELD (VIDEO_HEIGHT / 2)
|
||||||
|
|
||||||
|
typedef uint32_t video_framebuffer_t[VIDEO_HEIGHT][WORDS_PER_LINE];
|
||||||
|
typedef uint32_t (*video_framebuffer_ptr_t)[WORDS_PER_LINE];
|
||||||
|
|
||||||
|
void video_init(video_framebuffer_t fb);
|
||||||
|
void video_set_framebuffer(video_framebuffer_t fb);
|
||||||
|
void video_set_framebuffer_switched_cb(void (*cb)());
|
||||||
324
font.xbm
Normal file
324
font.xbm
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
#define font_width 160
|
||||||
|
#define font_height 192
|
||||||
|
static char font_bits[] = {
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x06, 0x18, 0x60,
|
||||||
|
0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01,
|
||||||
|
0x06, 0x18, 0x60, 0x80, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67,
|
||||||
|
0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79,
|
||||||
|
0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67,
|
||||||
|
0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79,
|
||||||
|
0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x01, 0x06, 0x18, 0x60,
|
||||||
|
0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01,
|
||||||
|
0x06, 0x18, 0x60, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x06, 0x18, 0x60,
|
||||||
|
0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01,
|
||||||
|
0x06, 0x18, 0x60, 0x80, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67,
|
||||||
|
0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79,
|
||||||
|
0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67,
|
||||||
|
0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79,
|
||||||
|
0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x01, 0x06, 0x18, 0x60,
|
||||||
|
0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01,
|
||||||
|
0x06, 0x18, 0x60, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0xF9,
|
||||||
|
0xCC, 0xCF, 0xCF, 0x7C, 0xFC, 0xF3, 0x9F, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0x3F, 0x3F, 0xF9, 0xCC, 0x03, 0x4F, 0x3E,
|
||||||
|
0xF9, 0xF3, 0x8F, 0x1F, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF,
|
||||||
|
0xFF, 0x3F, 0x3F, 0x79, 0x80, 0x03, 0x7F, 0x3E, 0xF9, 0xF3, 0xCF, 0x3F,
|
||||||
|
0x9F, 0xE4, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0x3F, 0xFF, 0xFF,
|
||||||
|
0xCC, 0xCB, 0x3F, 0x7F, 0xFC, 0xFF, 0xE7, 0x7F, 0x3E, 0xF0, 0xF3, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0x3F, 0xFF, 0xFF, 0xCC, 0x03, 0x3F, 0x3F,
|
||||||
|
0xF4, 0xFF, 0xE7, 0x7F, 0x7E, 0xF8, 0xC0, 0xFF, 0x1F, 0xFE, 0xFF, 0xF3,
|
||||||
|
0xFF, 0x3F, 0xFF, 0x7F, 0x80, 0x4F, 0x9F, 0x9F, 0xF9, 0xFF, 0xE7, 0x7F,
|
||||||
|
0x3E, 0xF0, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xCC, 0x03, 0x9F, 0x9C, 0xF1, 0xFF, 0xE7, 0x7F, 0x9E, 0xE4, 0xF3, 0xCF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0x3F, 0xFF, 0xFF, 0xCC, 0x03, 0xCF, 0x3C,
|
||||||
|
0xE4, 0xFF, 0xCF, 0x3F, 0xFF, 0xFC, 0xF3, 0xCF, 0xFF, 0xFF, 0xFC, 0xF9,
|
||||||
|
0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x1F,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, 0xFC, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0x9F, 0xFF, 0xFF, 0xFF, 0xE7,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x3F, 0x7F, 0xF8,
|
||||||
|
0xC0, 0x8F, 0x0F, 0x7C, 0x78, 0xC0, 0x87, 0x1F, 0xFE, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xE1, 0x3B, 0x1F, 0x3F, 0xF3, 0xCE, 0x87, 0xCF, 0x3F,
|
||||||
|
0xFF, 0xCF, 0x3B, 0xEF, 0xFC, 0xFC, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC,
|
||||||
|
0x3B, 0x0F, 0xBF, 0xF3, 0xCF, 0x93, 0xCF, 0x3F, 0xFF, 0xC7, 0x3B, 0xEF,
|
||||||
|
0xFC, 0xFC, 0xF3, 0x3F, 0xFF, 0x3F, 0xFF, 0xCE, 0x3B, 0x3F, 0xFF, 0xF3,
|
||||||
|
0xE7, 0x99, 0x0F, 0x3E, 0xF8, 0xE7, 0x87, 0xEF, 0xFC, 0xFF, 0xFF, 0xCF,
|
||||||
|
0x1F, 0xFE, 0xFC, 0xC7, 0x3B, 0x3F, 0xFF, 0xF9, 0xE7, 0x99, 0xFF, 0x3C,
|
||||||
|
0xF7, 0xF3, 0x3B, 0x1F, 0xFC, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xF3, 0xE3,
|
||||||
|
0x3B, 0x3F, 0x7F, 0xFC, 0xCF, 0x01, 0xFF, 0x3C, 0xF7, 0xF3, 0x3B, 0xFF,
|
||||||
|
0xFC, 0xFC, 0xF3, 0xF3, 0x1F, 0xFE, 0xF3, 0xF3, 0x3B, 0x3F, 0x3F, 0xFF,
|
||||||
|
0xCE, 0x9F, 0xEF, 0x3C, 0xF7, 0xF9, 0x3B, 0xFF, 0xFC, 0xFC, 0xF3, 0xCF,
|
||||||
|
0xFF, 0xFF, 0xFC, 0xFF, 0x87, 0x0F, 0x3C, 0xF0, 0xE1, 0x9F, 0x1F, 0x7E,
|
||||||
|
0xF8, 0xF9, 0x87, 0x1F, 0xFE, 0xFF, 0xF1, 0x3F, 0xFF, 0x3F, 0xFF, 0xF3,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x3F, 0x3F, 0xF8,
|
||||||
|
0xE1, 0x83, 0x0F, 0x3C, 0xF0, 0xE1, 0x33, 0x1F, 0x3E, 0xF0, 0xCC, 0xF3,
|
||||||
|
0xE7, 0x39, 0xF3, 0xE1, 0x7B, 0x1F, 0x3E, 0xF3, 0xC0, 0x13, 0xCF, 0x3C,
|
||||||
|
0xF3, 0xCC, 0x33, 0x3F, 0xFF, 0xF3, 0xE4, 0xF3, 0xC7, 0x38, 0xF3, 0xCC,
|
||||||
|
0xCD, 0xCE, 0x3C, 0x73, 0xCE, 0x33, 0xCF, 0x3F, 0xFF, 0xCC, 0x33, 0x3F,
|
||||||
|
0xFF, 0xF3, 0xE4, 0xF3, 0x07, 0x38, 0xF2, 0xCC, 0xB5, 0xCE, 0x3C, 0x78,
|
||||||
|
0xFE, 0x33, 0x0F, 0x3E, 0xF8, 0xFC, 0x03, 0x3F, 0xFF, 0xF3, 0xF0, 0xF3,
|
||||||
|
0x27, 0x39, 0xF0, 0xCC, 0xB5, 0x0E, 0x3C, 0x73, 0xFE, 0x33, 0xCF, 0x3F,
|
||||||
|
0xFF, 0xC4, 0x33, 0x3F, 0xFF, 0xF3, 0xE4, 0xF3, 0xE7, 0x39, 0xF1, 0xCC,
|
||||||
|
0x4D, 0xCF, 0x3C, 0x73, 0xCE, 0x33, 0xCF, 0x3F, 0xFF, 0xCC, 0x33, 0x3F,
|
||||||
|
0x3F, 0xF3, 0xE4, 0xF3, 0xE7, 0x39, 0xF3, 0xCC, 0xFB, 0xCF, 0x3C, 0xF3,
|
||||||
|
0xC0, 0x13, 0xCF, 0x3C, 0xFF, 0xCC, 0x33, 0x3F, 0x3F, 0xF3, 0xCC, 0xF3,
|
||||||
|
0xE7, 0x39, 0xF3, 0xCC, 0x07, 0xCE, 0x3C, 0xF8, 0xE1, 0x83, 0x0F, 0x3C,
|
||||||
|
0xFF, 0xE1, 0x33, 0x1F, 0x7E, 0xF8, 0xCC, 0x03, 0xE7, 0x39, 0xF3, 0xE1,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0x1F, 0x3E, 0xF8,
|
||||||
|
0xE1, 0x03, 0xCF, 0x3C, 0x73, 0x9E, 0x39, 0xCF, 0x3C, 0xF0, 0xF1, 0xF3,
|
||||||
|
0x1F, 0xFF, 0xFC, 0xFF, 0x33, 0xCF, 0x3C, 0xF3, 0xDC, 0xCF, 0xCF, 0x3C,
|
||||||
|
0x73, 0x9E, 0x93, 0xCF, 0xFC, 0xF3, 0xF9, 0xF3, 0x3F, 0x7F, 0xF8, 0xFF,
|
||||||
|
0x33, 0xCF, 0x3C, 0xF3, 0xFC, 0xCF, 0xCF, 0x3C, 0x73, 0x9E, 0x93, 0x1F,
|
||||||
|
0xFE, 0xF9, 0xF9, 0xE7, 0x3F, 0x3F, 0xF3, 0xFF, 0x33, 0xCF, 0x3C, 0xF3,
|
||||||
|
0xE1, 0xCF, 0xCF, 0x3C, 0x73, 0x92, 0xC7, 0x1F, 0xFE, 0xFC, 0xF9, 0xE7,
|
||||||
|
0x3F, 0xFF, 0xFF, 0xFF, 0x83, 0xCF, 0x3C, 0xF8, 0xCF, 0xCF, 0xCF, 0x3C,
|
||||||
|
0x73, 0x92, 0xC7, 0x3F, 0x7F, 0xFE, 0xF9, 0xCF, 0x3F, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xF3, 0xCF, 0x3C, 0xF9, 0xCF, 0xCF, 0xCF, 0x3C, 0x73, 0x80, 0x93, 0x3F,
|
||||||
|
0x3F, 0xFF, 0xF9, 0xCF, 0x3F, 0xFF, 0xFF, 0xFF, 0xF3, 0xCF, 0x3C, 0xF3,
|
||||||
|
0xCC, 0xCF, 0xCF, 0x7C, 0x78, 0x80, 0x93, 0x3F, 0x3F, 0xF0, 0xF9, 0x9F,
|
||||||
|
0x3F, 0xFF, 0xFF, 0xFF, 0xF3, 0x1F, 0x3E, 0xF3, 0xE1, 0xCF, 0x1F, 0xFE,
|
||||||
|
0xFC, 0xCC, 0x39, 0x3F, 0x3F, 0xF0, 0xF9, 0x9F, 0x3F, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xF9, 0x3F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x3F,
|
||||||
|
0x1F, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F,
|
||||||
|
0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0x3F, 0xFF,
|
||||||
|
0xFF, 0x3F, 0xFF, 0xFF, 0xF8, 0xFF, 0xF3, 0x3F, 0xFF, 0xF9, 0xFC, 0xC7,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0x3F, 0xFF, 0xFF, 0x3F, 0xFF, 0x7F,
|
||||||
|
0xF8, 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xFC, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0x9F, 0x0F, 0x3F, 0xFF, 0xE1, 0x3F, 0x1F, 0x7E, 0xFE, 0xC0, 0x83, 0x1F,
|
||||||
|
0x7F, 0xF8, 0xCC, 0xCF, 0x07, 0x3C, 0xF8, 0xE1, 0xFF, 0x7F, 0x3E, 0xF8,
|
||||||
|
0xCC, 0x07, 0xCF, 0x7C, 0x7E, 0xE6, 0x33, 0x3F, 0xFF, 0xF9, 0xE4, 0xCF,
|
||||||
|
0x27, 0x39, 0xF3, 0xCC, 0xFF, 0x0F, 0x3E, 0xF3, 0xFC, 0x33, 0xCF, 0x3C,
|
||||||
|
0x7C, 0xE6, 0x33, 0x3F, 0xFF, 0xF9, 0xF0, 0xCF, 0x27, 0x39, 0xF3, 0xCC,
|
||||||
|
0xFF, 0x67, 0x3E, 0xF3, 0xFC, 0x33, 0x0F, 0x7C, 0xFE, 0xF0, 0x33, 0x3F,
|
||||||
|
0xFF, 0xF9, 0xF0, 0xCF, 0x27, 0x39, 0xF3, 0xCC, 0xFF, 0x67, 0x3E, 0xF3,
|
||||||
|
0xCC, 0x33, 0xCF, 0x7F, 0x7E, 0xFC, 0x33, 0x3F, 0xFF, 0xF9, 0xE4, 0xCF,
|
||||||
|
0x27, 0x39, 0xF3, 0xCC, 0xFF, 0x8F, 0x3C, 0xF8, 0xE1, 0x07, 0x1F, 0x7E,
|
||||||
|
0x7E, 0xF0, 0x33, 0x1F, 0xFE, 0xF9, 0xCC, 0x87, 0x27, 0x39, 0xF3, 0xE1,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xE6, 0xFF, 0xFF,
|
||||||
|
0x7F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xCF,
|
||||||
|
0x9F, 0xFF, 0x7F, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0xCF, 0x3F, 0xFF, 0x7F, 0x9E,
|
||||||
|
0x83, 0x1F, 0x7C, 0xF8, 0xC1, 0xE7, 0xCF, 0x3C, 0x73, 0x9E, 0x39, 0xCF,
|
||||||
|
0x3C, 0xF8, 0xF3, 0xCF, 0x3F, 0xFF, 0x7F, 0x9E, 0x33, 0xCF, 0x3C, 0xF6,
|
||||||
|
0xFC, 0x87, 0xCF, 0x3C, 0x73, 0x9E, 0x93, 0xCF, 0xFC, 0xF9, 0xF3, 0xCF,
|
||||||
|
0x3F, 0x3F, 0x66, 0x9E, 0x33, 0xCF, 0x3C, 0xFF, 0xE0, 0xE7, 0xCF, 0x3C,
|
||||||
|
0x73, 0x92, 0xC7, 0xCF, 0xFC, 0xFC, 0xF9, 0xCF, 0x7F, 0x9E, 0x64, 0x9E,
|
||||||
|
0x33, 0xCF, 0x3C, 0xFF, 0xC7, 0xE7, 0xCF, 0x3C, 0x73, 0x92, 0xC7, 0xCF,
|
||||||
|
0x7C, 0xFE, 0xF9, 0xCF, 0x7F, 0x9E, 0x71, 0x9E, 0x33, 0xCF, 0x3C, 0xFF,
|
||||||
|
0xC7, 0x87, 0xCF, 0x7C, 0x78, 0x80, 0x93, 0xCF, 0x3C, 0xFF, 0xF3, 0xCF,
|
||||||
|
0x3F, 0xFF, 0x7F, 0x9E, 0x83, 0x1F, 0x3C, 0xFF, 0xE0, 0x8F, 0x1F, 0xFC,
|
||||||
|
0xFC, 0xCC, 0x39, 0x1F, 0x3C, 0xF8, 0xF3, 0xCF, 0x3F, 0xFF, 0x7F, 0x9E,
|
||||||
|
0xF3, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFC, 0xFF, 0xF3, 0xCF, 0x3F, 0xFF, 0x7F, 0x9E, 0xF3, 0xFF, 0xFC, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFE, 0xFF, 0xE7, 0xCF,
|
||||||
|
0x9F, 0xFF, 0x7F, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x06, 0x18, 0x60,
|
||||||
|
0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01,
|
||||||
|
0x06, 0x18, 0x60, 0x80, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67,
|
||||||
|
0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79,
|
||||||
|
0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67,
|
||||||
|
0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79,
|
||||||
|
0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x01, 0x06, 0x18, 0x60,
|
||||||
|
0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01,
|
||||||
|
0x06, 0x18, 0x60, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x06, 0x18, 0x60,
|
||||||
|
0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01,
|
||||||
|
0x06, 0x18, 0x60, 0x80, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67,
|
||||||
|
0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79,
|
||||||
|
0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67,
|
||||||
|
0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79,
|
||||||
|
0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x01, 0x06, 0x18, 0x60,
|
||||||
|
0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01,
|
||||||
|
0x06, 0x18, 0x60, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x3E, 0xFF, 0xFB,
|
||||||
|
0xE3, 0xFF, 0xCF, 0xFC, 0xFC, 0xF3, 0x01, 0xFE, 0x1F, 0xE0, 0xFF, 0xFF,
|
||||||
|
0x07, 0xF8, 0x7F, 0x80, 0x79, 0x3E, 0x7F, 0xF0, 0xC9, 0xFD, 0xCE, 0xFC,
|
||||||
|
0xFC, 0xED, 0x79, 0x1E, 0x9E, 0xE7, 0xFF, 0xFF, 0xE7, 0x79, 0x78, 0x9E,
|
||||||
|
0x79, 0xFE, 0x3F, 0xE0, 0xF9, 0x4B, 0x1F, 0xFE, 0xFC, 0xFD, 0x79, 0xEE,
|
||||||
|
0x9D, 0xE7, 0x99, 0xFF, 0xE7, 0xB9, 0x77, 0x9E, 0x79, 0x3E, 0x9F, 0xE5,
|
||||||
|
0xFB, 0xB7, 0x1F, 0xFE, 0xFC, 0xFB, 0x79, 0x36, 0x9B, 0xE7, 0xCC, 0xFF,
|
||||||
|
0xE7, 0x59, 0x6C, 0x9E, 0x79, 0x3E, 0x9F, 0xFD, 0xE0, 0x7B, 0x3F, 0xFF,
|
||||||
|
0xFF, 0xF5, 0x79, 0xD6, 0x9B, 0x67, 0xE6, 0x01, 0xE6, 0x59, 0x6B, 0x9E,
|
||||||
|
0x79, 0x3E, 0x9F, 0xFE, 0xFB, 0x7B, 0x0F, 0xFC, 0xFF, 0xEB, 0x79, 0xD6,
|
||||||
|
0x9B, 0x67, 0xE6, 0x7F, 0xE6, 0x59, 0x6C, 0x9E, 0x79, 0x3E, 0x9F, 0xE6,
|
||||||
|
0xF8, 0xB7, 0x3F, 0xFF, 0xFC, 0xF7, 0x79, 0x36, 0x9B, 0xE7, 0xCC, 0x7F,
|
||||||
|
0xE6, 0x59, 0x6B, 0x9E, 0x79, 0x3E, 0x3F, 0x60, 0xB9, 0x4B, 0x0F, 0xFC,
|
||||||
|
0xFC, 0xEF, 0x79, 0xEE, 0x9D, 0xE7, 0x99, 0x7F, 0xE6, 0xB9, 0x77, 0x9E,
|
||||||
|
0x79, 0x3E, 0x7F, 0xF0, 0xC4, 0xFD, 0x3E, 0xFF, 0xFC, 0xED, 0x79, 0x1E,
|
||||||
|
0x9E, 0xE7, 0xFF, 0xFF, 0xE7, 0x79, 0x78, 0x9E, 0x01, 0xFE, 0x7F, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF3, 0x01, 0xFE, 0x1F, 0xE0, 0xFF, 0xFF,
|
||||||
|
0x07, 0xF8, 0x7F, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFC,
|
||||||
|
0xE3, 0x01, 0xFE, 0x7F, 0xE0, 0xFF, 0x01, 0x7E, 0x1F, 0xE0, 0xFF, 0xFB,
|
||||||
|
0xEF, 0x1F, 0xFF, 0xF3, 0xB7, 0xFF, 0xFF, 0xFB, 0xEF, 0x79, 0xFE, 0x3F,
|
||||||
|
0xF4, 0xFF, 0x79, 0x3E, 0x9F, 0xE7, 0xFF, 0xF9, 0xE6, 0x7B, 0xEF, 0xF3,
|
||||||
|
0xB7, 0x3F, 0xFF, 0xFD, 0xF7, 0x79, 0xCE, 0x3C, 0xF4, 0xFF, 0x79, 0x7E,
|
||||||
|
0x9F, 0x67, 0xE6, 0x7B, 0xEF, 0xBD, 0xF7, 0xFF, 0xCF, 0x3F, 0xFF, 0xFE,
|
||||||
|
0xEF, 0x79, 0xCE, 0x7C, 0xF4, 0xFF, 0x79, 0x7E, 0x9F, 0xE7, 0xCC, 0xBB,
|
||||||
|
0xEF, 0x7E, 0xFB, 0xF3, 0xFF, 0x0F, 0xFC, 0xF8, 0xF3, 0x79, 0xCE, 0xFC,
|
||||||
|
0xF4, 0xF3, 0x79, 0x3E, 0x9E, 0xE7, 0x99, 0xD1, 0x47, 0x9F, 0xFD, 0xF1,
|
||||||
|
0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x79, 0xCE, 0xFC, 0xF4, 0xF3, 0x79, 0xFE,
|
||||||
|
0x9F, 0xE7, 0x99, 0xAF, 0xBE, 0xFC, 0xEA, 0xF8, 0xFF, 0x3F, 0xFF, 0xFF,
|
||||||
|
0xFF, 0x79, 0xCE, 0xFC, 0xF4, 0xFF, 0x79, 0xFE, 0x9F, 0xE7, 0xCC, 0xB7,
|
||||||
|
0xDE, 0x7B, 0xEB, 0xDC, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x79, 0x2E, 0xFA,
|
||||||
|
0xF4, 0xFF, 0x79, 0xFE, 0x9F, 0x67, 0xE6, 0x3B, 0xEE, 0xBD, 0xE3, 0xCC,
|
||||||
|
0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x79, 0xEE, 0xFF, 0xFF, 0xFF, 0x79, 0xFE,
|
||||||
|
0x9F, 0xE7, 0xFF, 0xFD, 0xF6, 0xDE, 0xEF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0x01, 0xEE, 0xFF, 0xFF, 0xFF, 0x01, 0xFE, 0x1F, 0xE0, 0xFF, 0xFF,
|
||||||
|
0xFE, 0xF8, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x06, 0x18, 0x60,
|
||||||
|
0x80, 0x01, 0x06, 0x18, 0xE0, 0xFF, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01,
|
||||||
|
0x06, 0x18, 0x60, 0x80, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0xE7, 0xFF, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0xE7, 0xDE, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67,
|
||||||
|
0x9E, 0x79, 0xE6, 0x99, 0xE7, 0xED, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79,
|
||||||
|
0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0xE7, 0xF3, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0xE7, 0xF3, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67,
|
||||||
|
0x9E, 0x79, 0xE6, 0x99, 0xE7, 0xED, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79,
|
||||||
|
0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0xE7, 0xDE, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0xE7, 0xFF, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x01, 0x06, 0x18, 0x60,
|
||||||
|
0x80, 0x01, 0x06, 0x18, 0xE0, 0xFF, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01,
|
||||||
|
0x06, 0x18, 0x60, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x06, 0x18, 0x60,
|
||||||
|
0x80, 0x01, 0x06, 0x18, 0xE0, 0xFF, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01,
|
||||||
|
0x06, 0x18, 0x60, 0x80, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0xE7, 0xF3, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0xE7, 0xF3, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67,
|
||||||
|
0x9E, 0x79, 0xE6, 0x99, 0xE7, 0xFF, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79,
|
||||||
|
0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0xE7, 0xC0, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0xE7, 0xFF, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67,
|
||||||
|
0x9E, 0x79, 0xE6, 0x99, 0xE7, 0xF3, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79,
|
||||||
|
0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0xE7, 0xF3, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0xE7, 0xFF, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x01, 0x06, 0x18, 0x60,
|
||||||
|
0x80, 0x01, 0x06, 0x18, 0xE0, 0xFF, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01,
|
||||||
|
0x06, 0x18, 0x60, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x06, 0x18, 0x60,
|
||||||
|
0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01,
|
||||||
|
0x06, 0x18, 0x60, 0x80, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67,
|
||||||
|
0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79,
|
||||||
|
0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67,
|
||||||
|
0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79,
|
||||||
|
0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x01, 0x06, 0x18, 0x60,
|
||||||
|
0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01,
|
||||||
|
0x06, 0x18, 0x60, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x06, 0x18, 0x60,
|
||||||
|
0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01,
|
||||||
|
0x06, 0x18, 0x60, 0x80, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67,
|
||||||
|
0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79,
|
||||||
|
0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67,
|
||||||
|
0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79,
|
||||||
|
0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99,
|
||||||
|
0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E,
|
||||||
|
0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x79, 0xE6,
|
||||||
|
0x99, 0x67, 0x9E, 0x79, 0xE6, 0x99, 0x67, 0x9E, 0x01, 0x06, 0x18, 0x60,
|
||||||
|
0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01, 0x06, 0x18, 0x60, 0x80, 0x01,
|
||||||
|
0x06, 0x18, 0x60, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
};
|
||||||
293
main.c
293
main.c
@@ -1,231 +1,116 @@
|
|||||||
// main.c
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
#include "hardware/clocks.h"
|
#include "pico/multicore.h"
|
||||||
#include "hardware/dma.h"
|
|
||||||
#include "hardware/irq.h"
|
|
||||||
#include "hardware/pio.h"
|
|
||||||
|
|
||||||
#include "video_dma.pio.h"
|
#include "cvideo.h"
|
||||||
|
|
||||||
// ---------------------------
|
#include "font.xbm"
|
||||||
// User-adjustable pins
|
|
||||||
// ---------------------------
|
|
||||||
#define VIDEO_PIO pio0
|
|
||||||
#define DATA_SM 0
|
|
||||||
#define SYNC_SM 1
|
|
||||||
|
|
||||||
#define DATA_PIN 2 // pixel / luma bit pin
|
static video_framebuffer_t fb0, fb1;
|
||||||
#define SYNC_PIN 3 // sync pin
|
|
||||||
|
|
||||||
// ---------------------------
|
#define START_X 35
|
||||||
// Video format
|
#define END_X (VIDEO_WIDTH-40)
|
||||||
// ---------------------------
|
#define START_Y 20
|
||||||
#define VIDEO_WIDTH 768
|
#define END_Y (VIDEO_HEIGHT-40)
|
||||||
#define VIDEO_HEIGHT 576
|
|
||||||
#define WORDS_PER_LINE (VIDEO_WIDTH / 32)
|
|
||||||
#define LINES_PER_FIELD (VIDEO_HEIGHT / 2)
|
|
||||||
|
|
||||||
#define SYNC_INTERVAL_S 0.000002f // 2 us per sync-SM instruction
|
#define CHARS_PER_LINE 32
|
||||||
#define ACTIVE_VIDEO_S 0.000052f // 52 us active video per line
|
#define CHAR_LINES 20
|
||||||
|
|
||||||
// Match the .pio program's published constant.
|
static char text_mode_buffer[20][32];
|
||||||
// pioasm will emit CLOCKS_PER_BIT in the generated header.
|
|
||||||
#ifndef CLOCKS_PER_BIT
|
|
||||||
#define CLOCKS_PER_BIT 6
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ---------------------------
|
static void clear(video_framebuffer_t fb){
|
||||||
// Framebuffer
|
memset(fb, 0, sizeof(video_framebuffer_t));
|
||||||
// One bit per pixel, 32 pixels per word
|
}
|
||||||
// ---------------------------
|
|
||||||
static uint32_t framebuffer[VIDEO_HEIGHT][WORDS_PER_LINE];
|
|
||||||
|
|
||||||
// Field/line tracking for line-based DMA.
|
static void set_bit(video_framebuffer_t fb, uint x, uint y, bool value) {
|
||||||
// This is intentionally kept in software to match the sync SM's 288 active
|
if(x>=VIDEO_WIDTH || y>=VIDEO_HEIGHT)
|
||||||
// lines per field.
|
return;
|
||||||
static volatile bool even_field = true;
|
uint index_x = x / 32;
|
||||||
static volatile uint line_in_field = 0;
|
uint pos_x = x % 32;
|
||||||
|
|
||||||
// DMA channel that feeds the PIO TX FIFO
|
uint flag = value << (31-pos_x);
|
||||||
static int video_dma_chan;
|
if(value)
|
||||||
|
fb[y][index_x] |= flag;
|
||||||
|
else
|
||||||
|
fb[y][index_x] &= ~flag;
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------
|
#define CHAR_WIDTH font_width / 16
|
||||||
// Optional test pattern
|
#define CHAR_HEIGHT font_height / 16
|
||||||
// Replace this with your own drawing code.
|
|
||||||
// ---------------------------
|
|
||||||
#define BORDER 40
|
|
||||||
static void fill_test_pattern(void) {
|
|
||||||
memset(framebuffer, 0x00, sizeof(framebuffer));
|
|
||||||
|
|
||||||
for (uint y = 0; y < VIDEO_HEIGHT; ++y) {
|
void draw_character(video_framebuffer_t fb, unsigned int x, unsigned int y, unsigned int scale, char character) {
|
||||||
for (uint x = 0; x < VIDEO_WIDTH; ++x) {
|
uint8_t row = character / 16;
|
||||||
bool on = false;
|
uint8_t column = character % 16;
|
||||||
|
uint32_t font_x = column * 10;
|
||||||
|
uint32_t font_y = row * 12;
|
||||||
|
|
||||||
// Simple visible pattern:
|
for (int j = font_y; j < font_y + CHAR_HEIGHT; j++) {
|
||||||
// border + checker
|
for (int i = font_x; i < font_x + CHAR_WIDTH; i++) {
|
||||||
if (x < BORDER || x >= VIDEO_WIDTH - BORDER || y < BORDER || y >= VIDEO_HEIGHT - BORDER) {
|
// XBM images pad rows with zeros
|
||||||
on = true;
|
uint32_t array_position;
|
||||||
} else if (((x >> 4) ^ (y >> 4)) & 1) {
|
if (font_width %8 != 0) {
|
||||||
on = true;
|
array_position = (j * (font_width + (8 - font_width % 8))) + i;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
array_position = (j * font_width) + i;
|
||||||
|
}
|
||||||
|
uint32_t array_index = array_position / 8;
|
||||||
|
// XBM image, low bits are first
|
||||||
|
uint32_t byte_position = array_position % 8;
|
||||||
|
|
||||||
if (on) {
|
uint8_t value = font_bits[array_index] >> byte_position & 1 ;
|
||||||
uint word = x >> 5;
|
|
||||||
uint bit = 31 - (x & 31); // MSB-first
|
for (int sx = 0; sx < scale; sx++) {
|
||||||
framebuffer[y][word] |= (1u << bit);
|
for (int sy = 0; sy < scale; sy++) {
|
||||||
|
set_bit(fb, x + ((i - font_x) * scale) + sx, y + ((j- font_y) * scale) + sy, !value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------
|
void core1_entry() {
|
||||||
// PIO init helpers
|
gpio_init(25);
|
||||||
// ---------------------------
|
gpio_set_dir(25, GPIO_OUT);
|
||||||
static void init_cvdata_program(PIO pio, uint sm, uint offset, float clkdiv, uint data_pin) {
|
|
||||||
pio_sm_config c = cvdata_program_get_default_config(offset);
|
|
||||||
|
|
||||||
sm_config_set_set_pins(&c, data_pin, 1);
|
|
||||||
sm_config_set_out_pins(&c, data_pin, 1);
|
|
||||||
sm_config_set_clkdiv(&c, clkdiv);
|
|
||||||
|
|
||||||
// Shift left, autopull every 32 bits.
|
|
||||||
// If the image is mirrored, change this to shift-right and/or change bit packing.
|
|
||||||
sm_config_set_out_shift(&c, false, true, 32);
|
|
||||||
|
|
||||||
pio_gpio_init(pio, data_pin);
|
|
||||||
pio_sm_set_consecutive_pindirs(pio, sm, data_pin, 1, true);
|
|
||||||
|
|
||||||
pio_sm_init(pio, sm, offset, &c);
|
|
||||||
|
|
||||||
// Preload X = VIDEO_WIDTH - 1
|
|
||||||
pio_sm_put_blocking(pio, sm, VIDEO_WIDTH - 1);
|
|
||||||
pio_sm_exec(pio, sm, pio_encode_pull(false, false));
|
|
||||||
pio_sm_exec(pio, sm, pio_encode_mov(pio_x, pio_osr));
|
|
||||||
pio_sm_exec(pio, sm, pio_encode_out(pio_null, 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void init_cvsync_program(PIO pio, uint sm, uint offset, float clkdiv, uint sync_pin) {
|
|
||||||
pio_sm_config c = cvsync_program_get_default_config(offset);
|
|
||||||
|
|
||||||
sm_config_set_sideset_pins(&c, sync_pin);
|
|
||||||
sm_config_set_clkdiv(&c, clkdiv);
|
|
||||||
|
|
||||||
pio_gpio_init(pio, sync_pin);
|
|
||||||
pio_sm_set_consecutive_pindirs(pio, sm, sync_pin, 1, true);
|
|
||||||
|
|
||||||
pio_sm_init(pio, sm, offset, &c);
|
|
||||||
|
|
||||||
// Preload OSR = lines_per_field - 1
|
|
||||||
pio_sm_put_blocking(pio, sm, LINES_PER_FIELD - 1);
|
|
||||||
pio_sm_exec(pio, sm, pio_encode_pull(false, false));
|
|
||||||
|
|
||||||
// Start with Y = 0, meaning "even field" in this program.
|
|
||||||
pio_sm_exec(pio, sm, pio_encode_set(pio_y, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------
|
|
||||||
// DMA setup
|
|
||||||
// ---------------------------
|
|
||||||
static void init_video_dma(PIO pio, uint data_sm) {
|
|
||||||
video_dma_chan = dma_claim_unused_channel(true);
|
|
||||||
|
|
||||||
dma_channel_config cfg = dma_channel_get_default_config(video_dma_chan);
|
|
||||||
channel_config_set_transfer_data_size(&cfg, DMA_SIZE_32);
|
|
||||||
channel_config_set_read_increment(&cfg, true);
|
|
||||||
channel_config_set_write_increment(&cfg, false);
|
|
||||||
|
|
||||||
// Pace the DMA from the data SM TX FIFO DREQ
|
|
||||||
channel_config_set_dreq(&cfg, pio_get_dreq(pio, data_sm, true));
|
|
||||||
|
|
||||||
dma_channel_configure(
|
|
||||||
video_dma_chan,
|
|
||||||
&cfg,
|
|
||||||
&pio->txf[data_sm], // write address
|
|
||||||
NULL, // read address set per line
|
|
||||||
0, // transfer count set per line
|
|
||||||
false // don't start yet
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------
|
|
||||||
// Start DMA for one scanline
|
|
||||||
// ---------------------------
|
|
||||||
static inline void start_dma_for_current_line(void) {
|
|
||||||
uint src_line = even_field ? (line_in_field * 2u) : (line_in_field * 2u + 1u);
|
|
||||||
|
|
||||||
dma_channel_set_read_addr(video_dma_chan, framebuffer[src_line], false);
|
|
||||||
dma_channel_set_trans_count(video_dma_chan, WORDS_PER_LINE, true);
|
|
||||||
|
|
||||||
line_in_field++;
|
|
||||||
if (line_in_field >= LINES_PER_FIELD) {
|
|
||||||
line_in_field = 0;
|
|
||||||
even_field = !even_field;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------
|
|
||||||
// PIO IRQ handler:
|
|
||||||
// The sync SM pushes one token into its RX FIFO during each line's back porch.
|
|
||||||
// As soon as the previous line DMA has finished, consume one token and arm the
|
|
||||||
// next scanline so the data FIFO is primed before visible pixels start.
|
|
||||||
// ---------------------------
|
|
||||||
static void pio0_irq0_handler(void) {
|
|
||||||
if (!pio_sm_is_rx_fifo_empty(VIDEO_PIO, SYNC_SM) && !dma_channel_is_busy(video_dma_chan)) {
|
|
||||||
(void)pio_sm_get(VIDEO_PIO, SYNC_SM);
|
|
||||||
start_dma_for_current_line();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------
|
|
||||||
// Video start
|
|
||||||
// ---------------------------
|
|
||||||
static void video_init(void) {
|
|
||||||
if ((VIDEO_WIDTH % 32) != 0) {
|
|
||||||
panic("VIDEO_WIDTH must be a multiple of 32");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint sync_offset = pio_add_program(VIDEO_PIO, &cvsync_program);
|
|
||||||
uint data_offset = pio_add_program(VIDEO_PIO, &cvdata_program);
|
|
||||||
|
|
||||||
// Same timing idea as the original repo:
|
|
||||||
// sync SM: 1 instruction every 2 us
|
|
||||||
// data SM: enough PIO cycles to emit VIDEO_WIDTH bits in 52 us
|
|
||||||
float sys_hz = (float)clock_get_hz(clk_sys);
|
|
||||||
float data_clkdiv = (sys_hz / ((float)VIDEO_WIDTH / ACTIVE_VIDEO_S)) / (float)CLOCKS_PER_BIT;
|
|
||||||
float sync_clkdiv = sys_hz * SYNC_INTERVAL_S;
|
|
||||||
|
|
||||||
init_cvdata_program(VIDEO_PIO, DATA_SM, data_offset, data_clkdiv, DATA_PIN);
|
|
||||||
init_cvsync_program(VIDEO_PIO, SYNC_SM, sync_offset, sync_clkdiv, SYNC_PIN);
|
|
||||||
init_video_dma(VIDEO_PIO, DATA_SM);
|
|
||||||
|
|
||||||
// Route sync-SM RX FIFO notifications to CPU IRQ 0.
|
|
||||||
pio_set_irq0_source_enabled(VIDEO_PIO, pis_sm1_rx_fifo_not_empty, true);
|
|
||||||
irq_set_exclusive_handler(PIO0_IRQ_0, pio0_irq0_handler);
|
|
||||||
irq_set_enabled(PIO0_IRQ_0, true);
|
|
||||||
|
|
||||||
// Start with the first line of the even field
|
|
||||||
even_field = true;
|
|
||||||
line_in_field = 0;
|
|
||||||
|
|
||||||
// Prime the FIFO so the very first active line does not depend on IRQ latency.
|
|
||||||
start_dma_for_current_line();
|
|
||||||
|
|
||||||
pio_sm_set_enabled(VIDEO_PIO, DATA_SM, true);
|
|
||||||
pio_sm_set_enabled(VIDEO_PIO, SYNC_SM, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
stdio_init_all();
|
|
||||||
|
|
||||||
fill_test_pattern(); // Replace with your own framebuffer writer
|
|
||||||
video_init();
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
// Your application code goes here.
|
gpio_put(25, 1);
|
||||||
// Some other code can freely draw into framebuffer[].
|
sleep_ms(500);
|
||||||
|
gpio_put(25, 0);
|
||||||
|
sleep_ms(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void framebuffer_switched_cb(){
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
stdio_init_all();
|
||||||
|
multicore_launch_core1(core1_entry);
|
||||||
|
|
||||||
|
clear(fb0);
|
||||||
|
clear(fb1);
|
||||||
|
video_init(fb0);
|
||||||
|
video_set_framebuffer_switched_cb(framebuffer_switched_cb);
|
||||||
|
|
||||||
|
int fbnum = 1;
|
||||||
|
video_framebuffer_ptr_t fbs[] = {fb0, fb1};
|
||||||
|
int i = 0;
|
||||||
|
while (true) {
|
||||||
|
clear(fbs[fbnum]);
|
||||||
|
for(int y=0; y<20; y++){
|
||||||
|
for(int x=0; x<32; x++){
|
||||||
|
draw_character(fbs[fbnum], START_X+x*(CHAR_WIDTH+1)*2, START_Y+y*(CHAR_HEIGHT+1)*2, 2, '0'+(i+x+y)%10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
video_set_framebuffer(fbs[fbnum]);
|
||||||
|
fbnum = (fbnum+1)%2;
|
||||||
|
i = (i+1)%10;
|
||||||
|
sleep_ms(500);
|
||||||
|
|
||||||
tight_loop_contents();
|
tight_loop_contents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
.define DATA_DELAY 4
|
.define DATA_DELAY 4
|
||||||
.define LINE_IRQ 0
|
.define LINE_IRQ 0
|
||||||
|
.define HSHIFT_DELAY 0
|
||||||
.define PUBLIC CLOCKS_PER_BIT DATA_DELAY + 2
|
.define PUBLIC CLOCKS_PER_BIT DATA_DELAY + 2
|
||||||
|
|
||||||
.program cvsync
|
.program cvsync
|
||||||
@@ -85,15 +86,16 @@ hsync_video:
|
|||||||
; X = pixels_per_line - 1, preloaded once from C
|
; X = pixels_per_line - 1, preloaded once from C
|
||||||
; Each line:
|
; Each line:
|
||||||
; clear output
|
; clear output
|
||||||
; reload Y from X
|
|
||||||
; wait for sync SM to raise LINE_IRQ
|
; wait for sync SM to raise LINE_IRQ
|
||||||
|
; apply a small extra delay for horizontal positioning
|
||||||
|
; reload Y from X
|
||||||
; shift out one bit per loop
|
; shift out one bit per loop
|
||||||
|
|
||||||
.wrap_target
|
.wrap_target
|
||||||
set pins, 0
|
set pins, 0
|
||||||
mov y, x
|
|
||||||
wait 1 irq LINE_IRQ
|
wait 1 irq LINE_IRQ
|
||||||
irq clear LINE_IRQ
|
irq clear LINE_IRQ
|
||||||
|
mov y, x
|
||||||
|
|
||||||
data_out:
|
data_out:
|
||||||
out pins, 1 [DATA_DELAY]
|
out pins, 1 [DATA_DELAY]
|
||||||
|
|||||||
Reference in New Issue
Block a user