Add SD card menu
This commit is contained in:
@@ -12,7 +12,6 @@ add_subdirectory(ext/FatFs_SPI build)
|
|||||||
|
|
||||||
add_executable(RP2040_GB
|
add_executable(RP2040_GB
|
||||||
src/main.c
|
src/main.c
|
||||||
src/rom.c
|
|
||||||
src/mk_ili9225.c
|
src/mk_ili9225.c
|
||||||
ext/minigb_apu/minigb_apu.c
|
ext/minigb_apu/minigb_apu.c
|
||||||
ext/i2s/i2s.c
|
ext/i2s/i2s.c
|
||||||
|
|||||||
@@ -665,6 +665,17 @@ void auto_assign_palette(uint16_t palette[3][4], uint8_t game_checksum, const ch
|
|||||||
}
|
}
|
||||||
case 0x16:
|
case 0x16:
|
||||||
{
|
{
|
||||||
|
if(disambiguation_character=='M') {
|
||||||
|
/* CUSTOM */
|
||||||
|
/* Batman - The Animated Series (USA, Europe) */
|
||||||
|
get_colour_palette(palette,0x0D,0x05);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
/* Donkey Kong Land (Japan) */
|
||||||
|
get_colour_palette(palette,0x0C,0x05);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Yakuman (Japan);; Yakuman (Japan) (Rev A) */
|
/* Yakuman (Japan);; Yakuman (Japan) (Rev A) */
|
||||||
get_colour_palette(palette,0x12,0x00);
|
get_colour_palette(palette,0x12,0x00);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#define SCREEN_SIZE_X 176u
|
#define SCREEN_SIZE_X 176u
|
||||||
#define SCREEN_SIZE_Y 220u
|
#define SCREEN_SIZE_Y 220u
|
||||||
@@ -141,3 +142,34 @@ void mk_ili9225_set_x(uint8_t x);
|
|||||||
* Exit and stop using LCD. Currently does nothing.
|
* Exit and stop using LCD. Currently does nothing.
|
||||||
*/
|
*/
|
||||||
void mk_ili9225_exit(void);
|
void mk_ili9225_exit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill a rectangle at the given location, size and color.
|
||||||
|
*/
|
||||||
|
void mk_ili9225_fill_rect(uint8_t x,uint8_t y,uint8_t w,uint8_t h,uint16_t color);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill the entire screen with the specified RGB565 color
|
||||||
|
*/
|
||||||
|
void mk_ili9225_fill(uint16_t color);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a specified pixel to the given color
|
||||||
|
*/
|
||||||
|
void mk_ili9225_pixel(uint8_t x,uint8_t y,uint16_t color);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the specified framebuffer at the given coordinates
|
||||||
|
*/
|
||||||
|
void mk_ili9225_blit(uint16_t *fbuf,uint8_t x,uint8_t y,uint8_t w,uint8_t h);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an 8x8 framebuffer for the given letter and color / background color
|
||||||
|
*/
|
||||||
|
void mk_ili9225_get_letter(uint16_t *fbuf,char letter,uint16_t color,uint16_t bgcolor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write text to the screen using the the coordinates as the upper-left corner of the text.
|
||||||
|
* All characters have dimensions of 8x8 pixels.
|
||||||
|
*/
|
||||||
|
void mk_ili9225_text(char *s,uint8_t x,uint8_t y,uint16_t color,uint16_t bgcolor);
|
||||||
|
|||||||
+267
-224
@@ -46,6 +46,7 @@
|
|||||||
#include <hardware/dma.h>
|
#include <hardware/dma.h>
|
||||||
#include <hardware/spi.h>
|
#include <hardware/spi.h>
|
||||||
#include <hardware/sync.h>
|
#include <hardware/sync.h>
|
||||||
|
#include <hardware/flash.h>
|
||||||
#include <hardware/timer.h>
|
#include <hardware/timer.h>
|
||||||
#include <hardware/vreg.h>
|
#include <hardware/vreg.h>
|
||||||
#include <pico/bootrom.h>
|
#include <pico/bootrom.h>
|
||||||
@@ -81,27 +82,29 @@
|
|||||||
#define GPIO_LED 22
|
#define GPIO_LED 22
|
||||||
|
|
||||||
#if ENABLE_SOUND
|
#if ENABLE_SOUND
|
||||||
// Global variables for audio task
|
/**
|
||||||
// stream contains N=AUDIO_SAMPLES samples
|
* Global variables for audio task
|
||||||
// each sample is 32 bits
|
* stream contains N=AUDIO_SAMPLES samples
|
||||||
// (16 bits for the left channel + 16 bits for the right channel in stereo interleaved format)
|
* each sample is 32 bits
|
||||||
// This is intended to be played at AUDIO_SAMPLE_RATE Hz
|
* 16 bits for the left channel + 16 bits for the right channel in stereo interleaved format)
|
||||||
uint16_t *stream;
|
* This is intended to be played at AUDIO_SAMPLE_RATE Hz
|
||||||
|
*/
|
||||||
|
uint16_t *stream;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* DMA channel for LCD communication. */
|
/** Definition of ROM data
|
||||||
static uint dma_lcd;
|
* We're going to erase and reprogram a region 1Mb from the start of the flash
|
||||||
/* Definition of ROM data variable. Must be declared like:
|
* Once done, we can access this at XIP_BASE + 1Mb.
|
||||||
* #include <pico/platform.h>
|
* Game Boy DMG ROM size ranges from 32768 bytes (e.g. Tetris) to 1,048,576 bytes (e.g. Pokemod Red)
|
||||||
* const unsigned char __in_flash("rom") rom[] = {
|
|
||||||
* ...
|
|
||||||
* };
|
|
||||||
*/
|
*/
|
||||||
extern const unsigned char rom[];
|
#define FLASH_TARGET_OFFSET (1024 * 1024)
|
||||||
unsigned char rom_bank0[16384];
|
const uint8_t *rom = (const uint8_t *) (XIP_BASE + FLASH_TARGET_OFFSET);
|
||||||
|
static unsigned char rom_bank0[65536];
|
||||||
|
|
||||||
static uint8_t ram[32768];
|
static uint8_t ram[32768];
|
||||||
static int lcd_line_busy = 0;
|
static int lcd_line_busy = 0;
|
||||||
static palette_t palette; // Colour palette
|
static palette_t palette; // Colour palette
|
||||||
|
static uint8_t manual_palette_selected=0;
|
||||||
|
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
@@ -134,12 +137,6 @@ union core_cmd {
|
|||||||
uint32_t full;
|
uint32_t full;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gb_priv {
|
|
||||||
uint32_t lcd_line_hashes[LCD_HEIGHT];
|
|
||||||
uint dma_pixel_buffer_chan;
|
|
||||||
};
|
|
||||||
static struct gb_priv gb_priv = { 0 };
|
|
||||||
|
|
||||||
/* Pixel data is stored in here. */
|
/* Pixel data is stored in here. */
|
||||||
static uint8_t pixels_buffer[LCD_WIDTH];
|
static uint8_t pixels_buffer[LCD_WIDTH];
|
||||||
|
|
||||||
@@ -223,95 +220,35 @@ void gb_error(struct gb_s *gb, const enum gb_error_e gb_err, const uint16_t addr
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void core1_irq_dma_lcd_end_transfer(void)
|
|
||||||
{
|
|
||||||
mk_ili9225_write_pixels_end();
|
|
||||||
__atomic_store_n(&lcd_line_busy, 0, __ATOMIC_SEQ_CST);
|
|
||||||
dma_channel_acknowledge_irq0(dma_lcd);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if ENABLE_LCD
|
#if ENABLE_LCD
|
||||||
void core1_lcd_draw_line(const uint_fast8_t line)
|
void core1_lcd_draw_line(const uint_fast8_t line)
|
||||||
{
|
{
|
||||||
static uint16_t fb[LCD_WIDTH];
|
static uint16_t fb[LCD_WIDTH];
|
||||||
|
|
||||||
//dma_channel_wait_for_finish_blocking(dma_lcd);
|
|
||||||
for(unsigned int x = 0; x < LCD_WIDTH; x++)
|
for(unsigned int x = 0; x < LCD_WIDTH; x++)
|
||||||
{
|
{
|
||||||
fb[x] = palette[(pixels_buffer[x] & LCD_PALETTE_ALL) >> 4]
|
fb[x] = palette[(pixels_buffer[x] & LCD_PALETTE_ALL) >> 4]
|
||||||
[pixels_buffer[x] & 3];
|
[pixels_buffer[x] & 3];
|
||||||
}
|
}
|
||||||
|
|
||||||
//mk_ili9225_set_address(line + 16, LCD_WIDTH + 30);
|
|
||||||
mk_ili9225_set_x(line + 16);
|
mk_ili9225_set_x(line + 16);
|
||||||
|
|
||||||
#if USE_DMA
|
|
||||||
mk_ili9225_write_pixels_start();
|
|
||||||
dma_channel_transfer_from_buffer_now(dma_lcd, &fb[0], LCD_WIDTH);
|
|
||||||
do {
|
|
||||||
__wfi();
|
|
||||||
} while (dma_channel_is_busy(dma_lcd));
|
|
||||||
__compiler_memory_barrier();
|
|
||||||
#else
|
|
||||||
mk_ili9225_write_pixels(fb, LCD_WIDTH);
|
mk_ili9225_write_pixels(fb, LCD_WIDTH);
|
||||||
__atomic_store_n(&lcd_line_busy, 0, __ATOMIC_SEQ_CST);
|
__atomic_store_n(&lcd_line_busy, 0, __ATOMIC_SEQ_CST);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_Noreturn
|
_Noreturn
|
||||||
void main_core1(void)
|
void main_core1(void)
|
||||||
{
|
{
|
||||||
static dma_channel_config c2;
|
|
||||||
uint16_t clear_screen_colour = palette[2][3];
|
|
||||||
union core_cmd cmd;
|
union core_cmd cmd;
|
||||||
|
|
||||||
/* Initialise and control LCD on core 1. */
|
/* Initialise and control LCD on core 1. */
|
||||||
mk_ili9225_init();
|
mk_ili9225_init();
|
||||||
|
|
||||||
/* Initilise DMA transfer for clearing the LCD screen. */
|
|
||||||
dma_lcd = dma_claim_unused_channel(true);
|
|
||||||
c2 = dma_channel_get_default_config(dma_lcd);
|
|
||||||
channel_config_set_transfer_data_size(&c2, DMA_SIZE_16);
|
|
||||||
channel_config_set_dreq(&c2,DREQ_SPI0_TX);
|
|
||||||
channel_config_set_read_increment(&c2, false);
|
|
||||||
channel_config_set_write_increment(&c2, false);
|
|
||||||
channel_config_set_ring(&c2, false, 0);
|
|
||||||
|
|
||||||
/* Enable IRQ for wake on interrupt functionality. */
|
|
||||||
/* Use DMA_IRQ_1, DMA_IRQ_0 is already used by the SD Card reader */
|
|
||||||
irq_set_exclusive_handler(DMA_IRQ_1, core1_irq_dma_lcd_end_transfer);
|
|
||||||
dma_channel_set_irq1_enabled(dma_lcd, true);
|
|
||||||
irq_set_enabled(DMA_IRQ_1, true);
|
|
||||||
|
|
||||||
/* Clear LCD screen. */
|
/* Clear LCD screen. */
|
||||||
mk_ili9225_write_pixels_start();
|
mk_ili9225_fill(0x0000);
|
||||||
dma_channel_configure(dma_lcd, &c2, &spi_get_hw(spi0)->dr, &clear_screen_colour,
|
|
||||||
SCREEN_SIZE_X*SCREEN_SIZE_Y+16, true);
|
|
||||||
do {
|
|
||||||
__wfi();
|
|
||||||
} while (dma_channel_is_busy(dma_lcd));
|
|
||||||
__compiler_memory_barrier();
|
|
||||||
|
|
||||||
/* Set DMA transfer to be the length of a DMG line. */
|
|
||||||
dma_channel_set_trans_count(dma_lcd, LCD_WIDTH, false);
|
|
||||||
channel_config_set_read_increment(&c2, true);
|
|
||||||
//dma_sniffer_enable(dma_lcd, 0, true);
|
|
||||||
|
|
||||||
/* Set LCD window to DMG size. */
|
/* Set LCD window to DMG size. */
|
||||||
mk_ili9225_set_window(16, LCD_HEIGHT + 15,
|
mk_ili9225_fill_rect(31,16,LCD_WIDTH,LCD_HEIGHT,0x0000);
|
||||||
31, LCD_WIDTH + 30);
|
|
||||||
mk_ili9225_set_address(16, LCD_WIDTH + 30);
|
|
||||||
//mk_ili9225_set_x(15);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Clear GB Screen window. */
|
|
||||||
mk_ili9225_write_pixels_start();
|
|
||||||
dma_channel_set_trans_count(dma_lcd, LCD_HEIGHT*LCD_WIDTH+16, false);
|
|
||||||
dma_channel_set_read_addr(dma_lcd, &green, true);
|
|
||||||
/* TODO: Add sleeping wait. */
|
|
||||||
dma_channel_wait_for_finish_blocking(dma_lcd);
|
|
||||||
mk_ili9225_write_pixels_end();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Sleep used for debugging LCD window.
|
// Sleep used for debugging LCD window.
|
||||||
//sleep_ms(1000);
|
//sleep_ms(1000);
|
||||||
@@ -350,18 +287,8 @@ void lcd_draw_line(struct gb_s *gb, const uint8_t pixels[LCD_WIDTH],
|
|||||||
while(__atomic_load_n(&lcd_line_busy, __ATOMIC_SEQ_CST))
|
while(__atomic_load_n(&lcd_line_busy, __ATOMIC_SEQ_CST))
|
||||||
tight_loop_contents();
|
tight_loop_contents();
|
||||||
|
|
||||||
//memcpy(pixels_buffer, pixels, LCD_WIDTH);
|
memcpy(pixels_buffer, pixels, LCD_WIDTH);
|
||||||
dma_hw->sniff_data = 0;
|
|
||||||
//line_to_copy = line;
|
|
||||||
dma_channel_set_read_addr(gb_priv.dma_pixel_buffer_chan, pixels, false);
|
|
||||||
dma_channel_set_write_addr(gb_priv.dma_pixel_buffer_chan, pixels_buffer, true);
|
|
||||||
dma_channel_wait_for_finish_blocking(gb_priv.dma_pixel_buffer_chan);
|
|
||||||
|
|
||||||
if(gb_priv.lcd_line_hashes[line] == dma_hw->sniff_data)
|
|
||||||
return;
|
|
||||||
|
|
||||||
gb_priv.lcd_line_hashes[line] = dma_hw->sniff_data;
|
|
||||||
|
|
||||||
/* Populate command. */
|
/* Populate command. */
|
||||||
cmd.cmd = CORE_CMD_LCD_LINE;
|
cmd.cmd = CORE_CMD_LCD_LINE;
|
||||||
cmd.data = line;
|
cmd.data = line;
|
||||||
@@ -372,11 +299,13 @@ void lcd_draw_line(struct gb_s *gb, const uint8_t pixels[LCD_WIDTH],
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ENABLE_SDCARD
|
#if ENABLE_SDCARD
|
||||||
|
/**
|
||||||
|
* Load a save file from the SD card
|
||||||
|
*/
|
||||||
void read_cart_ram_file(struct gb_s *gb) {
|
void read_cart_ram_file(struct gb_s *gb) {
|
||||||
/* Load Save File. */
|
|
||||||
char filename[16];
|
char filename[16];
|
||||||
uint_fast32_t save_size;
|
uint_fast32_t save_size;
|
||||||
UINT bw;
|
UINT br;
|
||||||
|
|
||||||
gb_get_rom_name(gb,filename);
|
gb_get_rom_name(gb,filename);
|
||||||
save_size=gb_get_save_size(gb);
|
save_size=gb_get_save_size(gb);
|
||||||
@@ -391,7 +320,7 @@ void read_cart_ram_file(struct gb_s *gb) {
|
|||||||
FIL fil;
|
FIL fil;
|
||||||
fr=f_open(&fil,filename,FA_READ);
|
fr=f_open(&fil,filename,FA_READ);
|
||||||
if (fr==FR_OK) {
|
if (fr==FR_OK) {
|
||||||
f_read(&fil,ram,save_size,&bw);
|
f_read(&fil,ram,f_size(&fil),&br);
|
||||||
} else {
|
} else {
|
||||||
printf("f_open(%s) error: %s (%d)\n",filename,FRESULT_str(fr),fr);
|
printf("f_open(%s) error: %s (%d)\n",filename,FRESULT_str(fr),fr);
|
||||||
}
|
}
|
||||||
@@ -402,25 +331,12 @@ void read_cart_ram_file(struct gb_s *gb) {
|
|||||||
}
|
}
|
||||||
f_unmount(pSD->pcName);
|
f_unmount(pSD->pcName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the RTC of the game cartridge. Only used by games that support it.
|
|
||||||
* You could potentially force the game to allow the player to
|
|
||||||
* reset the time by setting the RTC to invalid values.
|
|
||||||
*
|
|
||||||
* Using memset(&gb->cart_rtc, 0xFF, sizeof(gb->cart_rtc)) for
|
|
||||||
* example causes Pokemon Gold/Silver to say "TIME NOT SET",
|
|
||||||
* allowing the player to set the time without having some dumb
|
|
||||||
* password.
|
|
||||||
*
|
|
||||||
* The memset has to be done directly to gb->cart_rtc because
|
|
||||||
* gb_set_rtc() processes the input values, which may cause
|
|
||||||
* games to not detect invalid values.
|
|
||||||
*/
|
|
||||||
memset(gb->cart_rtc, 0xFF, sizeof(gb->cart_rtc));
|
|
||||||
|
|
||||||
printf("read_cart_ram_file(%s) COMPLETE (%lu bytes)\n",filename,save_size);
|
printf("read_cart_ram_file(%s) COMPLETE (%lu bytes)\n",filename,save_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a save file to the SD card
|
||||||
|
*/
|
||||||
void write_cart_ram_file(struct gb_s *gb) {
|
void write_cart_ram_file(struct gb_s *gb) {
|
||||||
char filename[16];
|
char filename[16];
|
||||||
uint_fast32_t save_size;
|
uint_fast32_t save_size;
|
||||||
@@ -452,6 +368,179 @@ void write_cart_ram_file(struct gb_s *gb) {
|
|||||||
}
|
}
|
||||||
printf("write_cart_ram_file(%s) COMPLETE (%lu bytes)\n",filename,save_size);
|
printf("write_cart_ram_file(%s) COMPLETE (%lu bytes)\n",filename,save_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a .gb rom file in flash from the SD card
|
||||||
|
*/
|
||||||
|
void load_cart_rom_file(char *filename) {
|
||||||
|
UINT br;
|
||||||
|
uint8_t buffer[FLASH_SECTOR_SIZE];
|
||||||
|
sd_card_t *pSD=sd_get_by_num(0);
|
||||||
|
FRESULT fr=f_mount(&pSD->fatfs,pSD->pcName,1);
|
||||||
|
if (FR_OK!=fr) {
|
||||||
|
printf("f_mount error: %s (%d)\n",FRESULT_str(fr),fr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FIL fil;
|
||||||
|
fr=f_open(&fil,filename,FA_READ);
|
||||||
|
if (fr==FR_OK) {
|
||||||
|
uint32_t flash_target_offset=FLASH_TARGET_OFFSET;
|
||||||
|
for(;;) {
|
||||||
|
f_read(&fil,buffer,sizeof buffer,&br);
|
||||||
|
if(br==0) break; /* end of file */
|
||||||
|
|
||||||
|
printf("\nErasing target region...\n");
|
||||||
|
flash_range_erase(flash_target_offset,FLASH_SECTOR_SIZE);
|
||||||
|
printf("\nProgramming target region...\n");
|
||||||
|
flash_range_program(flash_target_offset,buffer,FLASH_SECTOR_SIZE);
|
||||||
|
flash_target_offset+=FLASH_SECTOR_SIZE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("f_open(%s) error: %s (%d)\n",filename,FRESULT_str(fr),fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
fr=f_close(&fil);
|
||||||
|
if(fr!=FR_OK) {
|
||||||
|
printf("f_close error: %s (%d)\n", FRESULT_str(fr), fr);
|
||||||
|
}
|
||||||
|
f_unmount(pSD->pcName);
|
||||||
|
|
||||||
|
printf("load_cart_rom_file(%s) COMPLETE (%lu bytes)\n",filename,br);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function used by the rom file selector to display one page of .gb rom files
|
||||||
|
*/
|
||||||
|
uint16_t rom_file_selector_display_page(char filename[22][256],uint16_t num_page) {
|
||||||
|
sd_card_t *pSD=sd_get_by_num(0);
|
||||||
|
DIR dj;
|
||||||
|
FILINFO fno;
|
||||||
|
FRESULT fr;
|
||||||
|
|
||||||
|
fr=f_mount(&pSD->fatfs,pSD->pcName,1);
|
||||||
|
if (FR_OK!=fr) {
|
||||||
|
printf("f_mount error: %s (%d)\n",FRESULT_str(fr),fr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clear the filenames array */
|
||||||
|
for(uint8_t ifile=0;ifile<22;ifile++) {
|
||||||
|
strcpy(filename[ifile],"");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* search *.gb files */
|
||||||
|
uint16_t num_file=0;
|
||||||
|
fr=f_findfirst(&dj, &fno, "", "*.gb");
|
||||||
|
|
||||||
|
/* skip the first N pages */
|
||||||
|
if(num_page>0) {
|
||||||
|
while(num_file<num_page*22 && fr == FR_OK && fno.fname[0]) {
|
||||||
|
num_file++;
|
||||||
|
fr=f_findnext(&dj, &fno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store the filenames of this page */
|
||||||
|
num_file=0;
|
||||||
|
while(num_file<22 && fr == FR_OK && fno.fname[0]) {
|
||||||
|
strcpy(filename[num_file],fno.fname);
|
||||||
|
num_file++;
|
||||||
|
fr=f_findnext(&dj, &fno);
|
||||||
|
}
|
||||||
|
f_closedir(&dj);
|
||||||
|
f_unmount(pSD->pcName);
|
||||||
|
|
||||||
|
/* display *.gb rom files on screen */
|
||||||
|
mk_ili9225_fill(0x0000);
|
||||||
|
for(uint8_t ifile=0;ifile<num_file;ifile++) {
|
||||||
|
mk_ili9225_text(filename[ifile],0,ifile*8,0xFFFF,0x0000);
|
||||||
|
}
|
||||||
|
return num_file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ROM selector displays pages of up to 22 rom files
|
||||||
|
* allowing the user to select which rom file to start
|
||||||
|
* Copy your *.gb rom files to the root directory of the SD card
|
||||||
|
*/
|
||||||
|
void rom_file_selector() {
|
||||||
|
uint16_t num_page;
|
||||||
|
char filename[22][256];
|
||||||
|
uint16_t num_file;
|
||||||
|
|
||||||
|
/* display the first page with up to 22 rom files */
|
||||||
|
num_file=rom_file_selector_display_page(filename,num_page);
|
||||||
|
|
||||||
|
/* select the first rom */
|
||||||
|
uint8_t selected=0;
|
||||||
|
mk_ili9225_text(filename[selected],0,selected*8,0xFFFF,0xF800);
|
||||||
|
|
||||||
|
/* get user's input */
|
||||||
|
bool up,down,left,right,a,b,select,start;
|
||||||
|
while(true) {
|
||||||
|
up=gpio_get(GPIO_UP);
|
||||||
|
down=gpio_get(GPIO_DOWN);
|
||||||
|
left=gpio_get(GPIO_LEFT);
|
||||||
|
right=gpio_get(GPIO_RIGHT);
|
||||||
|
a=gpio_get(GPIO_A);
|
||||||
|
b=gpio_get(GPIO_B);
|
||||||
|
select=gpio_get(GPIO_SELECT);
|
||||||
|
start=gpio_get(GPIO_START);
|
||||||
|
if(!start) {
|
||||||
|
/* re-start the last game (no need to reprogram flash) */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(!a | !b) {
|
||||||
|
/* copy the rom from the SD card to flash and start the game */
|
||||||
|
load_cart_rom_file(filename[selected]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(!down) {
|
||||||
|
/* select the next rom */
|
||||||
|
mk_ili9225_text(filename[selected],0,selected*8,0xFFFF,0x0000);
|
||||||
|
selected++;
|
||||||
|
if(selected>=num_file) selected=0;
|
||||||
|
mk_ili9225_text(filename[selected],0,selected*8,0xFFFF,0xF800);
|
||||||
|
sleep_ms(150);
|
||||||
|
}
|
||||||
|
if(!up) {
|
||||||
|
/* select the previous rom */
|
||||||
|
mk_ili9225_text(filename[selected],0,selected*8,0xFFFF,0x0000);
|
||||||
|
if(selected==0) {
|
||||||
|
selected=num_file-1;
|
||||||
|
} else {
|
||||||
|
selected--;
|
||||||
|
}
|
||||||
|
mk_ili9225_text(filename[selected],0,selected*8,0xFFFF,0xF800);
|
||||||
|
sleep_ms(150);
|
||||||
|
}
|
||||||
|
if(!right) {
|
||||||
|
/* select the next page */
|
||||||
|
num_page++;
|
||||||
|
num_file=rom_file_selector_display_page(filename,num_page);
|
||||||
|
if(num_file==0) {
|
||||||
|
/* no files in this page, go to the previous page */
|
||||||
|
num_page--;
|
||||||
|
num_file=rom_file_selector_display_page(filename,num_page);
|
||||||
|
}
|
||||||
|
/* select the first file */
|
||||||
|
selected=0;
|
||||||
|
mk_ili9225_text(filename[selected],0,selected*8,0xFFFF,0xF800);
|
||||||
|
sleep_ms(150);
|
||||||
|
}
|
||||||
|
if((!left) && num_page>0) {
|
||||||
|
/* select the previous page */
|
||||||
|
num_page--;
|
||||||
|
num_file=rom_file_selector_display_page(filename,num_page);
|
||||||
|
/* select the first file */
|
||||||
|
selected=0;
|
||||||
|
mk_ili9225_text(filename[selected],0,selected*8,0xFFFF,0xF800);
|
||||||
|
sleep_ms(150);
|
||||||
|
}
|
||||||
|
tight_loop_contents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
@@ -523,106 +612,9 @@ int main(void)
|
|||||||
spi_init(spi0, 30*1000*1000);
|
spi_init(spi0, 30*1000*1000);
|
||||||
spi_set_format(spi0, 16, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
|
spi_set_format(spi0, 16, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
|
||||||
|
|
||||||
/* Initialise GB context. */
|
|
||||||
memcpy(rom_bank0, rom, sizeof(rom_bank0));
|
|
||||||
|
|
||||||
ret = gb_init(&gb, &gb_rom_read, &gb_cart_ram_read,
|
|
||||||
&gb_cart_ram_write, &gb_error, &gb_priv);
|
|
||||||
putstdio("GB ");
|
|
||||||
|
|
||||||
if(ret != GB_INIT_NO_ERROR)
|
|
||||||
{
|
|
||||||
printf("Error: %d\n", ret);
|
|
||||||
goto sleep;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if ENABLE_SDCARD
|
|
||||||
/* Load Save File. */
|
|
||||||
read_cart_ram_file(&gb);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Update buttons state */
|
|
||||||
gb.direct.joypad_bits.up=gpio_get(GPIO_UP);
|
|
||||||
gb.direct.joypad_bits.down=gpio_get(GPIO_DOWN);
|
|
||||||
gb.direct.joypad_bits.left=gpio_get(GPIO_LEFT);
|
|
||||||
gb.direct.joypad_bits.right=gpio_get(GPIO_RIGHT);
|
|
||||||
gb.direct.joypad_bits.a=gpio_get(GPIO_A);
|
|
||||||
gb.direct.joypad_bits.b=gpio_get(GPIO_B);
|
|
||||||
gb.direct.joypad_bits.select=gpio_get(GPIO_SELECT);
|
|
||||||
gb.direct.joypad_bits.start=gpio_get(GPIO_START);
|
|
||||||
|
|
||||||
/* manually assign a palette with button combo */
|
|
||||||
|
|
||||||
if(!gb.direct.joypad_bits.a && !gb.direct.joypad_bits.up) {
|
|
||||||
get_colour_palette(palette,0x10,0x05); /* A + Up */
|
|
||||||
} else if(!gb.direct.joypad_bits.a && !gb.direct.joypad_bits.down) {
|
|
||||||
get_colour_palette(palette,0x07,0x00); /* A + Down */
|
|
||||||
} else if(!gb.direct.joypad_bits.a && !gb.direct.joypad_bits.right) {
|
|
||||||
get_colour_palette(palette,0x1C,0x03); /* A + Right */
|
|
||||||
} else if(!gb.direct.joypad_bits.a && !gb.direct.joypad_bits.left) {
|
|
||||||
get_colour_palette(palette,0x0D,0x05); /* A + Left */
|
|
||||||
} else if(!gb.direct.joypad_bits.b && !gb.direct.joypad_bits.up) {
|
|
||||||
get_colour_palette(palette,0x19,0x03); /* B + Up */
|
|
||||||
} else if(!gb.direct.joypad_bits.b && !gb.direct.joypad_bits.down) {
|
|
||||||
get_colour_palette(palette,0x1A,0x05); /* B + Down */
|
|
||||||
} else if(!gb.direct.joypad_bits.b && !gb.direct.joypad_bits.right) {
|
|
||||||
get_colour_palette(palette,0x13,0x00); /* B + Right */
|
|
||||||
} else if(!gb.direct.joypad_bits.b && !gb.direct.joypad_bits.left) {
|
|
||||||
get_colour_palette(palette,0x16,0x00); /* B + Left (Game Boy Pocket Palette, shades of gray) */
|
|
||||||
} else if(!gb.direct.joypad_bits.up) {
|
|
||||||
get_colour_palette(palette,0x12,0x00); /* Up */
|
|
||||||
} else if(!gb.direct.joypad_bits.down) {
|
|
||||||
get_colour_palette(palette,0x17,0x00); /* Down */
|
|
||||||
} else if(!gb.direct.joypad_bits.right) {
|
|
||||||
get_colour_palette(palette,0x05,0x00); /* Right */
|
|
||||||
} else if(!gb.direct.joypad_bits.left) {
|
|
||||||
get_colour_palette(palette,0x18,0x05); /* Left */
|
|
||||||
} else if(!gb.direct.joypad_bits.a && !gb.direct.joypad_bits.b) {
|
|
||||||
get_colour_palette(palette,0xFF,0xFF); /* A + B */
|
|
||||||
} else {
|
|
||||||
/* Automatically assign a colour palette to the game */
|
|
||||||
char rom_title[16];
|
|
||||||
auto_assign_palette(palette, gb_colour_hash(&gb),gb_get_rom_name(&gb,rom_title));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if ENABLE_LCD
|
|
||||||
gb_init_lcd(&gb, &lcd_draw_line);
|
|
||||||
{
|
|
||||||
/* Start Core1, which processes requests to the LCD. */
|
|
||||||
putstdio("CORE1 ");
|
|
||||||
multicore_launch_core1(main_core1);
|
|
||||||
|
|
||||||
/* initialise pixel buffer copy DMA. */
|
|
||||||
static dma_channel_config dma_config;
|
|
||||||
gb_priv.dma_pixel_buffer_chan = dma_claim_unused_channel(true);
|
|
||||||
dma_config = dma_channel_get_default_config(gb_priv.dma_pixel_buffer_chan);
|
|
||||||
channel_config_set_transfer_data_size(&dma_config, DMA_SIZE_32);
|
|
||||||
channel_config_set_read_increment(&dma_config, true);
|
|
||||||
channel_config_set_write_increment(&dma_config, true);
|
|
||||||
dma_sniffer_enable(gb_priv.dma_pixel_buffer_chan, 0x0, true);
|
|
||||||
channel_config_set_sniff_enable(&dma_config, true);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
irq_set_exclusive_handler(DMA_IRQ_1, core0_irq_dma_lcd_line_copy);
|
|
||||||
dma_channel_set_irq1_enabled(gb_priv.dma_pixel_buffer_chan, true);
|
|
||||||
irq_set_enabled(DMA_IRQ_1, true);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dma_channel_configure(
|
|
||||||
gb_priv.dma_pixel_buffer_chan,
|
|
||||||
&dma_config,
|
|
||||||
pixels_buffer,
|
|
||||||
0, /* We don't have a pointer to the pixel buffer here. */
|
|
||||||
LCD_WIDTH/sizeof(uint32_t),
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
putstdio("LCD ");
|
|
||||||
//gb.direct.interlace = 1;
|
|
||||||
#endif
|
|
||||||
#if ENABLE_SOUND
|
#if ENABLE_SOUND
|
||||||
// Allocate memory for the stream buffer
|
// Allocate memory for the stream buffer
|
||||||
stream=malloc(AUDIO_BUFFER_SIZE_BYTES);
|
stream=malloc(AUDIO_BUFFER_SIZE_BYTES);
|
||||||
assert(stream!=NULL);
|
assert(stream!=NULL);
|
||||||
memset(stream,0,AUDIO_BUFFER_SIZE_BYTES); // Zero out the stream buffer
|
memset(stream,0,AUDIO_BUFFER_SIZE_BYTES); // Zero out the stream buffer
|
||||||
|
|
||||||
@@ -632,7 +624,51 @@ int main(void)
|
|||||||
i2s_config.dma_trans_count =AUDIO_SAMPLES;
|
i2s_config.dma_trans_count =AUDIO_SAMPLES;
|
||||||
i2s_volume(&i2s_config,2);
|
i2s_volume(&i2s_config,2);
|
||||||
i2s_init(&i2s_config);
|
i2s_init(&i2s_config);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
#if ENABLE_LCD
|
||||||
|
#if ENABLE_SDCARD
|
||||||
|
/* ROM File selector */
|
||||||
|
mk_ili9225_init();
|
||||||
|
mk_ili9225_fill(0x0000);
|
||||||
|
rom_file_selector();
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Initialise GB context. */
|
||||||
|
memcpy(rom_bank0, rom, sizeof(rom_bank0));
|
||||||
|
ret = gb_init(&gb, &gb_rom_read, &gb_cart_ram_read,
|
||||||
|
&gb_cart_ram_write, &gb_error, NULL);
|
||||||
|
putstdio("GB ");
|
||||||
|
|
||||||
|
if(ret != GB_INIT_NO_ERROR)
|
||||||
|
{
|
||||||
|
printf("Error: %d\n", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ENABLE_SDCARD
|
||||||
|
/* Load Save File. */
|
||||||
|
read_cart_ram_file(&gb);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Automatically assign a colour palette to the game */
|
||||||
|
char rom_title[16];
|
||||||
|
auto_assign_palette(palette, gb_colour_hash(&gb),gb_get_rom_name(&gb,rom_title));
|
||||||
|
|
||||||
|
#if ENABLE_LCD
|
||||||
|
gb_init_lcd(&gb, &lcd_draw_line);
|
||||||
|
|
||||||
|
/* Start Core1, which processes requests to the LCD. */
|
||||||
|
putstdio("CORE1 ");
|
||||||
|
multicore_launch_core1(main_core1);
|
||||||
|
|
||||||
|
putstdio("LCD ");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ENABLE_SOUND
|
||||||
// Initialize audio emulation
|
// Initialize audio emulation
|
||||||
audio_init();
|
audio_init();
|
||||||
|
|
||||||
@@ -689,11 +725,25 @@ int main(void)
|
|||||||
i2s_decrease_volume(&i2s_config);
|
i2s_decrease_volume(&i2s_config);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if(!gb.direct.joypad_bits.right && prev_joypad_bits.right) {
|
||||||
|
/* select + right */
|
||||||
|
if(manual_palette_selected<12) {
|
||||||
|
manual_palette_selected++;
|
||||||
|
manual_assign_palette(palette,manual_palette_selected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!gb.direct.joypad_bits.left && prev_joypad_bits.left) {
|
||||||
|
/* select + left */
|
||||||
|
if(manual_palette_selected>0) {
|
||||||
|
manual_palette_selected--;
|
||||||
|
manual_assign_palette(palette,manual_palette_selected);
|
||||||
|
}
|
||||||
|
}
|
||||||
if(!gb.direct.joypad_bits.start && prev_joypad_bits.start) {
|
if(!gb.direct.joypad_bits.start && prev_joypad_bits.start) {
|
||||||
#if ENABLE_SDCARD
|
#if ENABLE_SDCARD
|
||||||
write_cart_ram_file(&gb);
|
write_cart_ram_file(&gb);
|
||||||
#endif
|
#endif
|
||||||
gb_reset(&gb);
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -819,17 +869,10 @@ int main(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
|
|
||||||
puts("\nEmulation Ended");
|
puts("\nEmulation Ended");
|
||||||
|
/* stop lcd task running on core 1 */
|
||||||
|
multicore_reset_core1();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
mk_ili9225_set_rst(true);
|
|
||||||
reset_usb_boot(0, 0);
|
|
||||||
|
|
||||||
/* Sleep forever. */
|
|
||||||
sleep:
|
|
||||||
stdio_flush();
|
|
||||||
while(1)
|
|
||||||
__wfi();
|
|
||||||
|
|
||||||
HEDLEY_UNREACHABLE();
|
|
||||||
}
|
}
|
||||||
|
|||||||
+738
-1
@@ -392,7 +392,7 @@ unsigned mk_ili9225_init(void)
|
|||||||
{ MK_ILI9225_REG_LCD_AC_DRIVING_CTRL, 0x0100 },
|
{ MK_ILI9225_REG_LCD_AC_DRIVING_CTRL, 0x0100 },
|
||||||
/* Increment vertical and horizontal address.
|
/* Increment vertical and horizontal address.
|
||||||
* Use vertical image. */
|
* Use vertical image. */
|
||||||
{ MK_ILI9225_REG_ENTRY_MODE, 0x1008 },
|
{ MK_ILI9225_REG_ENTRY_MODE, 0x1018 },
|
||||||
/* Turn off all display outputs. */
|
/* Turn off all display outputs. */
|
||||||
{ MK_ILI9225_REG_DISPLAY_CTRL, 0x0000 },
|
{ MK_ILI9225_REG_DISPLAY_CTRL, 0x0000 },
|
||||||
/* Set porches to 8 lines. */
|
/* Set porches to 8 lines. */
|
||||||
@@ -558,3 +558,740 @@ void mk_ili9225_set_drive_freq(uint16_t f)
|
|||||||
void mk_ili9225_exit(void)
|
void mk_ili9225_exit(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mk_ili9225_fill_rect(uint8_t x,uint8_t y,uint8_t w,uint8_t h,uint16_t color)
|
||||||
|
{
|
||||||
|
set_register(MK_ILI9225_REG_ENTRY_MODE,0x1018);
|
||||||
|
set_register(MK_ILI9225_REG_HORI_WIN_ADDR1, y+h-1); // y_max
|
||||||
|
set_register(MK_ILI9225_REG_HORI_WIN_ADDR2, y); // y_min
|
||||||
|
set_register(MK_ILI9225_REG_VERT_WIN_ADDR1, 219-x); // x_max
|
||||||
|
set_register(MK_ILI9225_REG_VERT_WIN_ADDR2, 219-(x+w-1)); // x_min
|
||||||
|
set_register(MK_ILI9225_REG_RAM_ADDR_SET1,y);
|
||||||
|
set_register(MK_ILI9225_REG_RAM_ADDR_SET2,219-x);
|
||||||
|
write_register(MK_ILI9225_REG_GRAM_RW);
|
||||||
|
mk_ili9225_set_rs(1);
|
||||||
|
mk_ili9225_set_cs(0);
|
||||||
|
for(uint16_t i=0;i<w*h;i++) {
|
||||||
|
mk_ili9225_spi_write16(&color,1);
|
||||||
|
}
|
||||||
|
mk_ili9225_set_cs(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mk_ili9225_fill(uint16_t color)
|
||||||
|
{
|
||||||
|
mk_ili9225_fill_rect(0,0,220,176,color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mk_ili9225_pixel(uint8_t x,uint8_t y,uint16_t color)
|
||||||
|
{
|
||||||
|
set_register(MK_ILI9225_REG_RAM_ADDR_SET1,y);
|
||||||
|
set_register(MK_ILI9225_REG_RAM_ADDR_SET2,219-x);
|
||||||
|
set_register(MK_ILI9225_REG_GRAM_RW,color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mk_ili9225_blit(uint16_t *fbuf,uint8_t x,uint8_t y,uint8_t w,uint8_t h) {
|
||||||
|
set_register(MK_ILI9225_REG_ENTRY_MODE,0x1018);
|
||||||
|
set_register(MK_ILI9225_REG_HORI_WIN_ADDR1, y+h-1); // y_max
|
||||||
|
set_register(MK_ILI9225_REG_HORI_WIN_ADDR2, y); // y_min
|
||||||
|
set_register(MK_ILI9225_REG_VERT_WIN_ADDR1, 219-x); // x_max
|
||||||
|
set_register(MK_ILI9225_REG_VERT_WIN_ADDR2, 219-(x+w-1)); // x_min
|
||||||
|
set_register(MK_ILI9225_REG_RAM_ADDR_SET1,y);
|
||||||
|
set_register(MK_ILI9225_REG_RAM_ADDR_SET2,219-x);
|
||||||
|
write_register(MK_ILI9225_REG_GRAM_RW);
|
||||||
|
mk_ili9225_set_rs(1);
|
||||||
|
mk_ili9225_set_cs(0);
|
||||||
|
mk_ili9225_spi_write16(fbuf,w*h);
|
||||||
|
mk_ili9225_set_cs(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mk_ili9225_get_letter(uint16_t *fbuf,char l,uint16_t color,uint16_t bgcolor) {
|
||||||
|
uint8_t letter[8];
|
||||||
|
uint8_t row;
|
||||||
|
|
||||||
|
switch(l)
|
||||||
|
{
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00111100,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01111110,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'b':
|
||||||
|
case 'B':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b01111100,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01111100,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01111100,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
case 'C':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00011110,
|
||||||
|
0b00110000,
|
||||||
|
0b01100000,
|
||||||
|
0b01100000,
|
||||||
|
0b01100000,
|
||||||
|
0b00110000,
|
||||||
|
0b00011110,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
case 'D':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b01111000,
|
||||||
|
0b01101100,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01101100,
|
||||||
|
0b01111000,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'e':
|
||||||
|
case 'E':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b01111110,
|
||||||
|
0b01100000,
|
||||||
|
0b01100000,
|
||||||
|
0b01111000,
|
||||||
|
0b01100000,
|
||||||
|
0b01100000,
|
||||||
|
0b01111110,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
case 'F':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b01111110,
|
||||||
|
0b01100000,
|
||||||
|
0b01100000,
|
||||||
|
0b01111000,
|
||||||
|
0b01100000,
|
||||||
|
0b01100000,
|
||||||
|
0b01100000,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'g':
|
||||||
|
case 'G':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00111100,
|
||||||
|
0b01100110,
|
||||||
|
0b01100000,
|
||||||
|
0b01101110,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b00111110,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
case 'H':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01111110,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
case 'I':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00111100,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00111100,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'j':
|
||||||
|
case 'J':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00000110,
|
||||||
|
0b00000110,
|
||||||
|
0b00000110,
|
||||||
|
0b00000110,
|
||||||
|
0b00000110,
|
||||||
|
0b01100110,
|
||||||
|
0b00111100,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'k':
|
||||||
|
case 'K':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b11000110,
|
||||||
|
0b11001100,
|
||||||
|
0b11011000,
|
||||||
|
0b11110000,
|
||||||
|
0b11011000,
|
||||||
|
0b11001100,
|
||||||
|
0b11000110,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'l':
|
||||||
|
case 'L':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b01100000,
|
||||||
|
0b01100000,
|
||||||
|
0b01100000,
|
||||||
|
0b01100000,
|
||||||
|
0b01100000,
|
||||||
|
0b01100000,
|
||||||
|
0b01111110,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'm':
|
||||||
|
case 'M':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b11000110,
|
||||||
|
0b11101110,
|
||||||
|
0b11111110,
|
||||||
|
0b11010110,
|
||||||
|
0b11000110,
|
||||||
|
0b11000110,
|
||||||
|
0b11000110,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'n':
|
||||||
|
case 'N':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b11000110,
|
||||||
|
0b11100110,
|
||||||
|
0b11110110,
|
||||||
|
0b11011110,
|
||||||
|
0b11001110,
|
||||||
|
0b11000110,
|
||||||
|
0b11000110,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'o':
|
||||||
|
case 'O':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00111100,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b00111100,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
case 'P':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b01111100,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01111100,
|
||||||
|
0b01100000,
|
||||||
|
0b01100000,
|
||||||
|
0b01100000,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'q':
|
||||||
|
case 'Q':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b01111000,
|
||||||
|
0b11001100,
|
||||||
|
0b11001100,
|
||||||
|
0b11001100,
|
||||||
|
0b11001100,
|
||||||
|
0b11011100,
|
||||||
|
0b01111110,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
case 'R':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b01111100,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01111100,
|
||||||
|
0b01101100,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
case 'S':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00111100,
|
||||||
|
0b01100110,
|
||||||
|
0b01110000,
|
||||||
|
0b00111100,
|
||||||
|
0b00001110,
|
||||||
|
0b01100110,
|
||||||
|
0b00111100,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 't':
|
||||||
|
case 'T':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b01111110,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
case 'U':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b00111100,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'v':
|
||||||
|
case 'V':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b00111100,
|
||||||
|
0b00111100,
|
||||||
|
0b00011000,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'w':
|
||||||
|
case 'W':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b11000110,
|
||||||
|
0b11000110,
|
||||||
|
0b11000110,
|
||||||
|
0b11010110,
|
||||||
|
0b11111110,
|
||||||
|
0b11101110,
|
||||||
|
0b11000110,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
case 'X':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b11000011,
|
||||||
|
0b01100110,
|
||||||
|
0b00111100,
|
||||||
|
0b00011000,
|
||||||
|
0b00111100,
|
||||||
|
0b01100110,
|
||||||
|
0b11000011,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'y':
|
||||||
|
case 'Y':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b11000011,
|
||||||
|
0b01100110,
|
||||||
|
0b00111100,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'z':
|
||||||
|
case 'Z':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b11111110,
|
||||||
|
0b00001100,
|
||||||
|
0b00011000,
|
||||||
|
0b00110000,
|
||||||
|
0b01100000,
|
||||||
|
0b11000000,
|
||||||
|
0b11111110,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '-':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b01111110,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '(':
|
||||||
|
case '[':
|
||||||
|
case '{':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00001100,
|
||||||
|
0b00011000,
|
||||||
|
0b00110000,
|
||||||
|
0b00110000,
|
||||||
|
0b00110000,
|
||||||
|
0b00011000,
|
||||||
|
0b00001100,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ')':
|
||||||
|
case ']':
|
||||||
|
case '}':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00110000,
|
||||||
|
0b00011000,
|
||||||
|
0b00001100,
|
||||||
|
0b00001100,
|
||||||
|
0b00001100,
|
||||||
|
0b00011000,
|
||||||
|
0b00110000,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ',':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00110000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '.':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '!':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00000000,
|
||||||
|
0b00011000,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '&':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00111000,
|
||||||
|
0b01101100,
|
||||||
|
0b01101000,
|
||||||
|
0b01110110,
|
||||||
|
0b11011100,
|
||||||
|
0b11001110,
|
||||||
|
0b01111011,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '\'':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00110000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '0':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00111100,
|
||||||
|
0b01100110,
|
||||||
|
0b01101110,
|
||||||
|
0b01111110,
|
||||||
|
0b01110110,
|
||||||
|
0b01100110,
|
||||||
|
0b00111100,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '1':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00011000,
|
||||||
|
0b00111000,
|
||||||
|
0b01111000,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '2':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00111100,
|
||||||
|
0b01100110,
|
||||||
|
0b00000110,
|
||||||
|
0b00001100,
|
||||||
|
0b00011000,
|
||||||
|
0b00110000,
|
||||||
|
0b01111110,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '3':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00111100,
|
||||||
|
0b01100110,
|
||||||
|
0b00000110,
|
||||||
|
0b00011100,
|
||||||
|
0b00000110,
|
||||||
|
0b01100110,
|
||||||
|
0b00111100,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '4':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00011100,
|
||||||
|
0b00111100,
|
||||||
|
0b01101100,
|
||||||
|
0b11001100,
|
||||||
|
0b11111110,
|
||||||
|
0b00001100,
|
||||||
|
0b00001100,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '5':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b01111110,
|
||||||
|
0b01100000,
|
||||||
|
0b01111100,
|
||||||
|
0b00000110,
|
||||||
|
0b00000110,
|
||||||
|
0b01100110,
|
||||||
|
0b00111100,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '6':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00011100,
|
||||||
|
0b00110000,
|
||||||
|
0b01100000,
|
||||||
|
0b01111100,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b00111100,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '7':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b01111110,
|
||||||
|
0b00000110,
|
||||||
|
0b00000110,
|
||||||
|
0b00001100,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00011000,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '8':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00111100,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b00111100,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b00111100,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '9':
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00111100,
|
||||||
|
0b01100110,
|
||||||
|
0b01100110,
|
||||||
|
0b00111110,
|
||||||
|
0b00000110,
|
||||||
|
0b00001100,
|
||||||
|
0b00111000,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
const uint8_t letter_[8]={0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000};
|
||||||
|
memcpy(letter,letter_,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(uint8_t y=0;y<8;y++) {
|
||||||
|
row=letter[y];
|
||||||
|
for(uint8_t x=0;x<8;x++) {
|
||||||
|
if(row & 128) {
|
||||||
|
fbuf[y*8+x]=color;
|
||||||
|
} else {
|
||||||
|
fbuf[y*8+x]=bgcolor;
|
||||||
|
}
|
||||||
|
row=row<<1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mk_ili9225_text(char *s,uint8_t x,uint8_t y,uint16_t color,uint16_t bgcolor) {
|
||||||
|
uint16_t fbuf[8*8];
|
||||||
|
for(uint8_t i=0;i<strlen(s);i++) {
|
||||||
|
mk_ili9225_get_letter(fbuf,s[i],color,bgcolor);
|
||||||
|
mk_ili9225_blit(fbuf,x,y,8,8);
|
||||||
|
x+=8;
|
||||||
|
if(x>27*8) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user