fix PICOMPUTERMAX keyboard and add dual screen support to MCUME_REV2

pull/9/head
jean-marcharvengt 2021-10-08 21:46:02 +02:00
rodzic a47483d3e6
commit 42601b4e91
47 zmienionych plików z 2264 dodań i 542 usunięć

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -32,8 +32,10 @@
#ifdef KEYMAP_PRESENT
#ifdef PICOMPUTER
#define keylables_map1_0 (char *)" "
#define keylables_map1_1 (char *)" "
#define keylables_map1_2 (char *)" "
const unsigned short key_map1[] = {
15+1,14+1,13+1,11+1,10+1,9+1,7+1,6+1,5+1,2+1,0,
0,12+1,8+1,4+1,0+1,1+1,3+1,0,0,0,0,
@ -47,6 +49,9 @@ const unsigned short key_map1[] = {
// [PAUSE] 8 [ 6 ] 9 [ 5 ] 10 [ 4 ] 11
// [START] 12 [ 3 ] 13 [ 2 ] 14 [ 1 ] 15
#define keylables_map2_0 (char *)" "
#define keylables_map2_1 (char *)" "
#define keylables_map2_2 (char *)" "
const unsigned short key_map2[] = {
0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,
@ -54,6 +59,9 @@ const unsigned short key_map2[] = {
0,0,0,0
};
#define keylables_map3_0 (char *)" "
#define keylables_map3_1 (char *)" "
#define keylables_map3_2 (char *)" "
const unsigned short key_map3[] = {
0,0,0,0,0,0,0,0,0,0,0, // function keys
0, 0,0,0,0,0,0,0,0,0,0,
@ -68,7 +76,6 @@ const unsigned short matkeys[] = {
0x508,0x501,0x502,0x504 }; // cursor keys
#endif
#endif
@ -86,7 +93,7 @@ const unsigned short matkeys[] = {
#define MASK_JOY1_DOWN 0x0800
#define MASK_JOY1_BTN 0x1000
#define MASK_KEY_USER4 0x2000
#define MASK_OSKB 0x8000
extern void emu_init(void);

Wyświetl plik

@ -210,19 +210,19 @@ static void drawOskb(void)
// lineOSKB2(KXOFF,KYOFF+16, (char *)" A!S@D#F$G%H+J&K*L-EN", 1);
// lineOSKB2(KXOFF,KYOFF+32, (char *)" Z(X)C?V/B\"N<M>.,SP ", 2);
if (oskbMap == 0) {
lineOSKB(KXOFF,KYOFF, (char *)"qwertyuiop\x1a", 0);
lineOSKB(KXOFF,KYOFF, (char *)" asdfghjkl\x19", 1);
lineOSKB(KXOFF,KYOFF, (char *)" zxcvbnm.\x10 ", 2);
lineOSKB(KXOFF,KYOFF, keylables_map1_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map1_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map1_2, 2);
}
else if (oskbMap == 1) {
lineOSKB(KXOFF,KYOFF, (char *)"1234567890=", 0);
lineOSKB(KXOFF,KYOFF, (char *)" !@#$%+&*- ", 1);
lineOSKB(KXOFF,KYOFF, (char *)" ()?/\"<>,: ", 2);
lineOSKB(KXOFF,KYOFF, keylables_map2_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map2_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map2_2, 2);
}
else {
lineOSKB(KXOFF,KYOFF, (char *)"\x11\x12\x13\x14\x15\x16\x17\x18 ", 0);
lineOSKB(KXOFF,KYOFF, (char *)" ", 1);
lineOSKB(KXOFF,KYOFF, (char *)" ; ", 2);
lineOSKB(KXOFF,KYOFF, keylables_map3_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map3_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map3_2, 2);
}
}
@ -306,6 +306,7 @@ static int handleOskb(void)
else {
retval = key_map3[retval];
}
//if (retval) { toggleOskb(true); updated=false; };
}
}
else {
@ -495,7 +496,12 @@ int emu_ReadKeys(void)
unsigned char keymatrixtmp[6];
for (int i=0;i<6;i++){
gpio_put(cols[i], 0);
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
@ -506,17 +512,21 @@ int emu_ReadKeys(void)
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] = row;
}
#ifdef MULTI_DEBOUNCE
for (int i=0;i<6;i++){
// gpio_set_dir(cols[i], GPIO_OUT);
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
@ -527,18 +537,20 @@ int emu_ReadKeys(void)
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
// gpio_set_dir(cols[i], GPIO_IN);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
for (int i=0;i<6;i++){
// gpio_set_dir(cols[i], GPIO_OUT);
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
@ -549,11 +561,13 @@ int emu_ReadKeys(void)
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
// gpio_set_dir(cols[i], GPIO_IN);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
#endif
#ifdef SWAP_ALT_DEL
// Swap ALT and DEL
@ -848,35 +862,26 @@ void emu_InitJoysticks(void) {
gpio_set_dir(4, GPIO_OUT);
gpio_set_dir(5, GPIO_OUT);
gpio_set_dir(14, GPIO_OUT);
gpio_put(1, 1);
gpio_put(2, 1);
gpio_put(3, 1);
gpio_put(4, 1);
gpio_put(5, 1);
gpio_put(14, 1);
/*
gpio_put(1, 0);
gpio_put(2, 0);
gpio_put(3, 0);
gpio_put(4, 0);
gpio_put(5, 0);
gpio_put(14, 0);
gpio_set_pulls(1,true,true);
gpio_set_pulls(2,true,true);
gpio_set_pulls(3,true,true);
gpio_set_pulls(4,true,true);
gpio_set_pulls(5,true,true);
gpio_set_pulls(14,true,true);
// but set as input floating when not used!
gpio_set_dir(1, GPIO_IN);
gpio_set_dir(2, GPIO_IN);
gpio_set_dir(3, GPIO_IN);
gpio_set_dir(4, GPIO_IN);
gpio_set_dir(5, GPIO_IN);
gpio_set_dir(14, GPIO_IN);
*/
gpio_set_dir(14, GPIO_IN);
gpio_disable_pulls(1);
gpio_disable_pulls(2);
gpio_disable_pulls(3);
gpio_disable_pulls(4);
gpio_disable_pulls(5);
gpio_disable_pulls(14);
// Input pins (cols)
gpio_init(6);
gpio_init(9);
@ -884,18 +889,18 @@ void emu_InitJoysticks(void) {
gpio_init(8);
gpio_init(7);
gpio_init(22);
gpio_set_pulls(6,true,false);
gpio_set_dir(6,GPIO_IN);
gpio_set_pulls(9,true,false);
gpio_set_dir(9,GPIO_IN);
gpio_set_pulls(15,true,false);
gpio_set_dir(15,GPIO_IN);
gpio_set_pulls(8,true,false);
gpio_set_dir(8,GPIO_IN);
gpio_set_pulls(7,true,false);
gpio_set_dir(7,GPIO_IN);
gpio_set_pulls(22,true,false);
gpio_set_dir(22,GPIO_IN);
gpio_pull_up(6);
gpio_pull_up(9);
gpio_pull_up(15);
gpio_pull_up(8);
gpio_pull_up(7);
gpio_pull_up(22);
#endif
}

Wyświetl plik

@ -28,7 +28,10 @@
#define ACTION_RUNVGA 130
#ifdef KEYMAP_PRESENT
#define keylables_map1_0 (char *)"qwertyuiop\x1a"
#define keylables_map1_1 (char *)" asdfghjkl\x19"
#define keylables_map1_2 (char *)" zxcvbnm.\x10 "
const unsigned short key_map1[] = {
'Q','W','E','R','T','Y','U','I','O','P',157,
0,'A','S','D','F','G','H','J','K','L',0x0D,
@ -36,6 +39,9 @@ const unsigned short key_map1[] = {
145,157,29,17
};
#define keylables_map2_0 (char *)"1234567890 "
#define keylables_map2_1 (char *)" !@#$%+&*- "
#define keylables_map2_2 (char *)" ()?/\"<>,: "
const unsigned short key_map2[] = {
'1','2','3','4','5','6','7','8','9','0',0,
0, '!','@','#','$','%','+','&','*','-','\/',
@ -43,6 +49,9 @@ const unsigned short key_map2[] = {
0,0,0,0
};
#define keylables_map3_0 (char *)"\x11\x12\x13\x14\x15\x16\x17\x18 "
#define keylables_map3_1 (char *)" "
#define keylables_map3_2 (char *)" ;= "
const unsigned short key_map3[] = {
133,134,135,136,137,138,139,140,0,0,0, // function keys
0, 0,0,0,0,0,0,0,0,0,0,
@ -55,7 +64,7 @@ const unsigned short matkeys[] = {
0x510,0x010,0x110,0x210,0x310,0x410,0x401,0x301,0x201,0x101,0x001, // row 2
0x520,0x102,0x202,0x302,0x402,0x404,0x304,0x204,0x104,0x004, // row 3
0x508,0x501,0x502,0x504 }; // cursor keys
#endif

Wyświetl plik

@ -13,11 +13,19 @@ extern "C" {
#include "iopins.h"
}
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
// Dual display config, initialize TFT
#include "tft_t_dma.h"
static TFT_T_DMA tft;
#else
// Non Dual display config
#ifdef USE_VGA
#include "vga_t_dma.h"
#else
#include "tft_t_dma.h"
#endif
extern TFT_T_DMA tft;
#endif
#define MAX_FILES 64
@ -39,7 +47,7 @@ extern "C" {
#define MENU_VGA_XOFFSET (MENU_FILE_XOFFSET+MENU_FILE_W+8)
#define MENU_VGA_YOFFSET (MENU_VBAR_YOFFSET+MENU_FILE_H-32-37)
extern TFT_T_DMA tft;
static char romspath[64];
static int nbFiles=0;
@ -142,8 +150,175 @@ void emu_Free(void * pt)
free(pt);
}
void emu_drawText(unsigned short x, unsigned short y, const char * text, unsigned short fgcolor, unsigned short bgcolor, int doublesize)
{
tft.drawText(x, y, text, fgcolor, bgcolor, doublesize?true:false);
}
/********************************
* OSKB handling
********************************/
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
// On screen keyboard position
#define KXOFF 28 //64
#define KYOFF 96
#define KWIDTH 11 //22
#define KHEIGHT 3
static bool oskbOn = false;
static int cxpos = 0;
static int cypos = 0;
static int oskbMap = 0;
static uint16_t oskbBLastState = 0;
static void lineOSKB2(int kxoff, int kyoff, char * str, int row)
{
char c[2] = {'A',0};
const char * cpt = str;
for (int i=0; i<KWIDTH; i++)
{
c[0] = *cpt++;
c[1] = 0;
uint16_t bg = RGBVAL16(0x00,0x00,0xff);
if ( (cxpos == i) && (cypos == row) ) bg = RGBVAL16(0xff,0x00,0x00);
tft.drawTextNoDma(kxoff+8*i,kyoff, &c[0], RGBVAL16(0x00,0xff,0xff), bg, ((i&1)?false:true));
}
}
static void lineOSKB(int kxoff, int kyoff, char * str, int row)
{
char c[4] = {' ',0,' ',0};
const char * cpt = str;
for (int i=0; i<KWIDTH; i++)
{
c[1] = *cpt++;
uint16_t bg;
if (row&1) bg = (i&1)?RGBVAL16(0xff,0xff,0xff):RGBVAL16(0xe0,0xe0,0xe0);
else bg = (i&1)?RGBVAL16(0xe0,0xe0,0xe0):RGBVAL16(0xff,0xff,0xff);
if ( (cxpos == i) && (cypos == row) ) bg = RGBVAL16(0x00,0xff,0xff);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+0 , " ", RGBVAL16(0x00,0x00,0x00), bg, false);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+8 , &c[0], RGBVAL16(0x00,0x00,0x00), bg, true);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+24, " ", RGBVAL16(0x00,0x00,0x00), bg, false);
}
}
static void drawOskb(void)
{
// lineOSKB2(KXOFF,KYOFF+0, (char *)"Q1W2E3R4T5Y6U7I8O9P0<=", 0);
// lineOSKB2(KXOFF,KYOFF+16, (char *)" A!S@D#F$G%H+J&K*L-EN", 1);
// lineOSKB2(KXOFF,KYOFF+32, (char *)" Z(X)C?V/B\"N<M>.,SP ", 2);
if (oskbMap == 0) {
lineOSKB(KXOFF,KYOFF, keylables_map1_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map1_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map1_2, 2);
}
else if (oskbMap == 1) {
lineOSKB(KXOFF,KYOFF, keylables_map2_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map2_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map2_2, 2);
}
else {
lineOSKB(KXOFF,KYOFF, keylables_map3_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map3_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map3_2, 2);
}
}
void toggleOskb(bool forceoff) {
if (forceoff) oskbOn=true;
if (oskbOn) {
oskbOn = false;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,32, "Press USER2 to toggle onscreen keyboard.", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0x00,0x00,0x00), true);
} else {
oskbOn = true;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,32, " Press USER2 to exit onscreen keyboard. ", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0x00,0x00,0x00), true);
tft.drawTextNoDma(0,64, " (USER1 to toggle between keymaps) ", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
tft.drawRectNoDma(KXOFF,KYOFF, 22*8, 3*16, RGBVAL16(0x00,0x00,0xFF));
drawOskb();
}
}
static int handleOskb(void)
{
int retval = 0;
uint16_t bClick = bLastState & ~oskbBLastState;
oskbBLastState = bLastState;
/*
static const char * digits = "0123456789ABCDEF";
char buf[5] = {0,0,0,0,0};
int val = bClick;
buf[0] = digits[(val>>12)&0xf];
buf[1] = digits[(val>>8)&0xf];
buf[2] = digits[(val>>4)&0xf];
buf[3] = digits[val&0xf];
tft.drawTextNoDma(0,KYOFF+ 64,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),1);
*/
if (bClick & MASK_KEY_USER2)
{
toggleOskb(false);
}
if (oskbOn)
{
bool updated = true;
if (bClick & MASK_KEY_USER1)
{
oskbMap += 1;
if (oskbMap == 3) oskbMap = 0;
}
else if (bClick & MASK_JOY2_LEFT)
{
cxpos++;
if (cxpos >= KWIDTH) cxpos = 0;
}
else if (bClick & MASK_JOY2_RIGHT)
{
cxpos--;
if (cxpos < 0) cxpos = KWIDTH-1;
}
else if (bClick & MASK_JOY2_DOWN)
{
cypos++;
if (cypos >= KHEIGHT) cypos = 0;
}
else if (bClick & MASK_JOY2_UP)
{
cypos--;
if (cypos < 0) cypos = KHEIGHT-1;
}
else if (oskbBLastState & MASK_JOY2_BTN)
{
retval = cypos*KWIDTH+cxpos+1;
if (retval) {
retval--;
//if (retval & 1) retval = key_map2[retval>>1];
//else retval = key_map1[retval>>1];
if (oskbMap == 0) {
retval = key_map1[retval];
}
else if (oskbMap == 1) {
retval = key_map2[retval];
}
else {
retval = key_map3[retval];
}
//if (retval) { toggleOskb(true); updated=false; };
}
}
else {
updated=false;
}
if (updated) drawOskb();
}
return retval;
}
#endif
/********************************
* Input and keyboard
********************************/
@ -318,13 +493,15 @@ int emu_ReadKeys(void)
keymatrix_hitrow = -1;
unsigned char row;
unsigned short cols[6]={1,2,3,4,5,14};
unsigned char keymatrixtmp[6];
for (int i=0;i<6;i++){
// gpio_set_dir(cols[i], GPIO_OUT);
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
@ -335,27 +512,80 @@ int emu_ReadKeys(void)
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
// gpio_set_dir(cols[i], GPIO_IN);
keymatrix[i]=row;
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] = row;
}
#ifdef MULTI_DEBOUNCE
for (int i=0;i<6;i++){
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(8) ? 0 : 0x02);
row |= (gpio_get(6) ? 0 : 0x04);
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
for (int i=0;i<6;i++){
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(8) ? 0 : 0x02);
row |= (gpio_get(6) ? 0 : 0x04);
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
#endif
#ifdef SWAP_ALT_DEL
// Swap ALT and DEL
unsigned char alt = keymatrix[0] & 0x02;
unsigned char del = keymatrix[5] & 0x20;
keymatrix[0] &= ~0x02;
keymatrix[5] &= ~0x20;
if (alt) keymatrix[5] |= 0x20;
if (del) keymatrix[0] |= 0x02;
unsigned char alt = keymatrixtmp[0] & 0x02;
unsigned char del = keymatrixtmp[5] & 0x20;
keymatrixtmp[0] &= ~0x02;
keymatrixtmp[5] &= ~0x20;
if (alt) keymatrixtmp[5] |= 0x20;
if (del) keymatrixtmp[0] |= 0x02;
#endif
bool alt_pressed=false;
if ( keymatrix[5] & 0x20 ) {alt_pressed=true; keymatrix[5] &= ~0x20;};
if ( keymatrixtmp[5] & 0x20 ) {alt_pressed=true; keymatrixtmp[5] &= ~0x20;};
for (int i=0;i<6;i++){
row = keymatrix[i];
row = keymatrixtmp[i];
if (row) keymatrix_hitrow=i;
keymatrix[i] = row;
}
//6,9,15,8,7,22
@ -399,7 +629,8 @@ int emu_ReadKeys(void)
hundred_ms_cnt += 1; // 2
if (hundred_ms_cnt >= 2)
{
hundred_ms_cnt = 0;
hundred_ms_cnt = 0;
/*
if ( (time_ms-keypress_t_ms) < 500)
{
if (key_alt == false)
@ -411,13 +642,14 @@ int emu_ReadKeys(void)
key_alt = false;
}
}
*/
}
}
}
else {
// Keep press
if (hundred_ms_cnt == 1) {
if ((to_ms_since_boot (get_absolute_time())-keypress_t_ms) > 1000)
if ((to_ms_since_boot (get_absolute_time())-keypress_t_ms) > 2000)
{
if (key_alt == false)
{
@ -460,6 +692,12 @@ int emu_ReadKeys(void)
|| (retval & MASK_KEY_USER4 ) )
{
}
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
if (oskbOn) {
retval |= MASK_OSKB;
}
#endif
return (retval);
}
@ -487,8 +725,6 @@ int emu_ReadI2CKeyboard(void) {
}
if (keymatrix_hitrow >=0 ) {
unsigned short match = ((unsigned short)keymatrix_hitrow<<8) | keymatrix[keymatrix_hitrow];
//if ( (match == 0x002 ) ) return 0; // shift or fn
//if (match < 0x100 ) match = match & ~0x002; // ignore shift key
for (int i=0; i<sizeof(matkeys)/sizeof(unsigned short); i++) {
if (match == matkeys[i]) {
hundred_ms_cnt = 0;
@ -497,6 +733,11 @@ int emu_ReadI2CKeyboard(void) {
}
}
#endif
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
if (!menuOn) {
retval = handleOskb();
}
#endif
return(retval);
}
@ -621,35 +862,26 @@ void emu_InitJoysticks(void) {
gpio_set_dir(4, GPIO_OUT);
gpio_set_dir(5, GPIO_OUT);
gpio_set_dir(14, GPIO_OUT);
gpio_put(1, 1);
gpio_put(2, 1);
gpio_put(3, 1);
gpio_put(4, 1);
gpio_put(5, 1);
gpio_put(14, 1);
/*
gpio_put(1, 0);
gpio_put(2, 0);
gpio_put(3, 0);
gpio_put(4, 0);
gpio_put(5, 0);
gpio_put(14, 0);
gpio_set_pulls(1,true,true);
gpio_set_pulls(2,true,true);
gpio_set_pulls(3,true,true);
gpio_set_pulls(4,true,true);
gpio_set_pulls(5,true,true);
gpio_set_pulls(14,true,true);
// but set as input floating when not used!
gpio_set_dir(1, GPIO_IN);
gpio_set_dir(2, GPIO_IN);
gpio_set_dir(3, GPIO_IN);
gpio_set_dir(4, GPIO_IN);
gpio_set_dir(5, GPIO_IN);
gpio_set_dir(14, GPIO_IN);
*/
gpio_set_dir(14, GPIO_IN);
gpio_disable_pulls(1);
gpio_disable_pulls(2);
gpio_disable_pulls(3);
gpio_disable_pulls(4);
gpio_disable_pulls(5);
gpio_disable_pulls(14);
// Input pins (cols)
gpio_init(6);
gpio_init(9);
@ -657,18 +889,18 @@ void emu_InitJoysticks(void) {
gpio_init(8);
gpio_init(7);
gpio_init(22);
gpio_set_pulls(6,true,false);
gpio_set_dir(6,GPIO_IN);
gpio_set_pulls(9,true,false);
gpio_set_dir(9,GPIO_IN);
gpio_set_pulls(15,true,false);
gpio_set_dir(15,GPIO_IN);
gpio_set_pulls(8,true,false);
gpio_set_dir(8,GPIO_IN);
gpio_set_pulls(7,true,false);
gpio_set_dir(7,GPIO_IN);
gpio_set_pulls(22,true,false);
gpio_set_dir(22,GPIO_IN);
gpio_pull_up(6);
gpio_pull_up(9);
gpio_pull_up(15);
gpio_pull_up(8);
gpio_pull_up(7);
gpio_pull_up(22);
#endif
}
@ -722,6 +954,14 @@ void backgroundMenu(void) {
tft.drawTextNoDma(0,0, TITLE, RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
}
static void menuLeft(void)
{
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
toggleOskb(true);
#endif
}
int handleMenu(uint16_t bClick)
{
int action = ACTION_NONE;
@ -741,12 +981,13 @@ int handleMenu(uint16_t bClick)
strcpy(romspath,newpath);
curFile = 0;
nbFiles = readNbFiles(newpath);
menuRedraw=true;
}
else
{
action = ACTION_RUNTFT;
action = ACTION_RUNTFT;
menuLeft();
}
menuRedraw=true;
}
else if ( (bClick & MASK_KEY_USER1) ) {
menuRedraw=true;
@ -980,6 +1221,11 @@ int emu_LoadFile(char * filename, char * buf, int size)
********************************/
void emu_init(void)
{
// Dual display config, initialize TFT
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
tft.begin();
#endif
sd_init_driver();
FRESULT fr = f_mount(&fatfs, "0:", 1);

Wyświetl plik

@ -32,36 +32,45 @@
#ifdef KEYMAP_PRESENT
#ifdef PICOMPUTER
#define keylables_map1_0 (char *)"qwertyuiop\x1a"
#define keylables_map1_1 (char *)" asdfghjkl\x19"
#define keylables_map1_2 (char *)" zxcvbnm.\x10 "
const unsigned short key_map1[] = {
//0x1F+1,0x1F ,0x1A+1,0x18+1,0x1D+1,0x1B+1,0x33+1,0x35+1,0x30+1,0x32+1,0x34+1, // Digits
0x2F+1,0x2F ,0x2A+1,0x28+1,0x2D+1,0x2B+1,0x0B+1,0x0D+1,0x08+1,0x0A+1,0x34+1,
0x2C+1,0x3F+1,0x3F ,0x3A+1,0x38+1,0x3D+1,0x39+1,0x01+1,0x05+1,0x00+1,0x0C+1,
0, 0x17+1,0x16+1,0x12+1,0x10+1,0x15+1,0x23+1,0x25+1,0x20+1, 0x21+1,
0x2F+1,0x2F,0x2A+1,0x28+1,0x2D+1,0x2B+1,0x0B+1,0x0D+1,0x08+1,0x0A+1,0x34+1,
0,0x3F+1,0x3F,0x3A+1,0x38+1,0x3D+1,0x39+1,0x01+1,0x05+1,0x00+1,0x0C+1,
0,0x17+1,0x16+1,0x12+1,0x10+1,0x15+1,0x23+1,0x25+1,0x22+1, 0x21+1,
0,0,0,0
};
#define keylables_map2_0 (char *)"1234567890="
#define keylables_map2_1 (char *)"T!@#$%+&*- "
#define keylables_map2_2 (char *)" ()?/\"<>,: "
const unsigned short key_map2[] = {
0x1F+1,0x1F,0x1A+1,0x18+1,0x1D+1,0x1B+1,0x33+1,0x35+1,0x30+1,0x32+1,0x34+1, // Digits
0x2C+1,0x07+1,0x22+1,0x26+1,0x02+1,0x06+1,0x36+1,0x37+1,0x0F+1,0x0E + 1,0x06+1, // various
//0x07+1=*, 0x22+1=.,0x26+1=/, 0x02+1=;, 0x06+1=+, 0x36+1=<, 0x37+1=>, 0x0F+1==, 0x0E+1=-, 0x06+1=+
0, 0,0,0,0,0,3,4,19,20,
0x1F+1,0x1F,0x1A+1,0x18+1,0x1D+1,0x1B+1,0x33+1,0x35+1,0x30+1,0x32+1,0x0F+1, // Digits
0x2C+1,95+1,117+1,90+1,88+1,93+1,0x06+1,91+1,0x07+1,0x0E + 1,0, // various
0, 112+1,114+1,102+1,0x26+1,94+1,0x36+1,0x37+1,0x20+1,66+1,
0,0,0,0
};
//0x07+1=*, 0x22+1=.,0x26+1=/, 0x02+1=;, 0x06+1=+, 0x36+1=<, 0x37+1=>, 0x0F+1==, 0x0E+1=-, 0x06+1=+
#define keylables_map3_0 (char *)"\x11\x12\x13\x14H "
#define keylables_map3_1 (char *)" "
#define keylables_map3_2 (char *)" ' ; "
const unsigned short key_map3[] = {
0,0,0,0,0,0,0,0,0,0,0, // function keys
3+1,4+1,19+1,20+1,17+1,0,0,0,0,0,0, // function keys
0, 0,0,0,0,0,0,0,0,0,0,
0, 0,0,0,0,0,0,0,0,0,
0, 0,0,0,0,115+1,0,0,0x02+1,0,
0,0,0,0
};
const unsigned short matkeys[] = {
0x020,0x120,0x220,0x320,0x420,0x408,0x308,0x208,0x108,0x008,0x002, // row 1
0x510,0x010,0x110,0x210,0x310,0x410,0x401,0x301,0x201,0x101,0x001, // row 2
0x520,0x102,0x202,0x302,0x402,0x404,0x304,0x204,0x104,0x004, // row 3
0x508,0x501,0x502,0x504 }; // cursor keys
#endif
#endif
/* Pokey code
@ -139,7 +148,7 @@ KEY_L = 0
#define MASK_JOY1_DOWN 0x0800
#define MASK_JOY1_BTN 0x1000
#define MASK_KEY_USER4 0x2000
#define MASK_OSKB 0x8000
extern void emu_init(void);

Wyświetl plik

@ -19,6 +19,7 @@ extern "C" {
#include "vga_t_dma.h"
#else
#include "tft_t_dma.h"
#endif
volatile bool vbl=true;
bool repeating_timer_callback(struct repeating_timer *t) {
@ -29,7 +30,6 @@ bool repeating_timer_callback(struct repeating_timer *t) {
}
return true;
}
#endif
TFT_T_DMA tft;
static int skip=0;
@ -62,10 +62,8 @@ int main(void) {
emu_Init(filename);
tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
tft.startDMA();
#ifndef USE_VGA
struct repeating_timer timer;
add_repeating_timer_ms(15, repeating_timer_callback, NULL, &timer);
#endif
}
tft.waitSync();
}

Wyświetl plik

@ -210,19 +210,19 @@ static void drawOskb(void)
// lineOSKB2(KXOFF,KYOFF+16, (char *)" A!S@D#F$G%H+J&K*L-EN", 1);
// lineOSKB2(KXOFF,KYOFF+32, (char *)" Z(X)C?V/B\"N<M>.,SP ", 2);
if (oskbMap == 0) {
lineOSKB(KXOFF,KYOFF, (char *)"qwertyuiop\x1a", 0);
lineOSKB(KXOFF,KYOFF, (char *)" asdfghjkl\x19", 1);
lineOSKB(KXOFF,KYOFF, (char *)" zxcvbnm.\x10 ", 2);
lineOSKB(KXOFF,KYOFF, keylables_map1_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map1_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map1_2, 2);
}
else if (oskbMap == 1) {
lineOSKB(KXOFF,KYOFF, (char *)"1234567890=", 0);
lineOSKB(KXOFF,KYOFF, (char *)" $ + *- ", 1);
lineOSKB(KXOFF,KYOFF, (char *)" ()?/\"<>,: ", 2);
lineOSKB(KXOFF,KYOFF, keylables_map2_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map2_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map2_2, 2);
}
else {
lineOSKB(KXOFF,KYOFF, (char *)" ", 0);
lineOSKB(KXOFF,KYOFF, (char *)" ", 1);
lineOSKB(KXOFF,KYOFF, (char *)" ; ", 2);
lineOSKB(KXOFF,KYOFF, keylables_map3_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map3_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map3_2, 2);
}
}
@ -306,6 +306,7 @@ static int handleOskb(void)
else {
retval = key_map3[retval];
}
//if (retval) { toggleOskb(true); updated=false; };
}
}
else {
@ -495,7 +496,12 @@ int emu_ReadKeys(void)
unsigned char keymatrixtmp[6];
for (int i=0;i<6;i++){
gpio_put(cols[i], 0);
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
@ -506,17 +512,21 @@ int emu_ReadKeys(void)
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] = row;
}
#ifdef MULTI_DEBOUNCE
for (int i=0;i<6;i++){
// gpio_set_dir(cols[i], GPIO_OUT);
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
@ -527,18 +537,20 @@ int emu_ReadKeys(void)
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
// gpio_set_dir(cols[i], GPIO_IN);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
for (int i=0;i<6;i++){
// gpio_set_dir(cols[i], GPIO_OUT);
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
@ -549,11 +561,13 @@ int emu_ReadKeys(void)
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
// gpio_set_dir(cols[i], GPIO_IN);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
#endif
#ifdef SWAP_ALT_DEL
// Swap ALT and DEL
@ -848,35 +862,26 @@ void emu_InitJoysticks(void) {
gpio_set_dir(4, GPIO_OUT);
gpio_set_dir(5, GPIO_OUT);
gpio_set_dir(14, GPIO_OUT);
gpio_put(1, 1);
gpio_put(2, 1);
gpio_put(3, 1);
gpio_put(4, 1);
gpio_put(5, 1);
gpio_put(14, 1);
/*
gpio_put(1, 0);
gpio_put(2, 0);
gpio_put(3, 0);
gpio_put(4, 0);
gpio_put(5, 0);
gpio_put(14, 0);
gpio_set_pulls(1,true,true);
gpio_set_pulls(2,true,true);
gpio_set_pulls(3,true,true);
gpio_set_pulls(4,true,true);
gpio_set_pulls(5,true,true);
gpio_set_pulls(14,true,true);
// but set as input floating when not used!
gpio_set_dir(1, GPIO_IN);
gpio_set_dir(2, GPIO_IN);
gpio_set_dir(3, GPIO_IN);
gpio_set_dir(4, GPIO_IN);
gpio_set_dir(5, GPIO_IN);
gpio_set_dir(14, GPIO_IN);
*/
gpio_set_dir(14, GPIO_IN);
gpio_disable_pulls(1);
gpio_disable_pulls(2);
gpio_disable_pulls(3);
gpio_disable_pulls(4);
gpio_disable_pulls(5);
gpio_disable_pulls(14);
// Input pins (cols)
gpio_init(6);
gpio_init(9);
@ -884,18 +889,18 @@ void emu_InitJoysticks(void) {
gpio_init(8);
gpio_init(7);
gpio_init(22);
gpio_set_pulls(6,true,false);
gpio_set_dir(6,GPIO_IN);
gpio_set_pulls(9,true,false);
gpio_set_dir(9,GPIO_IN);
gpio_set_pulls(15,true,false);
gpio_set_dir(15,GPIO_IN);
gpio_set_pulls(8,true,false);
gpio_set_dir(8,GPIO_IN);
gpio_set_pulls(7,true,false);
gpio_set_dir(7,GPIO_IN);
gpio_set_pulls(22,true,false);
gpio_set_dir(22,GPIO_IN);
gpio_pull_up(6);
gpio_pull_up(9);
gpio_pull_up(15);
gpio_pull_up(8);
gpio_pull_up(7);
gpio_pull_up(22);
#endif
}

Wyświetl plik

@ -38,6 +38,9 @@
{ 5,17,16,1,44}, // bnm. <space>
*/
#define keylables_map1_0 (char *)"qwertyuiop\x1a"
#define keylables_map1_1 (char *)" asdfghjkl\x19"
#define keylables_map1_2 (char *)" zxcvbnm.\x10 "
const unsigned short key_map1[] = {
20,26,8,21,23,28,24,12,18,19,39+64,
0, 4, 22, 7,9, 10,11,13,14,15,40,
@ -45,6 +48,9 @@ const unsigned short key_map1[] = {
0,0,0,0 //up,left,right,down
};
#define keylables_map2_0 (char *)"1234567890="
#define keylables_map2_1 (char *)" $ + *- "
#define keylables_map2_2 (char *)" ()?/\"<>,: "
const unsigned short key_map2[] = {
30,31,32,33,34,35,36,37,38,39,15+64,
0, 0,0,0,24+64,0,14+64,0,5+64,13+64,0,
@ -52,6 +58,9 @@ const unsigned short key_map2[] = {
36+64,34+64,37+64,35+64 //up,left,right,down
};
#define keylables_map3_0 (char *)" "
#define keylables_map3_1 (char *)" "
#define keylables_map3_2 (char *)" ; "
const unsigned short key_map3[] = {
0, 0,0,0,0,0,0,0,0,0,0, // Upper case
0, 0,0,0,0,0,0,0,0,0,0,

Wyświetl plik

@ -263,27 +263,28 @@ void SetColor(byte N,byte R,byte G,byte B)
void Joysticks(void)
{
int k;
int j;
int ij;
//int j;
int hk;
int N=0;
word JS[2] = { 0xFFFF,0xFFFF };
k=emu_ReadKeys();
j=emu_GetPad();
ij=emu_ReadI2CKeyboard();
k = emu_GetPad() & 0x7fff;
hk = emu_ReadI2CKeyboard();
if (j & 0x8000) N = 1;
else N = 0;
//if (j & 0x8000) N = 1;
//else N = 0;
if(j)
JS[N]=(JS[N]&0xFFF0)|(j-1);
if(ij)
JS[N]=(JS[N]&0xFFF0)|(ij-1);
if(k)
JS[N]=(JS[N]&0xFFF0)|(k-1);
if(hk)
JS[N]=(JS[N]&0xFFF0)|(hk-1);
if (k & MASK_JOY2_BTN)
{
JS[N]&=0xBFFF; //Fire 1
}
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
#else
if (k & MASK_KEY_USER1)
{
JS[N]&=0xFFBF; //Fire 2
@ -292,6 +293,7 @@ void Joysticks(void)
{
JS[0]=(JS[0]&0xFFF0)|(2); //1
}
#endif
// JS[0]=(JS[0]&0xFFF0)|(12);
// JS[0]=(JS[0]&0xFFF0)|(13);

Wyświetl plik

@ -13,11 +13,19 @@ extern "C" {
#include "iopins.h"
}
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
// Dual display config, initialize TFT
#include "tft_t_dma.h"
static TFT_T_DMA tft;
#else
// Non Dual display config
#ifdef USE_VGA
#include "vga_t_dma.h"
#else
#include "tft_t_dma.h"
#endif
extern TFT_T_DMA tft;
#endif
#define MAX_FILES 64
@ -39,7 +47,7 @@ extern "C" {
#define MENU_VGA_XOFFSET (MENU_FILE_XOFFSET+MENU_FILE_W+8)
#define MENU_VGA_YOFFSET (MENU_VBAR_YOFFSET+MENU_FILE_H-32-37)
extern TFT_T_DMA tft;
static char romspath[64];
static int nbFiles=0;
@ -142,8 +150,175 @@ void emu_Free(void * pt)
free(pt);
}
void emu_drawText(unsigned short x, unsigned short y, const char * text, unsigned short fgcolor, unsigned short bgcolor, int doublesize)
{
tft.drawText(x, y, text, fgcolor, bgcolor, doublesize?true:false);
}
/********************************
* OSKB handling
********************************/
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
// On screen keyboard position
#define KXOFF 28 //64
#define KYOFF 96
#define KWIDTH 11 //22
#define KHEIGHT 3
static bool oskbOn = false;
static int cxpos = 0;
static int cypos = 0;
static int oskbMap = 0;
static uint16_t oskbBLastState = 0;
static void lineOSKB2(int kxoff, int kyoff, char * str, int row)
{
char c[2] = {'A',0};
const char * cpt = str;
for (int i=0; i<KWIDTH; i++)
{
c[0] = *cpt++;
c[1] = 0;
uint16_t bg = RGBVAL16(0x00,0x00,0xff);
if ( (cxpos == i) && (cypos == row) ) bg = RGBVAL16(0xff,0x00,0x00);
tft.drawTextNoDma(kxoff+8*i,kyoff, &c[0], RGBVAL16(0x00,0xff,0xff), bg, ((i&1)?false:true));
}
}
static void lineOSKB(int kxoff, int kyoff, char * str, int row)
{
char c[4] = {' ',0,' ',0};
const char * cpt = str;
for (int i=0; i<KWIDTH; i++)
{
c[1] = *cpt++;
uint16_t bg;
if (row&1) bg = (i&1)?RGBVAL16(0xff,0xff,0xff):RGBVAL16(0xe0,0xe0,0xe0);
else bg = (i&1)?RGBVAL16(0xe0,0xe0,0xe0):RGBVAL16(0xff,0xff,0xff);
if ( (cxpos == i) && (cypos == row) ) bg = RGBVAL16(0x00,0xff,0xff);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+0 , " ", RGBVAL16(0x00,0x00,0x00), bg, false);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+8 , &c[0], RGBVAL16(0x00,0x00,0x00), bg, true);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+24, " ", RGBVAL16(0x00,0x00,0x00), bg, false);
}
}
static void drawOskb(void)
{
// lineOSKB2(KXOFF,KYOFF+0, (char *)"Q1W2E3R4T5Y6U7I8O9P0<=", 0);
// lineOSKB2(KXOFF,KYOFF+16, (char *)" A!S@D#F$G%H+J&K*L-EN", 1);
// lineOSKB2(KXOFF,KYOFF+32, (char *)" Z(X)C?V/B\"N<M>.,SP ", 2);
if (oskbMap == 0) {
lineOSKB(KXOFF,KYOFF, keylables_map1_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map1_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map1_2, 2);
}
else if (oskbMap == 1) {
lineOSKB(KXOFF,KYOFF, keylables_map2_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map2_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map2_2, 2);
}
else {
lineOSKB(KXOFF,KYOFF, keylables_map3_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map3_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map3_2, 2);
}
}
void toggleOskb(bool forceoff) {
if (forceoff) oskbOn=true;
if (oskbOn) {
oskbOn = false;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,32, "Press USER2 to toggle onscreen keyboard.", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0x00,0x00,0x00), true);
} else {
oskbOn = true;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,32, " Press USER2 to exit onscreen keyboard. ", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0x00,0x00,0x00), true);
tft.drawTextNoDma(0,64, " (USER1 to toggle between keymaps) ", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
tft.drawRectNoDma(KXOFF,KYOFF, 22*8, 3*16, RGBVAL16(0x00,0x00,0xFF));
drawOskb();
}
}
static int handleOskb(void)
{
int retval = 0;
uint16_t bClick = bLastState & ~oskbBLastState;
oskbBLastState = bLastState;
/*
static const char * digits = "0123456789ABCDEF";
char buf[5] = {0,0,0,0,0};
int val = bClick;
buf[0] = digits[(val>>12)&0xf];
buf[1] = digits[(val>>8)&0xf];
buf[2] = digits[(val>>4)&0xf];
buf[3] = digits[val&0xf];
tft.drawTextNoDma(0,KYOFF+ 64,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),1);
*/
if (bClick & MASK_KEY_USER2)
{
toggleOskb(false);
}
if (oskbOn)
{
bool updated = true;
if (bClick & MASK_KEY_USER1)
{
oskbMap += 1;
if (oskbMap == 3) oskbMap = 0;
}
else if (bClick & MASK_JOY2_LEFT)
{
cxpos++;
if (cxpos >= KWIDTH) cxpos = 0;
}
else if (bClick & MASK_JOY2_RIGHT)
{
cxpos--;
if (cxpos < 0) cxpos = KWIDTH-1;
}
else if (bClick & MASK_JOY2_DOWN)
{
cypos++;
if (cypos >= KHEIGHT) cypos = 0;
}
else if (bClick & MASK_JOY2_UP)
{
cypos--;
if (cypos < 0) cypos = KHEIGHT-1;
}
else if (oskbBLastState & MASK_JOY2_BTN)
{
retval = cypos*KWIDTH+cxpos+1;
if (retval) {
retval--;
//if (retval & 1) retval = key_map2[retval>>1];
//else retval = key_map1[retval>>1];
if (oskbMap == 0) {
retval = key_map1[retval];
}
else if (oskbMap == 1) {
retval = key_map2[retval];
}
else {
retval = key_map3[retval];
}
if (retval) { toggleOskb(true); updated=false; };
}
}
else {
updated=false;
}
if (updated) drawOskb();
}
return retval;
}
#endif
/********************************
* Input and keyboard
********************************/
@ -318,13 +493,15 @@ int emu_ReadKeys(void)
keymatrix_hitrow = -1;
unsigned char row;
unsigned short cols[6]={1,2,3,4,5,14};
unsigned char keymatrixtmp[6];
for (int i=0;i<6;i++){
// gpio_set_dir(cols[i], GPIO_OUT);
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
@ -335,27 +512,80 @@ int emu_ReadKeys(void)
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
// gpio_set_dir(cols[i], GPIO_IN);
keymatrix[i]=row;
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] = row;
}
#ifdef MULTI_DEBOUNCE
for (int i=0;i<6;i++){
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(8) ? 0 : 0x02);
row |= (gpio_get(6) ? 0 : 0x04);
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
for (int i=0;i<6;i++){
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(8) ? 0 : 0x02);
row |= (gpio_get(6) ? 0 : 0x04);
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
#endif
#ifdef SWAP_ALT_DEL
// Swap ALT and DEL
unsigned char alt = keymatrix[0] & 0x02;
unsigned char del = keymatrix[5] & 0x20;
keymatrix[0] &= ~0x02;
keymatrix[5] &= ~0x20;
if (alt) keymatrix[5] |= 0x20;
if (del) keymatrix[0] |= 0x02;
unsigned char alt = keymatrixtmp[0] & 0x02;
unsigned char del = keymatrixtmp[5] & 0x20;
keymatrixtmp[0] &= ~0x02;
keymatrixtmp[5] &= ~0x20;
if (alt) keymatrixtmp[5] |= 0x20;
if (del) keymatrixtmp[0] |= 0x02;
#endif
bool alt_pressed=false;
if ( keymatrix[5] & 0x20 ) {alt_pressed=true; keymatrix[5] &= ~0x20;};
if ( keymatrixtmp[5] & 0x20 ) {alt_pressed=true; keymatrixtmp[5] &= ~0x20;};
for (int i=0;i<6;i++){
row = keymatrix[i];
row = keymatrixtmp[i];
if (row) keymatrix_hitrow=i;
keymatrix[i] = row;
}
//6,9,15,8,7,22
@ -399,7 +629,8 @@ int emu_ReadKeys(void)
hundred_ms_cnt += 1; // 2
if (hundred_ms_cnt >= 2)
{
hundred_ms_cnt = 0;
hundred_ms_cnt = 0;
/*
if ( (time_ms-keypress_t_ms) < 500)
{
if (key_alt == false)
@ -411,13 +642,14 @@ int emu_ReadKeys(void)
key_alt = false;
}
}
*/
}
}
}
else {
// Keep press
if (hundred_ms_cnt == 1) {
if ((to_ms_since_boot (get_absolute_time())-keypress_t_ms) > 1000)
if ((to_ms_since_boot (get_absolute_time())-keypress_t_ms) > 2000)
{
if (key_alt == false)
{
@ -460,6 +692,12 @@ int emu_ReadKeys(void)
|| (retval & MASK_KEY_USER4 ) )
{
}
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
if (oskbOn) {
retval |= MASK_OSKB;
}
#endif
return (retval);
}
@ -487,8 +725,6 @@ int emu_ReadI2CKeyboard(void) {
}
if (keymatrix_hitrow >=0 ) {
unsigned short match = ((unsigned short)keymatrix_hitrow<<8) | keymatrix[keymatrix_hitrow];
//if ( (match == 0x002 ) ) return 0; // shift or fn
//if (match < 0x100 ) match = match & ~0x002; // ignore shift key
for (int i=0; i<sizeof(matkeys)/sizeof(unsigned short); i++) {
if (match == matkeys[i]) {
hundred_ms_cnt = 0;
@ -497,6 +733,11 @@ int emu_ReadI2CKeyboard(void) {
}
}
#endif
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
if (!menuOn) {
retval = handleOskb();
}
#endif
return(retval);
}
@ -621,35 +862,26 @@ void emu_InitJoysticks(void) {
gpio_set_dir(4, GPIO_OUT);
gpio_set_dir(5, GPIO_OUT);
gpio_set_dir(14, GPIO_OUT);
gpio_put(1, 1);
gpio_put(2, 1);
gpio_put(3, 1);
gpio_put(4, 1);
gpio_put(5, 1);
gpio_put(14, 1);
/*
gpio_put(1, 0);
gpio_put(2, 0);
gpio_put(3, 0);
gpio_put(4, 0);
gpio_put(5, 0);
gpio_put(14, 0);
gpio_set_pulls(1,true,true);
gpio_set_pulls(2,true,true);
gpio_set_pulls(3,true,true);
gpio_set_pulls(4,true,true);
gpio_set_pulls(5,true,true);
gpio_set_pulls(14,true,true);
// but set as input floating when not used!
gpio_set_dir(1, GPIO_IN);
gpio_set_dir(2, GPIO_IN);
gpio_set_dir(3, GPIO_IN);
gpio_set_dir(4, GPIO_IN);
gpio_set_dir(5, GPIO_IN);
gpio_set_dir(14, GPIO_IN);
*/
gpio_set_dir(14, GPIO_IN);
gpio_disable_pulls(1);
gpio_disable_pulls(2);
gpio_disable_pulls(3);
gpio_disable_pulls(4);
gpio_disable_pulls(5);
gpio_disable_pulls(14);
// Input pins (cols)
gpio_init(6);
gpio_init(9);
@ -657,18 +889,18 @@ void emu_InitJoysticks(void) {
gpio_init(8);
gpio_init(7);
gpio_init(22);
gpio_set_pulls(6,true,false);
gpio_set_dir(6,GPIO_IN);
gpio_set_pulls(9,true,false);
gpio_set_dir(9,GPIO_IN);
gpio_set_pulls(15,true,false);
gpio_set_dir(15,GPIO_IN);
gpio_set_pulls(8,true,false);
gpio_set_dir(8,GPIO_IN);
gpio_set_pulls(7,true,false);
gpio_set_dir(7,GPIO_IN);
gpio_set_pulls(22,true,false);
gpio_set_dir(22,GPIO_IN);
gpio_pull_up(6);
gpio_pull_up(9);
gpio_pull_up(15);
gpio_pull_up(8);
gpio_pull_up(7);
gpio_pull_up(22);
#endif
}
@ -722,6 +954,14 @@ void backgroundMenu(void) {
tft.drawTextNoDma(0,0, TITLE, RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
}
static void menuLeft(void)
{
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
toggleOskb(true);
#endif
}
int handleMenu(uint16_t bClick)
{
int action = ACTION_NONE;
@ -741,12 +981,13 @@ int handleMenu(uint16_t bClick)
strcpy(romspath,newpath);
curFile = 0;
nbFiles = readNbFiles(newpath);
menuRedraw=true;
}
else
{
action = ACTION_RUNTFT;
action = ACTION_RUNTFT;
menuLeft();
}
menuRedraw=true;
}
else if ( (bClick & MASK_KEY_USER1) ) {
menuRedraw=true;
@ -980,6 +1221,11 @@ int emu_LoadFile(char * filename, char * buf, int size)
********************************/
void emu_init(void)
{
// Dual display config, initialize TFT
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
tft.begin();
#endif
sd_init_driver();
FRESULT fr = f_mount(&fatfs, "0:", 1);

Wyświetl plik

@ -27,11 +27,13 @@
#ifdef KEYMAP_PRESENT
#ifdef PICOMPUTER
#define keylables_map1_0 (char *)"1234567890 "
#define keylables_map1_1 (char *)" # * "
#define keylables_map1_2 (char *)" "
const unsigned short key_map1[] = {
2,3,4,5,6,7,8,9,10,1,0,
0,11,12,0,0,0,0,0,0,0,0,
0,0,0,11,0,0,0,0,12,0,0,
0, 0,0,0,0,0,0,0,0,0,
0,0,0,0
};
@ -44,6 +46,9 @@ const unsigned short key_map1[] = {
11,1,12};
*/
#define keylables_map2_0 (char *)" "
#define keylables_map2_1 (char *)" "
#define keylables_map2_2 (char *)" "
const unsigned short key_map2[] = {
0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,
@ -51,6 +56,9 @@ const unsigned short key_map2[] = {
0,0,0,0
};
#define keylables_map3_0 (char *)" "
#define keylables_map3_1 (char *)" "
#define keylables_map3_2 (char *)" "
const unsigned short key_map3[] = {
0,0,0,0,0,0,0,0,0,0,0, // function keys
0, 0,0,0,0,0,0,0,0,0,0,
@ -65,7 +73,6 @@ const unsigned short matkeys[] = {
0x508,0x501,0x502,0x504 }; // cursor keys
#endif
#endif
#define MASK_JOY2_RIGHT 0x0001
@ -82,7 +89,7 @@ const unsigned short matkeys[] = {
#define MASK_JOY1_DOWN 0x0800
#define MASK_JOY1_BTN 0x1000
#define MASK_KEY_USER4 0x2000
#define MASK_OSKB 0x8000
extern void emu_init(void);
extern void emu_start(void);

Wyświetl plik

@ -16,6 +16,7 @@ extern "C" {
#include "vga_t_dma.h"
#else
#include "tft_t_dma.h"
#endif
volatile bool vbl=true;
bool repeating_timer_callback(struct repeating_timer *t) {
@ -26,7 +27,6 @@ bool repeating_timer_callback(struct repeating_timer *t) {
}
return true;
}
#endif
TFT_T_DMA tft;
static int skip=0;
@ -60,17 +60,15 @@ int main(void) {
emu_Init(filename);
tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
tft.startDMA();
#ifndef USE_VGA
struct repeating_timer timer;
add_repeating_timer_ms(25, repeating_timer_callback, NULL, &timer);
#endif
}
tft.waitSync();
}
else {
emu_Step();
uint16_t bClick = emu_DebounceLocalKeys();
emu_Input(bClick);
emu_Step();
}
//int c = getchar_timeout_us(0);
//switch (c) {

Wyświetl plik

@ -13,11 +13,19 @@ extern "C" {
#include "iopins.h"
}
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
// Dual display config, initialize TFT
#include "tft_t_dma.h"
static TFT_T_DMA tft;
#else
// Non Dual display config
#ifdef USE_VGA
#include "vga_t_dma.h"
#else
#include "tft_t_dma.h"
#endif
extern TFT_T_DMA tft;
#endif
#define MAX_FILES 64
@ -39,7 +47,7 @@ extern "C" {
#define MENU_VGA_XOFFSET (MENU_FILE_XOFFSET+MENU_FILE_W+8)
#define MENU_VGA_YOFFSET (MENU_VBAR_YOFFSET+MENU_FILE_H-32-37)
extern TFT_T_DMA tft;
static char romspath[64];
static int nbFiles=0;
@ -142,8 +150,175 @@ void emu_Free(void * pt)
free(pt);
}
void emu_drawText(unsigned short x, unsigned short y, const char * text, unsigned short fgcolor, unsigned short bgcolor, int doublesize)
{
tft.drawText(x, y, text, fgcolor, bgcolor, doublesize?true:false);
}
/********************************
* OSKB handling
********************************/
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
// On screen keyboard position
#define KXOFF 28 //64
#define KYOFF 96
#define KWIDTH 11 //22
#define KHEIGHT 3
static bool oskbOn = false;
static int cxpos = 0;
static int cypos = 0;
static int oskbMap = 0;
static uint16_t oskbBLastState = 0;
static void lineOSKB2(int kxoff, int kyoff, char * str, int row)
{
char c[2] = {'A',0};
const char * cpt = str;
for (int i=0; i<KWIDTH; i++)
{
c[0] = *cpt++;
c[1] = 0;
uint16_t bg = RGBVAL16(0x00,0x00,0xff);
if ( (cxpos == i) && (cypos == row) ) bg = RGBVAL16(0xff,0x00,0x00);
tft.drawTextNoDma(kxoff+8*i,kyoff, &c[0], RGBVAL16(0x00,0xff,0xff), bg, ((i&1)?false:true));
}
}
static void lineOSKB(int kxoff, int kyoff, char * str, int row)
{
char c[4] = {' ',0,' ',0};
const char * cpt = str;
for (int i=0; i<KWIDTH; i++)
{
c[1] = *cpt++;
uint16_t bg;
if (row&1) bg = (i&1)?RGBVAL16(0xff,0xff,0xff):RGBVAL16(0xe0,0xe0,0xe0);
else bg = (i&1)?RGBVAL16(0xe0,0xe0,0xe0):RGBVAL16(0xff,0xff,0xff);
if ( (cxpos == i) && (cypos == row) ) bg = RGBVAL16(0x00,0xff,0xff);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+0 , " ", RGBVAL16(0x00,0x00,0x00), bg, false);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+8 , &c[0], RGBVAL16(0x00,0x00,0x00), bg, true);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+24, " ", RGBVAL16(0x00,0x00,0x00), bg, false);
}
}
static void drawOskb(void)
{
// lineOSKB2(KXOFF,KYOFF+0, (char *)"Q1W2E3R4T5Y6U7I8O9P0<=", 0);
// lineOSKB2(KXOFF,KYOFF+16, (char *)" A!S@D#F$G%H+J&K*L-EN", 1);
// lineOSKB2(KXOFF,KYOFF+32, (char *)" Z(X)C?V/B\"N<M>.,SP ", 2);
if (oskbMap == 0) {
lineOSKB(KXOFF,KYOFF, keylables_map1_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map1_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map1_2, 2);
}
else if (oskbMap == 1) {
lineOSKB(KXOFF,KYOFF, keylables_map2_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map2_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map2_2, 2);
}
else {
lineOSKB(KXOFF,KYOFF, keylables_map3_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map3_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map3_2, 2);
}
}
void toggleOskb(bool forceoff) {
if (forceoff) oskbOn=true;
if (oskbOn) {
oskbOn = false;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,32, "Press USER2 to toggle onscreen keyboard.", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0x00,0x00,0x00), true);
} else {
oskbOn = true;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,32, " Press USER2 to exit onscreen keyboard. ", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0x00,0x00,0x00), true);
tft.drawTextNoDma(0,64, " (USER1 to toggle between keymaps) ", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
tft.drawRectNoDma(KXOFF,KYOFF, 22*8, 3*16, RGBVAL16(0x00,0x00,0xFF));
drawOskb();
}
}
static int handleOskb(void)
{
int retval = 0;
uint16_t bClick = bLastState & ~oskbBLastState;
oskbBLastState = bLastState;
/*
static const char * digits = "0123456789ABCDEF";
char buf[5] = {0,0,0,0,0};
int val = bClick;
buf[0] = digits[(val>>12)&0xf];
buf[1] = digits[(val>>8)&0xf];
buf[2] = digits[(val>>4)&0xf];
buf[3] = digits[val&0xf];
tft.drawTextNoDma(0,KYOFF+ 64,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),1);
*/
if (bClick & MASK_KEY_USER2)
{
toggleOskb(false);
}
if (oskbOn)
{
bool updated = true;
if (bClick & MASK_KEY_USER1)
{
oskbMap += 1;
if (oskbMap == 3) oskbMap = 0;
}
else if (bClick & MASK_JOY2_LEFT)
{
cxpos++;
if (cxpos >= KWIDTH) cxpos = 0;
}
else if (bClick & MASK_JOY2_RIGHT)
{
cxpos--;
if (cxpos < 0) cxpos = KWIDTH-1;
}
else if (bClick & MASK_JOY2_DOWN)
{
cypos++;
if (cypos >= KHEIGHT) cypos = 0;
}
else if (bClick & MASK_JOY2_UP)
{
cypos--;
if (cypos < 0) cypos = KHEIGHT-1;
}
else if (oskbBLastState & MASK_JOY2_BTN)
{
retval = cypos*KWIDTH+cxpos+1;
if (retval) {
retval--;
//if (retval & 1) retval = key_map2[retval>>1];
//else retval = key_map1[retval>>1];
if (oskbMap == 0) {
retval = key_map1[retval];
}
else if (oskbMap == 1) {
retval = key_map2[retval];
}
else {
retval = key_map3[retval];
}
//if (retval) { toggleOskb(true); updated=false; };
}
}
else {
updated=false;
}
if (updated) drawOskb();
}
return retval;
}
#endif
/********************************
* Input and keyboard
********************************/
@ -318,13 +493,15 @@ int emu_ReadKeys(void)
keymatrix_hitrow = -1;
unsigned char row;
unsigned short cols[6]={1,2,3,4,5,14};
unsigned char keymatrixtmp[6];
for (int i=0;i<6;i++){
// gpio_set_dir(cols[i], GPIO_OUT);
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
@ -335,27 +512,80 @@ int emu_ReadKeys(void)
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
// gpio_set_dir(cols[i], GPIO_IN);
keymatrix[i]=row;
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] = row;
}
#ifdef MULTI_DEBOUNCE
for (int i=0;i<6;i++){
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(8) ? 0 : 0x02);
row |= (gpio_get(6) ? 0 : 0x04);
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
for (int i=0;i<6;i++){
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(8) ? 0 : 0x02);
row |= (gpio_get(6) ? 0 : 0x04);
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
#endif
#ifdef SWAP_ALT_DEL
// Swap ALT and DEL
unsigned char alt = keymatrix[0] & 0x02;
unsigned char del = keymatrix[5] & 0x20;
keymatrix[0] &= ~0x02;
keymatrix[5] &= ~0x20;
if (alt) keymatrix[5] |= 0x20;
if (del) keymatrix[0] |= 0x02;
unsigned char alt = keymatrixtmp[0] & 0x02;
unsigned char del = keymatrixtmp[5] & 0x20;
keymatrixtmp[0] &= ~0x02;
keymatrixtmp[5] &= ~0x20;
if (alt) keymatrixtmp[5] |= 0x20;
if (del) keymatrixtmp[0] |= 0x02;
#endif
bool alt_pressed=false;
if ( keymatrix[5] & 0x20 ) {alt_pressed=true; keymatrix[5] &= ~0x20;};
if ( keymatrixtmp[5] & 0x20 ) {alt_pressed=true; keymatrixtmp[5] &= ~0x20;};
for (int i=0;i<6;i++){
row = keymatrix[i];
row = keymatrixtmp[i];
if (row) keymatrix_hitrow=i;
keymatrix[i] = row;
}
//6,9,15,8,7,22
@ -399,7 +629,8 @@ int emu_ReadKeys(void)
hundred_ms_cnt += 1; // 2
if (hundred_ms_cnt >= 2)
{
hundred_ms_cnt = 0;
hundred_ms_cnt = 0;
/*
if ( (time_ms-keypress_t_ms) < 500)
{
if (key_alt == false)
@ -411,13 +642,14 @@ int emu_ReadKeys(void)
key_alt = false;
}
}
*/
}
}
}
else {
// Keep press
if (hundred_ms_cnt == 1) {
if ((to_ms_since_boot (get_absolute_time())-keypress_t_ms) > 1000)
if ((to_ms_since_boot (get_absolute_time())-keypress_t_ms) > 2000)
{
if (key_alt == false)
{
@ -460,6 +692,12 @@ int emu_ReadKeys(void)
|| (retval & MASK_KEY_USER4 ) )
{
}
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
if (oskbOn) {
retval |= MASK_OSKB;
}
#endif
return (retval);
}
@ -487,8 +725,6 @@ int emu_ReadI2CKeyboard(void) {
}
if (keymatrix_hitrow >=0 ) {
unsigned short match = ((unsigned short)keymatrix_hitrow<<8) | keymatrix[keymatrix_hitrow];
//if ( (match == 0x002 ) ) return 0; // shift or fn
//if (match < 0x100 ) match = match & ~0x002; // ignore shift key
for (int i=0; i<sizeof(matkeys)/sizeof(unsigned short); i++) {
if (match == matkeys[i]) {
hundred_ms_cnt = 0;
@ -497,6 +733,11 @@ int emu_ReadI2CKeyboard(void) {
}
}
#endif
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
if (!menuOn) {
retval = handleOskb();
}
#endif
return(retval);
}
@ -621,35 +862,26 @@ void emu_InitJoysticks(void) {
gpio_set_dir(4, GPIO_OUT);
gpio_set_dir(5, GPIO_OUT);
gpio_set_dir(14, GPIO_OUT);
gpio_put(1, 1);
gpio_put(2, 1);
gpio_put(3, 1);
gpio_put(4, 1);
gpio_put(5, 1);
gpio_put(14, 1);
/*
gpio_put(1, 0);
gpio_put(2, 0);
gpio_put(3, 0);
gpio_put(4, 0);
gpio_put(5, 0);
gpio_put(14, 0);
gpio_set_pulls(1,true,true);
gpio_set_pulls(2,true,true);
gpio_set_pulls(3,true,true);
gpio_set_pulls(4,true,true);
gpio_set_pulls(5,true,true);
gpio_set_pulls(14,true,true);
// but set as input floating when not used!
gpio_set_dir(1, GPIO_IN);
gpio_set_dir(2, GPIO_IN);
gpio_set_dir(3, GPIO_IN);
gpio_set_dir(4, GPIO_IN);
gpio_set_dir(5, GPIO_IN);
gpio_set_dir(14, GPIO_IN);
*/
gpio_set_dir(14, GPIO_IN);
gpio_disable_pulls(1);
gpio_disable_pulls(2);
gpio_disable_pulls(3);
gpio_disable_pulls(4);
gpio_disable_pulls(5);
gpio_disable_pulls(14);
// Input pins (cols)
gpio_init(6);
gpio_init(9);
@ -657,18 +889,18 @@ void emu_InitJoysticks(void) {
gpio_init(8);
gpio_init(7);
gpio_init(22);
gpio_set_pulls(6,true,false);
gpio_set_dir(6,GPIO_IN);
gpio_set_pulls(9,true,false);
gpio_set_dir(9,GPIO_IN);
gpio_set_pulls(15,true,false);
gpio_set_dir(15,GPIO_IN);
gpio_set_pulls(8,true,false);
gpio_set_dir(8,GPIO_IN);
gpio_set_pulls(7,true,false);
gpio_set_dir(7,GPIO_IN);
gpio_set_pulls(22,true,false);
gpio_set_dir(22,GPIO_IN);
gpio_pull_up(6);
gpio_pull_up(9);
gpio_pull_up(15);
gpio_pull_up(8);
gpio_pull_up(7);
gpio_pull_up(22);
#endif
}
@ -722,6 +954,14 @@ void backgroundMenu(void) {
tft.drawTextNoDma(0,0, TITLE, RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
}
static void menuLeft(void)
{
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
toggleOskb(true);
#endif
}
int handleMenu(uint16_t bClick)
{
int action = ACTION_NONE;
@ -741,12 +981,13 @@ int handleMenu(uint16_t bClick)
strcpy(romspath,newpath);
curFile = 0;
nbFiles = readNbFiles(newpath);
menuRedraw=true;
}
else
{
action = ACTION_RUNTFT;
action = ACTION_RUNTFT;
menuLeft();
}
menuRedraw=true;
}
else if ( (bClick & MASK_KEY_USER1) ) {
menuRedraw=true;
@ -980,6 +1221,11 @@ int emu_LoadFile(char * filename, char * buf, int size)
********************************/
void emu_init(void)
{
// Dual display config, initialize TFT
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
tft.begin();
#endif
sd_init_driver();
FRESULT fr = f_mount(&fatfs, "0:", 1);

Wyświetl plik

@ -29,15 +29,20 @@
#ifdef KEYMAP_PRESENT
#ifdef PICOMPUTER
#define keylables_map1_0 (char *)"12 "
#define keylables_map1_1 (char *)" "
#define keylables_map1_2 (char *)" "
const unsigned short key_map1[] = {
0,2,3,0,0,0,0,0,0,0, 0,
2,3,0,0,0,0,0,0,0,0, 0,
0, 0,0,0,0,0,0,0,0,0,0,
0, 0,0,0,0,0,0,0,0,0, // not usable except last ones
0,0,0,0
};
#define keylables_map2_0 (char *)" "
#define keylables_map2_1 (char *)" "
#define keylables_map2_2 (char *)" "
const unsigned short key_map2[] = {
0,0,0,0,0,0,0,0,0,0, 0,
0, 0,0,0,0,0,0,0,0,0,0,
@ -46,6 +51,9 @@ const unsigned short key_map2[] = {
};
#define keylables_map3_0 (char *)" "
#define keylables_map3_1 (char *)" "
#define keylables_map3_2 (char *)" "
const unsigned short key_map3[] = {
0,0,0,0,0,0,0,0,0,0,0, // function keys
0, 0,0,0,0,0,0,0,0,0,0,
@ -60,7 +68,6 @@ const unsigned short matkeys[] = {
0x508,0x501,0x502,0x504 }; // cursor keys
#endif
#endif
@ -78,7 +85,7 @@ const unsigned short matkeys[] = {
#define MASK_JOY1_DOWN 0x0800
#define MASK_JOY1_BTN 0x1000
#define MASK_KEY_USER4 0x2000
#define MASK_OSKB 0x8000
extern void emu_init(void);

Wyświetl plik

@ -41,11 +41,6 @@ static char * lorom=0; //[MAX_ROM_SIZE];
/****************************************************************************
* Exported procedures
****************************************************************************/
void emu_KeyboardOnDown(int keymodifer, int key) {
}
void emu_KeyboardOnUp(int keymodifer, int key) {
}
void odd_Init(void)
{
@ -201,8 +196,7 @@ void odd_Stop(void)
void odd_Step(void)
{
run();
//emu_printf("s");
emu_DrawScreen((unsigned char *)getGBuf()+BORDERW/2, BMPW-BORDERW, BMPH, BMPW);
emu_DrawVsync();
}

Wyświetl plik

@ -2,7 +2,7 @@ extern void odd_Init(void);
extern void odd_Start(char * filename);
extern void odd_Stop(void);
extern void odd_Step(void);
extern void odd_Input(int key);

Wyświetl plik

@ -13,11 +13,19 @@ extern "C" {
#include "iopins.h"
}
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
// Dual display config, initialize TFT
#include "tft_t_dma.h"
static TFT_T_DMA tft;
#else
// Non Dual display config
#ifdef USE_VGA
#include "vga_t_dma.h"
#else
#include "tft_t_dma.h"
#endif
extern TFT_T_DMA tft;
#endif
#define MAX_FILES 64
@ -39,7 +47,7 @@ extern "C" {
#define MENU_VGA_XOFFSET (MENU_FILE_XOFFSET+MENU_FILE_W+8)
#define MENU_VGA_YOFFSET (MENU_VBAR_YOFFSET+MENU_FILE_H-32-37)
extern TFT_T_DMA tft;
static char romspath[64];
static int nbFiles=0;
@ -142,8 +150,176 @@ void emu_Free(void * pt)
free(pt);
}
void emu_drawText(unsigned short x, unsigned short y, const char * text, unsigned short fgcolor, unsigned short bgcolor, int doublesize)
{
tft.drawText(x, y, text, fgcolor, bgcolor, doublesize?true:false);
}
/********************************
* OSKB handling
********************************/
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
// On screen keyboard position
#define KXOFF 28 //64
#define KYOFF 96
#define KWIDTH 11 //22
#define KHEIGHT 3
static bool oskbOn = false;
static int cxpos = 0;
static int cypos = 0;
static int oskbMap = 0;
static uint16_t oskbBLastState = 0;
static void lineOSKB2(int kxoff, int kyoff, char * str, int row)
{
char c[2] = {'A',0};
const char * cpt = str;
for (int i=0; i<KWIDTH; i++)
{
c[0] = *cpt++;
c[1] = 0;
uint16_t bg = RGBVAL16(0x00,0x00,0xff);
if ( (cxpos == i) && (cypos == row) ) bg = RGBVAL16(0xff,0x00,0x00);
tft.drawTextNoDma(kxoff+8*i,kyoff, &c[0], RGBVAL16(0x00,0xff,0xff), bg, ((i&1)?false:true));
}
}
static void lineOSKB(int kxoff, int kyoff, char * str, int row)
{
char c[4] = {' ',0,' ',0};
const char * cpt = str;
for (int i=0; i<KWIDTH; i++)
{
c[1] = *cpt++;
uint16_t bg;
if (row&1) bg = (i&1)?RGBVAL16(0xff,0xff,0xff):RGBVAL16(0xe0,0xe0,0xe0);
else bg = (i&1)?RGBVAL16(0xe0,0xe0,0xe0):RGBVAL16(0xff,0xff,0xff);
if ( (cxpos == i) && (cypos == row) ) bg = RGBVAL16(0x00,0xff,0xff);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+0 , " ", RGBVAL16(0x00,0x00,0x00), bg, false);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+8 , &c[0], RGBVAL16(0x00,0x00,0x00), bg, true);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+24, " ", RGBVAL16(0x00,0x00,0x00), bg, false);
}
}
static void drawOskb(void)
{
// lineOSKB2(KXOFF,KYOFF+0, (char *)"Q1W2E3R4T5Y6U7I8O9P0<=", 0);
// lineOSKB2(KXOFF,KYOFF+16, (char *)" A!S@D#F$G%H+J&K*L-EN", 1);
// lineOSKB2(KXOFF,KYOFF+32, (char *)" Z(X)C?V/B\"N<M>.,SP ", 2);
if (oskbMap == 0) {
lineOSKB(KXOFF,KYOFF, keylables_map1_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map1_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map1_2, 2);
}
else if (oskbMap == 1) {
lineOSKB(KXOFF,KYOFF, keylables_map2_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map2_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map2_2, 2);
}
else {
lineOSKB(KXOFF,KYOFF, keylables_map3_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map3_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map3_2, 2);
}
}
void toggleOskb(bool forceoff) {
if (forceoff) oskbOn=true;
if (oskbOn) {
oskbOn = false;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,32, "Press USER2 to toggle onscreen keyboard.", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0x00,0x00,0x00), true);
} else {
oskbOn = true;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,32, " Press USER2 to exit onscreen keyboard. ", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0x00,0x00,0x00), true);
tft.drawTextNoDma(0,64, " (USER1 to toggle between keymaps) ", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
tft.drawRectNoDma(KXOFF,KYOFF, 22*8, 3*16, RGBVAL16(0x00,0x00,0xFF));
drawOskb();
}
}
static int handleOskb(void)
{
int retval = 0;
uint16_t bClick = bLastState & ~oskbBLastState;
oskbBLastState = bLastState;
if (bClick & MASK_KEY_USER2)
{
toggleOskb(false);
}
if (oskbOn)
{
bool updated = true;
if (bClick & MASK_KEY_USER1)
{
oskbMap += 1;
if (oskbMap == 3) oskbMap = 0;
}
else if (bClick & MASK_JOY2_LEFT)
{
cxpos++;
if (cxpos >= KWIDTH) cxpos = 0;
}
else if (bClick & MASK_JOY2_RIGHT)
{
cxpos--;
if (cxpos < 0) cxpos = KWIDTH-1;
}
else if (bClick & MASK_JOY2_DOWN)
{
cypos++;
if (cypos >= KHEIGHT) cypos = 0;
}
else if (bClick & MASK_JOY2_UP)
{
cypos--;
if (cypos < 0) cypos = KHEIGHT-1;
}
else if (oskbBLastState & MASK_JOY2_BTN)
{
retval = cypos*KWIDTH+cxpos+1;
if (retval) {
retval--;
//if (retval & 1) retval = key_map2[retval>>1];
//else retval = key_map1[retval>>1];
if (oskbMap == 0) {
retval = key_map1[retval];
}
else if (oskbMap == 1) {
retval = key_map2[retval];
}
else {
retval = key_map3[retval];
}
if (retval) { toggleOskb(true); updated=false; };
}
}
else {
updated=false;
}
if (updated) drawOskb();
}
/*
static const char * digits = "0123456789ABCDEF";
char buf[5] = {0,0,0,0,0};
int val = retval;
buf[0] = digits[(val>>12)&0xf];
buf[1] = digits[(val>>8)&0xf];
buf[2] = digits[(val>>4)&0xf];
buf[3] = digits[val&0xf];
tft.drawTextNoDma(0,0,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),1);
*/
return retval;
}
#endif
/********************************
* Input and keyboard
********************************/
@ -318,13 +494,15 @@ int emu_ReadKeys(void)
keymatrix_hitrow = -1;
unsigned char row;
unsigned short cols[6]={1,2,3,4,5,14};
unsigned char keymatrixtmp[6];
for (int i=0;i<6;i++){
// gpio_set_dir(cols[i], GPIO_OUT);
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
@ -335,27 +513,80 @@ int emu_ReadKeys(void)
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
// gpio_set_dir(cols[i], GPIO_IN);
keymatrix[i]=row;
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] = row;
}
#ifdef MULTI_DEBOUNCE
for (int i=0;i<6;i++){
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(8) ? 0 : 0x02);
row |= (gpio_get(6) ? 0 : 0x04);
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
for (int i=0;i<6;i++){
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(8) ? 0 : 0x02);
row |= (gpio_get(6) ? 0 : 0x04);
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
#endif
#ifdef SWAP_ALT_DEL
// Swap ALT and DEL
unsigned char alt = keymatrix[0] & 0x02;
unsigned char del = keymatrix[5] & 0x20;
keymatrix[0] &= ~0x02;
keymatrix[5] &= ~0x20;
if (alt) keymatrix[5] |= 0x20;
if (del) keymatrix[0] |= 0x02;
unsigned char alt = keymatrixtmp[0] & 0x02;
unsigned char del = keymatrixtmp[5] & 0x20;
keymatrixtmp[0] &= ~0x02;
keymatrixtmp[5] &= ~0x20;
if (alt) keymatrixtmp[5] |= 0x20;
if (del) keymatrixtmp[0] |= 0x02;
#endif
bool alt_pressed=false;
if ( keymatrix[5] & 0x20 ) {alt_pressed=true; keymatrix[5] &= ~0x20;};
if ( keymatrixtmp[5] & 0x20 ) {alt_pressed=true; keymatrixtmp[5] &= ~0x20;};
for (int i=0;i<6;i++){
row = keymatrix[i];
row = keymatrixtmp[i];
if (row) keymatrix_hitrow=i;
keymatrix[i] = row;
}
//6,9,15,8,7,22
@ -399,7 +630,8 @@ int emu_ReadKeys(void)
hundred_ms_cnt += 1; // 2
if (hundred_ms_cnt >= 2)
{
hundred_ms_cnt = 0;
hundred_ms_cnt = 0;
/*
if ( (time_ms-keypress_t_ms) < 500)
{
if (key_alt == false)
@ -411,13 +643,14 @@ int emu_ReadKeys(void)
key_alt = false;
}
}
*/
}
}
}
else {
// Keep press
if (hundred_ms_cnt == 1) {
if ((to_ms_since_boot (get_absolute_time())-keypress_t_ms) > 1000)
if ((to_ms_since_boot (get_absolute_time())-keypress_t_ms) > 2000)
{
if (key_alt == false)
{
@ -460,6 +693,12 @@ int emu_ReadKeys(void)
|| (retval & MASK_KEY_USER4 ) )
{
}
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
if (oskbOn) {
retval |= MASK_OSKB;
}
#endif
return (retval);
}
@ -487,8 +726,6 @@ int emu_ReadI2CKeyboard(void) {
}
if (keymatrix_hitrow >=0 ) {
unsigned short match = ((unsigned short)keymatrix_hitrow<<8) | keymatrix[keymatrix_hitrow];
//if ( (match == 0x002 ) ) return 0; // shift or fn
//if (match < 0x100 ) match = match & ~0x002; // ignore shift key
for (int i=0; i<sizeof(matkeys)/sizeof(unsigned short); i++) {
if (match == matkeys[i]) {
hundred_ms_cnt = 0;
@ -497,6 +734,11 @@ int emu_ReadI2CKeyboard(void) {
}
}
#endif
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
if (!menuOn) {
retval = handleOskb();
}
#endif
return(retval);
}
@ -621,35 +863,26 @@ void emu_InitJoysticks(void) {
gpio_set_dir(4, GPIO_OUT);
gpio_set_dir(5, GPIO_OUT);
gpio_set_dir(14, GPIO_OUT);
gpio_put(1, 1);
gpio_put(2, 1);
gpio_put(3, 1);
gpio_put(4, 1);
gpio_put(5, 1);
gpio_put(14, 1);
/*
gpio_put(1, 0);
gpio_put(2, 0);
gpio_put(3, 0);
gpio_put(4, 0);
gpio_put(5, 0);
gpio_put(14, 0);
gpio_set_pulls(1,true,true);
gpio_set_pulls(2,true,true);
gpio_set_pulls(3,true,true);
gpio_set_pulls(4,true,true);
gpio_set_pulls(5,true,true);
gpio_set_pulls(14,true,true);
// but set as input floating when not used!
gpio_set_dir(1, GPIO_IN);
gpio_set_dir(2, GPIO_IN);
gpio_set_dir(3, GPIO_IN);
gpio_set_dir(4, GPIO_IN);
gpio_set_dir(5, GPIO_IN);
gpio_set_dir(14, GPIO_IN);
*/
gpio_set_dir(14, GPIO_IN);
gpio_disable_pulls(1);
gpio_disable_pulls(2);
gpio_disable_pulls(3);
gpio_disable_pulls(4);
gpio_disable_pulls(5);
gpio_disable_pulls(14);
// Input pins (cols)
gpio_init(6);
gpio_init(9);
@ -657,18 +890,18 @@ void emu_InitJoysticks(void) {
gpio_init(8);
gpio_init(7);
gpio_init(22);
gpio_set_pulls(6,true,false);
gpio_set_dir(6,GPIO_IN);
gpio_set_pulls(9,true,false);
gpio_set_dir(9,GPIO_IN);
gpio_set_pulls(15,true,false);
gpio_set_dir(15,GPIO_IN);
gpio_set_pulls(8,true,false);
gpio_set_dir(8,GPIO_IN);
gpio_set_pulls(7,true,false);
gpio_set_dir(7,GPIO_IN);
gpio_set_pulls(22,true,false);
gpio_set_dir(22,GPIO_IN);
gpio_pull_up(6);
gpio_pull_up(9);
gpio_pull_up(15);
gpio_pull_up(8);
gpio_pull_up(7);
gpio_pull_up(22);
#endif
}
@ -722,6 +955,14 @@ void backgroundMenu(void) {
tft.drawTextNoDma(0,0, TITLE, RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
}
static void menuLeft(void)
{
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
toggleOskb(true);
#endif
}
int handleMenu(uint16_t bClick)
{
int action = ACTION_NONE;
@ -741,12 +982,13 @@ int handleMenu(uint16_t bClick)
strcpy(romspath,newpath);
curFile = 0;
nbFiles = readNbFiles(newpath);
menuRedraw=true;
}
else
{
action = ACTION_RUNTFT;
action = ACTION_RUNTFT;
menuLeft();
}
menuRedraw=true;
}
else if ( (bClick & MASK_KEY_USER1) ) {
menuRedraw=true;
@ -980,6 +1222,11 @@ int emu_LoadFile(char * filename, char * buf, int size)
********************************/
void emu_init(void)
{
// Dual display config, initialize TFT
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
tft.begin();
#endif
sd_init_driver();
FRESULT fr = f_mount(&fatfs, "0:", 1);

Wyświetl plik

@ -13,7 +13,7 @@
#define emu_Init(ROM) {odd_Init();odd_Start(ROM);}
#define emu_Step() {odd_Step();}
#define emu_Input(x) {}
#define emu_Input(x) {odd_Input(x);}
#define VID_FRAME_SKIP 0x0
#define PALETTE_SIZE 256
@ -26,8 +26,10 @@
#define ACTION_RUNVGA 130
#ifdef KEYMAP_PRESENT
#ifdef PICOMPUTER
#define keylables_map1_0 (char *)"1234567890 "
#define keylables_map1_1 (char *)" "
#define keylables_map1_2 (char *)" "
const unsigned short key_map1[] = {
1,2,3,4,5,6,7,8,9,10,0,
0,0,0,0,0,0,0,0,0,0,0,
@ -56,6 +58,9 @@ const unsigned short key_map1[] = {
31,32,33,34,35,36,37,36,39,40,
*/
#define keylables_map2_0 (char *)" "
#define keylables_map2_1 (char *)" "
#define keylables_map2_2 (char *)" "
const unsigned short key_map2[] = {
0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,
@ -63,6 +68,9 @@ const unsigned short key_map2[] = {
0,0,0,0
};
#define keylables_map3_0 (char *)" "
#define keylables_map3_1 (char *)" "
#define keylables_map3_2 (char *)" "
const unsigned short key_map3[] = {
0,0,0,0,0,0,0,0,0,0,0, // function keys
0, 0,0,0,0,0,0,0,0,0,0,
@ -77,7 +85,6 @@ const unsigned short matkeys[] = {
0x508,0x501,0x502,0x504 }; // cursor keys
#endif
#endif
#define MASK_JOY2_RIGHT 0x0001
#define MASK_JOY2_LEFT 0x0002
@ -93,7 +100,7 @@ const unsigned short matkeys[] = {
#define MASK_JOY1_DOWN 0x0800
#define MASK_JOY1_BTN 0x1000
#define MASK_KEY_USER4 0x2000
#define MASK_OSKB 0x8000
extern void emu_init(void);

Wyświetl plik

@ -16,6 +16,7 @@ extern "C" {
#include "vga_t_dma.h"
#else
#include "tft_t_dma.h"
#endif
volatile bool vbl=true;
bool repeating_timer_callback(struct repeating_timer *t) {
@ -26,7 +27,6 @@ bool repeating_timer_callback(struct repeating_timer *t) {
}
return true;
}
#endif
TFT_T_DMA tft;
static int skip=0;
@ -61,17 +61,15 @@ int main(void) {
emu_Init(filename);
tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
tft.startDMA();
#ifndef USE_VGA
struct repeating_timer timer;
add_repeating_timer_ms(15, repeating_timer_callback, NULL, &timer);
#endif
}
tft.waitSync();
}
else {
emu_Step();
uint16_t bClick = emu_DebounceLocalKeys();
emu_Input(bClick);
emu_Step();
}
//int c = getchar_timeout_us(0);
//switch (c) {

Wyświetl plik

@ -129,6 +129,21 @@ static unsigned int key_map[6][8]= {
};
static int k = 0;
static int hk = 0;
void odd_Input(int key) {
k = emu_GetPad();
hk = emu_ReadI2CKeyboard() & 0x7f;
}
void emu_KeyboardOnDown(int keymodifer, int key) {
}
void emu_KeyboardOnUp(int keymodifer, int key) {
}
static void do_kluges(void);
static void setvideomode(int t);
@ -260,15 +275,14 @@ void write_p1(Byte d){
Byte read_P2(void){
int i,si,so,km;
int k;
int hksim = 0;
k=emu_GetPad()&0x7f;
int hk = emu_ReadI2CKeyboard()&0x7f;
int key = emu_ReadKeys();
if (key & MASK_KEY_USER1) { // 1
k = 1;
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
#else
if (k & MASK_KEY_USER1) { // 1
hksim = 1;
}
#endif
if (!(p1 & 0x04)) {
si = (p2 & 7);
@ -276,14 +290,18 @@ Byte read_P2(void){
if (si<6) {
for (i=0; i<8; i++) {
km = key_map[si][i];
if ( (km == (k-1)) && (k) )
{
so = i ^ 0x07;
if (hk) {
if ( km == (hk-1) )
{
so = i ^ 0x07;
}
}
else if (hksim) {
if ( km == (hksim-1) )
{
so = i ^ 0x07;
}
}
else if ( (km == (hk-1)) && (hk) )
{
so = i ^ 0x07;
}
// if ((key[km] && ((!joykeystab[km]) || (key_shifts & KB_CAPSLOCK_FLAG))) || (key2[km])) {
// so = i ^ 0x07;
// }
@ -374,8 +392,6 @@ Byte ext_read(ADDRESS adr){
Byte in_bus(void){
Byte si=0,d=0,mode=0,jn=0;
int key;
if ((p1 & 0x08) && (p1 & 0x10)) {
/* Handle joystick read */
@ -383,13 +399,17 @@ Byte in_bus(void){
si = (p2 & 7);
}
d=0xFF;
/* Get current input */
key = emu_ReadKeys();
int key = 0;
if ( !(k & MASK_OSKB) ) {
key = k;
}
app_data.stick[0]=0;
app_data.stick[1]=1;
/*
if ( emu_GetPad() & 0x80 )
if ( key & 0x80 )
{
app_data.stick[0]=1;
app_data.stick[1]=0;
@ -410,8 +430,9 @@ Byte in_bus(void){
}
*/
mode=1;
if (key & 0x8000) jn=1;
else jn=0;
//if (key & 0x8000) jn=1;
//else jn=0;
switch(mode) {
case 1:
@ -424,7 +445,6 @@ Byte in_bus(void){
case 2:
/* Get current input */
// key = emu_GetPad();
// if (key & JKEY_PLEFT) d &= 0xF7;
// if (key & JKEY_PRIGHT) d &= 0xFD;
// if (key & JKEY_PUP) d &= 0xFE;

Wyświetl plik

@ -210,19 +210,19 @@ static void drawOskb(void)
// lineOSKB2(KXOFF,KYOFF+16, (char *)" A!S@D#F$G%H+J&K*L-EN", 1);
// lineOSKB2(KXOFF,KYOFF+32, (char *)" Z(X)C?V/B\"N<M>.,SP ", 2);
if (oskbMap == 0) {
lineOSKB(KXOFF,KYOFF, (char *)"qwertyuiop\x1a", 0);
lineOSKB(KXOFF,KYOFF, (char *)" asdfghjkl\x19", 1);
lineOSKB(KXOFF,KYOFF, (char *)" zxcvbnm.\x10 ", 2);
lineOSKB(KXOFF,KYOFF, keylables_map1_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map1_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map1_2, 2);
}
else if (oskbMap == 1) {
lineOSKB(KXOFF,KYOFF, (char *)"1234567890=", 0);
lineOSKB(KXOFF,KYOFF, (char *)" !@#$%+&*- ", 1);
lineOSKB(KXOFF,KYOFF, (char *)" ()?/\"<>,: ", 2);
lineOSKB(KXOFF,KYOFF, keylables_map2_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map2_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map2_2, 2);
}
else {
lineOSKB(KXOFF,KYOFF, (char *)"QWERTYUIOP ", 0);
lineOSKB(KXOFF,KYOFF, (char *)" ASDFGHJKL ", 1);
lineOSKB(KXOFF,KYOFF, (char *)" ZXCVBNM; ", 2);
lineOSKB(KXOFF,KYOFF, keylables_map3_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map3_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map3_2, 2);
}
}
@ -306,6 +306,7 @@ static int handleOskb(void)
else {
retval = key_map3[retval];
}
//if (retval) { toggleOskb(true); updated=false; };
}
}
else {
@ -495,7 +496,12 @@ int emu_ReadKeys(void)
unsigned char keymatrixtmp[6];
for (int i=0;i<6;i++){
gpio_put(cols[i], 0);
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
@ -506,17 +512,21 @@ int emu_ReadKeys(void)
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] = row;
}
#ifdef MULTI_DEBOUNCE
for (int i=0;i<6;i++){
// gpio_set_dir(cols[i], GPIO_OUT);
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
@ -527,18 +537,20 @@ int emu_ReadKeys(void)
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
// gpio_set_dir(cols[i], GPIO_IN);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
for (int i=0;i<6;i++){
// gpio_set_dir(cols[i], GPIO_OUT);
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
@ -549,11 +561,13 @@ int emu_ReadKeys(void)
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
// gpio_set_dir(cols[i], GPIO_IN);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
#endif
#ifdef SWAP_ALT_DEL
// Swap ALT and DEL
@ -848,35 +862,26 @@ void emu_InitJoysticks(void) {
gpio_set_dir(4, GPIO_OUT);
gpio_set_dir(5, GPIO_OUT);
gpio_set_dir(14, GPIO_OUT);
gpio_put(1, 1);
gpio_put(2, 1);
gpio_put(3, 1);
gpio_put(4, 1);
gpio_put(5, 1);
gpio_put(14, 1);
/*
gpio_put(1, 0);
gpio_put(2, 0);
gpio_put(3, 0);
gpio_put(4, 0);
gpio_put(5, 0);
gpio_put(14, 0);
gpio_set_pulls(1,true,true);
gpio_set_pulls(2,true,true);
gpio_set_pulls(3,true,true);
gpio_set_pulls(4,true,true);
gpio_set_pulls(5,true,true);
gpio_set_pulls(14,true,true);
// but set as input floating when not used!
gpio_set_dir(1, GPIO_IN);
gpio_set_dir(2, GPIO_IN);
gpio_set_dir(3, GPIO_IN);
gpio_set_dir(4, GPIO_IN);
gpio_set_dir(5, GPIO_IN);
gpio_set_dir(14, GPIO_IN);
*/
gpio_set_dir(14, GPIO_IN);
gpio_disable_pulls(1);
gpio_disable_pulls(2);
gpio_disable_pulls(3);
gpio_disable_pulls(4);
gpio_disable_pulls(5);
gpio_disable_pulls(14);
// Input pins (cols)
gpio_init(6);
gpio_init(9);
@ -884,18 +889,18 @@ void emu_InitJoysticks(void) {
gpio_init(8);
gpio_init(7);
gpio_init(22);
gpio_set_pulls(6,true,false);
gpio_set_dir(6,GPIO_IN);
gpio_set_pulls(9,true,false);
gpio_set_dir(9,GPIO_IN);
gpio_set_pulls(15,true,false);
gpio_set_dir(15,GPIO_IN);
gpio_set_pulls(8,true,false);
gpio_set_dir(8,GPIO_IN);
gpio_set_pulls(7,true,false);
gpio_set_dir(7,GPIO_IN);
gpio_set_pulls(22,true,false);
gpio_set_dir(22,GPIO_IN);
gpio_pull_up(6);
gpio_pull_up(9);
gpio_pull_up(15);
gpio_pull_up(8);
gpio_pull_up(7);
gpio_pull_up(22);
#endif
}

Wyświetl plik

@ -40,6 +40,9 @@
{ 5,17,16,225,44},// bnm <symbshift=RSHift> <space>
*/
#define keylables_map1_0 (char *)"qwertyuiop\x1a"
#define keylables_map1_1 (char *)" asdfghjkl\x19"
#define keylables_map1_2 (char *)" zxcvbnm.\x10 "
const unsigned short key_map1[] = {
20,26,8,21,23,28,24,12,18,19,39+128,
0, 4, 22, 7,9, 10,11,13,14,15,40,
@ -47,6 +50,9 @@ const unsigned short key_map1[] = {
0,0,0,0 //up,left,right,down
};
#define keylables_map2_0 (char *)"1234567890="
#define keylables_map2_1 (char *)" !@#$%+&*- "
#define keylables_map2_2 (char *)" ()?/\"<>,: "
const unsigned short key_map2[] = {
30,31,32,33,34,35,36,37,38,39,15+64,
0,30+64,31+64,32+64,33+64,34+64,14+64,35+64,5+64,13+64,0,
@ -54,6 +60,9 @@ const unsigned short key_map2[] = {
36+128,34+128,37+128,35+128 //up,left,right,down
};
#define keylables_map3_0 (char *)"QWERTYUIOP "
#define keylables_map3_1 (char *)" ASDFGHJKL "
#define keylables_map3_2 (char *)" ZXCVBNM; "
const unsigned short key_map3[] = {
20+128,26+128,8+128,21+128,23+128,28+128,24+128,12+128,18+128,19+128,0, // Upper case
0, 4+128, 22+128, 7+128,9+128, 10+128,11+128,13+128,14+128,15+128,0,

Wyświetl plik

@ -41,17 +41,32 @@ extern int nOptions_P1Diff;
extern int nOptions_P2Diff;
void emu_KeyboardOnDown(int keymodifer, int key) {
}
void emu_KeyboardOnUp(int keymodifer, int key) {
}
static int k = 0;
static int hk = 0;
void vcs_Input(int key) {
k = emu_GetPad();
hk = emu_ReadI2CKeyboard() & 0xF;
}
void keyjoy(void) {
int key;
BYTE v1,v2;
v1=v2=0x0f;
// read the keyboard state. The return value (in keys) is a pointer to a
// 256 byte buffer which holds the state of all the keyboard keys. If a
// byte's upper bit is set to 1, the key is pressed.
key = emu_ReadKeys();
int key = 0;
if ( !(k & MASK_OSKB) ) {
key = k;
}
if (key & MASK_JOY2_UP) v1 &= 0x0E;
if (key & MASK_JOY2_DOWN) v1 &= 0x0D;
if (key & MASK_JOY2_RIGHT) v1 &= 0x0B;
@ -60,40 +75,41 @@ void keyjoy(void) {
riotRead[0x280]=(v1 << 4) | v2;
}
static int kswitches = 0;
void keycons(void) {
//---------------------------------------------------------
// This function reads the state of the joysticks (buttons)
//---------------------------------------------------------
int key = emu_ReadKeys();;
int sw = emu_GetPad() & 0xff;
int hk = emu_ReadI2CKeyboard();
kswitches = 0;
if (hk == 1) {
if (kswitches & 0x01)
kswitches &= ~0x01;
else
kswitches |= 0x01;
}
else if (hk == 2) {
if (kswitches & 0x02)
kswitches &= ~0x02;
else
kswitches |= 0x02;
}
else if (hk == 3) {
if (kswitches & 0x04)
kswitches &= ~0x04;
else
kswitches |= 0x04;
}
else if (hk == 4) {
if (kswitches & 0x08)
kswitches &= ~0x08;
else
kswitches |= 0x08;
int key = 0;
if ( !(k & MASK_OSKB) ) {
key = k;
}
int kswitches = 0;
if (hk) {
if (hk == 1) {
if (kswitches & 0x01)
kswitches &= ~0x01;
else
kswitches |= 0x01;
}
else if (hk == 2) {
if (kswitches & 0x02)
kswitches &= ~0x02;
else
kswitches |= 0x02;
}
else if (hk == 3) {
if (kswitches & 0x04)
kswitches &= ~0x04;
else
kswitches |= 0x04;
}
else if (hk == 4) {
if (kswitches & 0x08)
kswitches &= ~0x08;
else
kswitches |= 0x08;
}
}
@ -103,7 +119,7 @@ void keycons(void) {
riotRead[SWCHB] |= 0x03;
if ( (key & MASK_KEY_USER3) /*|| (sw == 2)*/ || (kswitches & 0x04) ) //
if ( (key & MASK_KEY_USER3) || (kswitches & 0x04) )
nOptions_Color = !nOptions_Color;
if (!nOptions_Color)
@ -112,9 +128,19 @@ void keycons(void) {
riotRead[SWCHB] |= 0x08; /* Color */
if ( (key & MASK_KEY_USER1) /*|| (sw == 4)*/ || (kswitches & 0x02) )
if ( (kswitches & 0x02)
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
#else
|| (key & MASK_KEY_USER1)
#endif
)
riotRead[SWCHB] &= 0xFE; /* Reset */
if ( (key & MASK_KEY_USER2) /*|| (sw == 3)*/ || (kswitches & 0x01) )
if ( (kswitches & 0x01)
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
#else
|| (key & MASK_KEY_USER2)
#endif
)
riotRead[SWCHB] &= 0xFD; /* Select */
if (nOptions_P1Diff) riotRead[SWCHB] &= 0xBF; /* P0 amateur */
@ -125,17 +151,17 @@ void keycons(void) {
}
void keytrig(void) {
int key;
// read the keyboard state. The return value (in keys) is a pointer to a
// 256 byte buffer which holds the state of all the keyboard keys. If a
// byte's upper bit is set to 1, the key is pressed.
key = emu_ReadKeys();
int key = 0;
if ( !(k & MASK_OSKB) ) {
key = k;
}
if (!(tiaWrite[VBLANK] & 0x40)) {
tiaRead[INPT5]=0x80;
if (key & 0x10)
if (key & MASK_JOY2_BTN)
tiaRead[INPT4]=0x00;
else
tiaRead[INPT4]=0x80;

Wyświetl plik

@ -25,12 +25,6 @@ extern void mainloop(void);
/****************************************************************************
* Exported procedures
****************************************************************************/
void emu_KeyboardOnDown(int keymodifer, int key) {
}
void emu_KeyboardOnUp(int keymodifer, int key) {
}
void vcs_Init(void)
{
init_machine();

Wyświetl plik

@ -2,7 +2,7 @@ extern void vcs_Init(void);
extern void vcs_Start(char * filename);
extern void vcs_Stop(void);
extern void vcs_Step(void);
extern void vcs_Input(int key);

Wyświetl plik

@ -13,11 +13,19 @@ extern "C" {
#include "iopins.h"
}
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
// Dual display config, initialize TFT
#include "tft_t_dma.h"
static TFT_T_DMA tft;
#else
// Non Dual display config
#ifdef USE_VGA
#include "vga_t_dma.h"
#else
#include "tft_t_dma.h"
#endif
extern TFT_T_DMA tft;
#endif
#define MAX_FILES 64
@ -39,7 +47,7 @@ extern "C" {
#define MENU_VGA_XOFFSET (MENU_FILE_XOFFSET+MENU_FILE_W+8)
#define MENU_VGA_YOFFSET (MENU_VBAR_YOFFSET+MENU_FILE_H-32-37)
extern TFT_T_DMA tft;
static char romspath[64];
static int nbFiles=0;
@ -142,8 +150,176 @@ void emu_Free(void * pt)
free(pt);
}
void emu_drawText(unsigned short x, unsigned short y, const char * text, unsigned short fgcolor, unsigned short bgcolor, int doublesize)
{
tft.drawText(x, y, text, fgcolor, bgcolor, doublesize?true:false);
}
/********************************
* OSKB handling
********************************/
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
// On screen keyboard position
#define KXOFF 28 //64
#define KYOFF 96
#define KWIDTH 11 //22
#define KHEIGHT 3
static bool oskbOn = false;
static int cxpos = 0;
static int cypos = 0;
static int oskbMap = 0;
static uint16_t oskbBLastState = 0;
static void lineOSKB2(int kxoff, int kyoff, char * str, int row)
{
char c[2] = {'A',0};
const char * cpt = str;
for (int i=0; i<KWIDTH; i++)
{
c[0] = *cpt++;
c[1] = 0;
uint16_t bg = RGBVAL16(0x00,0x00,0xff);
if ( (cxpos == i) && (cypos == row) ) bg = RGBVAL16(0xff,0x00,0x00);
tft.drawTextNoDma(kxoff+8*i,kyoff, &c[0], RGBVAL16(0x00,0xff,0xff), bg, ((i&1)?false:true));
}
}
static void lineOSKB(int kxoff, int kyoff, char * str, int row)
{
char c[4] = {' ',0,' ',0};
const char * cpt = str;
for (int i=0; i<KWIDTH; i++)
{
c[1] = *cpt++;
uint16_t bg;
if (row&1) bg = (i&1)?RGBVAL16(0xff,0xff,0xff):RGBVAL16(0xe0,0xe0,0xe0);
else bg = (i&1)?RGBVAL16(0xe0,0xe0,0xe0):RGBVAL16(0xff,0xff,0xff);
if ( (cxpos == i) && (cypos == row) ) bg = RGBVAL16(0x00,0xff,0xff);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+0 , " ", RGBVAL16(0x00,0x00,0x00), bg, false);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+8 , &c[0], RGBVAL16(0x00,0x00,0x00), bg, true);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+24, " ", RGBVAL16(0x00,0x00,0x00), bg, false);
}
}
static void drawOskb(void)
{
// lineOSKB2(KXOFF,KYOFF+0, (char *)"Q1W2E3R4T5Y6U7I8O9P0<=", 0);
// lineOSKB2(KXOFF,KYOFF+16, (char *)" A!S@D#F$G%H+J&K*L-EN", 1);
// lineOSKB2(KXOFF,KYOFF+32, (char *)" Z(X)C?V/B\"N<M>.,SP ", 2);
if (oskbMap == 0) {
lineOSKB(KXOFF,KYOFF, keylables_map1_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map1_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map1_2, 2);
}
else if (oskbMap == 1) {
lineOSKB(KXOFF,KYOFF, keylables_map2_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map2_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map2_2, 2);
}
else {
lineOSKB(KXOFF,KYOFF, keylables_map3_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map3_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map3_2, 2);
}
}
void toggleOskb(bool forceoff) {
if (forceoff) oskbOn=true;
if (oskbOn) {
oskbOn = false;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,32, "Press USER2 to toggle onscreen keyboard.", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0x00,0x00,0x00), true);
} else {
oskbOn = true;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,32, " Press USER2 to exit onscreen keyboard. ", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0x00,0x00,0x00), true);
tft.drawTextNoDma(0,64, " (USER1 to toggle between keymaps) ", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
tft.drawRectNoDma(KXOFF,KYOFF, 22*8, 3*16, RGBVAL16(0x00,0x00,0xFF));
drawOskb();
}
}
static int handleOskb(void)
{
int retval = 0;
uint16_t bClick = bLastState & ~oskbBLastState;
oskbBLastState = bLastState;
if (bClick & MASK_KEY_USER2)
{
toggleOskb(false);
}
if (oskbOn)
{
bool updated = true;
if (bClick & MASK_KEY_USER1)
{
oskbMap += 1;
if (oskbMap == 3) oskbMap = 0;
}
else if (bClick & MASK_JOY2_LEFT)
{
cxpos++;
if (cxpos >= KWIDTH) cxpos = 0;
}
else if (bClick & MASK_JOY2_RIGHT)
{
cxpos--;
if (cxpos < 0) cxpos = KWIDTH-1;
}
else if (bClick & MASK_JOY2_DOWN)
{
cypos++;
if (cypos >= KHEIGHT) cypos = 0;
}
else if (bClick & MASK_JOY2_UP)
{
cypos--;
if (cypos < 0) cypos = KHEIGHT-1;
}
else if (oskbBLastState & MASK_JOY2_BTN)
{
retval = cypos*KWIDTH+cxpos+1;
if (retval) {
retval--;
//if (retval & 1) retval = key_map2[retval>>1];
//else retval = key_map1[retval>>1];
if (oskbMap == 0) {
retval = key_map1[retval];
}
else if (oskbMap == 1) {
retval = key_map2[retval];
}
else {
retval = key_map3[retval];
}
//if (retval=2) { toggleOskb(true); updated=false; };
}
}
else {
updated=false;
}
if (updated) drawOskb();
}
/*
static const char * digits = "0123456789ABCDEF";
char buf[5] = {0,0,0,0,0};
int val = retval;
buf[0] = digits[(val>>12)&0xf];
buf[1] = digits[(val>>8)&0xf];
buf[2] = digits[(val>>4)&0xf];
buf[3] = digits[val&0xf];
tft.drawTextNoDma(0,0,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),1);
*/
return retval;
}
#endif
/********************************
* Input and keyboard
********************************/
@ -318,13 +494,15 @@ int emu_ReadKeys(void)
keymatrix_hitrow = -1;
unsigned char row;
unsigned short cols[6]={1,2,3,4,5,14};
unsigned char keymatrixtmp[6];
for (int i=0;i<6;i++){
// gpio_set_dir(cols[i], GPIO_OUT);
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
@ -335,27 +513,80 @@ int emu_ReadKeys(void)
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
// gpio_set_dir(cols[i], GPIO_IN);
keymatrix[i]=row;
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] = row;
}
#ifdef MULTI_DEBOUNCE
for (int i=0;i<6;i++){
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(8) ? 0 : 0x02);
row |= (gpio_get(6) ? 0 : 0x04);
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
for (int i=0;i<6;i++){
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(8) ? 0 : 0x02);
row |= (gpio_get(6) ? 0 : 0x04);
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
#endif
#ifdef SWAP_ALT_DEL
// Swap ALT and DEL
unsigned char alt = keymatrix[0] & 0x02;
unsigned char del = keymatrix[5] & 0x20;
keymatrix[0] &= ~0x02;
keymatrix[5] &= ~0x20;
if (alt) keymatrix[5] |= 0x20;
if (del) keymatrix[0] |= 0x02;
unsigned char alt = keymatrixtmp[0] & 0x02;
unsigned char del = keymatrixtmp[5] & 0x20;
keymatrixtmp[0] &= ~0x02;
keymatrixtmp[5] &= ~0x20;
if (alt) keymatrixtmp[5] |= 0x20;
if (del) keymatrixtmp[0] |= 0x02;
#endif
bool alt_pressed=false;
if ( keymatrix[5] & 0x20 ) {alt_pressed=true; keymatrix[5] &= ~0x20;};
if ( keymatrixtmp[5] & 0x20 ) {alt_pressed=true; keymatrixtmp[5] &= ~0x20;};
for (int i=0;i<6;i++){
row = keymatrix[i];
row = keymatrixtmp[i];
if (row) keymatrix_hitrow=i;
keymatrix[i] = row;
}
//6,9,15,8,7,22
@ -399,7 +630,8 @@ int emu_ReadKeys(void)
hundred_ms_cnt += 1; // 2
if (hundred_ms_cnt >= 2)
{
hundred_ms_cnt = 0;
hundred_ms_cnt = 0;
/*
if ( (time_ms-keypress_t_ms) < 500)
{
if (key_alt == false)
@ -411,13 +643,14 @@ int emu_ReadKeys(void)
key_alt = false;
}
}
*/
}
}
}
else {
// Keep press
if (hundred_ms_cnt == 1) {
if ((to_ms_since_boot (get_absolute_time())-keypress_t_ms) > 1000)
if ((to_ms_since_boot (get_absolute_time())-keypress_t_ms) > 2000)
{
if (key_alt == false)
{
@ -460,6 +693,12 @@ int emu_ReadKeys(void)
|| (retval & MASK_KEY_USER4 ) )
{
}
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
if (oskbOn) {
retval |= MASK_OSKB;
}
#endif
return (retval);
}
@ -487,8 +726,6 @@ int emu_ReadI2CKeyboard(void) {
}
if (keymatrix_hitrow >=0 ) {
unsigned short match = ((unsigned short)keymatrix_hitrow<<8) | keymatrix[keymatrix_hitrow];
//if ( (match == 0x002 ) ) return 0; // shift or fn
//if (match < 0x100 ) match = match & ~0x002; // ignore shift key
for (int i=0; i<sizeof(matkeys)/sizeof(unsigned short); i++) {
if (match == matkeys[i]) {
hundred_ms_cnt = 0;
@ -497,6 +734,11 @@ int emu_ReadI2CKeyboard(void) {
}
}
#endif
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
if (!menuOn) {
retval = handleOskb();
}
#endif
return(retval);
}
@ -621,35 +863,26 @@ void emu_InitJoysticks(void) {
gpio_set_dir(4, GPIO_OUT);
gpio_set_dir(5, GPIO_OUT);
gpio_set_dir(14, GPIO_OUT);
gpio_put(1, 1);
gpio_put(2, 1);
gpio_put(3, 1);
gpio_put(4, 1);
gpio_put(5, 1);
gpio_put(14, 1);
/*
gpio_put(1, 0);
gpio_put(2, 0);
gpio_put(3, 0);
gpio_put(4, 0);
gpio_put(5, 0);
gpio_put(14, 0);
gpio_set_pulls(1,true,true);
gpio_set_pulls(2,true,true);
gpio_set_pulls(3,true,true);
gpio_set_pulls(4,true,true);
gpio_set_pulls(5,true,true);
gpio_set_pulls(14,true,true);
// but set as input floating when not used!
gpio_set_dir(1, GPIO_IN);
gpio_set_dir(2, GPIO_IN);
gpio_set_dir(3, GPIO_IN);
gpio_set_dir(4, GPIO_IN);
gpio_set_dir(5, GPIO_IN);
gpio_set_dir(14, GPIO_IN);
*/
gpio_set_dir(14, GPIO_IN);
gpio_disable_pulls(1);
gpio_disable_pulls(2);
gpio_disable_pulls(3);
gpio_disable_pulls(4);
gpio_disable_pulls(5);
gpio_disable_pulls(14);
// Input pins (cols)
gpio_init(6);
gpio_init(9);
@ -657,18 +890,18 @@ void emu_InitJoysticks(void) {
gpio_init(8);
gpio_init(7);
gpio_init(22);
gpio_set_pulls(6,true,false);
gpio_set_dir(6,GPIO_IN);
gpio_set_pulls(9,true,false);
gpio_set_dir(9,GPIO_IN);
gpio_set_pulls(15,true,false);
gpio_set_dir(15,GPIO_IN);
gpio_set_pulls(8,true,false);
gpio_set_dir(8,GPIO_IN);
gpio_set_pulls(7,true,false);
gpio_set_dir(7,GPIO_IN);
gpio_set_pulls(22,true,false);
gpio_set_dir(22,GPIO_IN);
gpio_pull_up(6);
gpio_pull_up(9);
gpio_pull_up(15);
gpio_pull_up(8);
gpio_pull_up(7);
gpio_pull_up(22);
#endif
}
@ -722,6 +955,14 @@ void backgroundMenu(void) {
tft.drawTextNoDma(0,0, TITLE, RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
}
static void menuLeft(void)
{
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
toggleOskb(true);
#endif
}
int handleMenu(uint16_t bClick)
{
int action = ACTION_NONE;
@ -741,12 +982,13 @@ int handleMenu(uint16_t bClick)
strcpy(romspath,newpath);
curFile = 0;
nbFiles = readNbFiles(newpath);
menuRedraw=true;
}
else
{
action = ACTION_RUNTFT;
action = ACTION_RUNTFT;
menuLeft();
}
menuRedraw=true;
}
else if ( (bClick & MASK_KEY_USER1) ) {
menuRedraw=true;
@ -980,6 +1222,11 @@ int emu_LoadFile(char * filename, char * buf, int size)
********************************/
void emu_init(void)
{
// Dual display config, initialize TFT
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
tft.begin();
#endif
sd_init_driver();
FRESULT fr = f_mount(&fatfs, "0:", 1);

Wyświetl plik

@ -12,7 +12,7 @@
#define emu_Init(ROM) {vcs_Init();vcs_Start(ROM);}
#define emu_Step() {vcs_Step();}
#define emu_Input(x) {}
#define emu_Input(x) {vcs_Input(x);}
#define PALETTE_SIZE 256
#define VID_FRAME_SKIP 0x0
@ -26,15 +26,20 @@
#define ACTION_RUNVGA 130
#ifdef KEYMAP_PRESENT
#ifdef PICOMPUTER
#define keylables_map1_0 (char *)"1234 "
#define keylables_map1_1 (char *)" "
#define keylables_map1_2 (char *)" "
const unsigned short key_map1[] = {
0,1,2,3,4,0,0,0,0,0,0,
1,2,3,4,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,
0, 0,0,0,0,0,0,0,0,0,
0,0,0,0
};
#define keylables_map2_0 (char *)" "
#define keylables_map2_1 (char *)" "
#define keylables_map2_2 (char *)" "
const unsigned short key_map2[] = {
0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,
@ -42,6 +47,9 @@ const unsigned short key_map2[] = {
0,0,0,0
};
#define keylables_map3_0 (char *)" "
#define keylables_map3_1 (char *)" "
#define keylables_map3_2 (char *)" "
const unsigned short key_map3[] = {
0,0,0,0,0,0,0,0,0,0,0, // function keys
0, 0,0,0,0,0,0,0,0,0,0,
@ -56,7 +64,6 @@ const unsigned short matkeys[] = {
0x508,0x501,0x502,0x504 }; // cursor keys
#endif
#endif
#define MASK_JOY2_RIGHT 0x0001
#define MASK_JOY2_LEFT 0x0002
@ -72,7 +79,7 @@ const unsigned short matkeys[] = {
#define MASK_JOY1_DOWN 0x0800
#define MASK_JOY1_BTN 0x1000
#define MASK_KEY_USER4 0x2000
#define MASK_OSKB 0x8000
extern void emu_init(void);
extern void emu_start(void);

Wyświetl plik

@ -16,6 +16,7 @@ extern "C" {
#include "vga_t_dma.h"
#else
#include "tft_t_dma.h"
#endif
volatile bool vbl=true;
bool repeating_timer_callback(struct repeating_timer *t) {
@ -26,7 +27,6 @@ bool repeating_timer_callback(struct repeating_timer *t) {
}
return true;
}
#endif
TFT_T_DMA tft;
static int skip=0;
@ -61,17 +61,15 @@ int main(void) {
emu_Init(filename);
tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
tft.startDMA();
#ifndef USE_VGA
struct repeating_timer timer;
add_repeating_timer_ms(15, repeating_timer_callback, NULL, &timer);
#endif
}
tft.waitSync();
}
else {
emu_Step();
uint16_t bClick = emu_DebounceLocalKeys();
emu_Input(bClick);
emu_Step();
}
//int c = getchar_timeout_us(0);
//switch (c) {

Wyświetl plik

@ -13,8 +13,50 @@ extern "C" {
#include "iopins.h"
}
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
// Dual display config, initialize TFT
#include "tft_t_dma.h"
static TFT_T_DMA tft;
#else
// Non Dual display config
#ifdef USE_VGA
#include "vga_t_dma.h"
#else
#include "tft_t_dma.h"
#endif
extern TFT_T_DMA tft;
#endif
#define MAX_FILES 64
#define MAX_FILENAME_SIZE 24
#define MAX_MENULINES 9
#define TEXT_HEIGHT 16
#define TEXT_WIDTH 8
#define MENU_FILE_XOFFSET (6*TEXT_WIDTH)
#define MENU_FILE_YOFFSET (2*TEXT_HEIGHT)
#define MENU_FILE_W (MAX_FILENAME_SIZE*TEXT_WIDTH)
#define MENU_FILE_H (MAX_MENULINES*TEXT_HEIGHT)
#define MENU_FILE_BGCOLOR RGBVAL16(0x00,0x00,0x40)
#define MENU_JOYS_YOFFSET (12*TEXT_HEIGHT)
#define MENU_VBAR_XOFFSET (0*TEXT_WIDTH)
#define MENU_VBAR_YOFFSET (MENU_FILE_YOFFSET)
#define MENU_TFT_XOFFSET (MENU_FILE_XOFFSET+MENU_FILE_W+8)
#define MENU_TFT_YOFFSET (MENU_VBAR_YOFFSET+32)
#define MENU_VGA_XOFFSET (MENU_FILE_XOFFSET+MENU_FILE_W+8)
#define MENU_VGA_YOFFSET (MENU_VBAR_YOFFSET+MENU_FILE_H-32-37)
static char romspath[64];
static int nbFiles=0;
static int curFile=0;
static int topFile=0;
static char selection[MAX_FILENAME_SIZE+1]="";
static char files[MAX_FILES][MAX_FILENAME_SIZE];
static bool menuRedraw=true;
#ifdef PICOMPUTER
static const unsigned short * keys;
static unsigned char keymatrix[6];
@ -34,7 +76,13 @@ static int xRef;
static int yRef;
static uint8_t usbnavpad=0;
static bool menuOn=true;
/********************************
* Generic output and malloc
********************************/
void emu_printf(char * text)
{
printf("%s\n",text);
@ -55,11 +103,220 @@ void emu_printh(int val)
printf("0x%.8\n",val);
}
static int malbufpt = 0;
static char malbuf[EXTRA_HEAP];
void * emu_Malloc(int size)
{
void * retval = malloc(size);
if (!retval) {
emu_printf("failled to allocate");
emu_printf(size);
emu_printf("fallback");
if ( (malbufpt+size) < sizeof(malbuf) ) {
retval = (void *)&malbuf[malbufpt];
malbufpt += size;
}
else {
emu_printf("failure to allocate");
}
}
else {
emu_printf("could allocate dynamic ");
emu_printf(size);
}
return retval;
}
void * emu_MallocI(int size)
{
void * retval = NULL;
if ( (malbufpt+size) < sizeof(malbuf) ) {
retval = (void *)&malbuf[malbufpt];
malbufpt += size;
emu_printf("could allocate static ");
emu_printf(size);
}
else {
emu_printf("failure to allocate");
}
return retval;
}
void emu_Free(void * pt)
{
free(pt);
}
void emu_drawText(unsigned short x, unsigned short y, const char * text, unsigned short fgcolor, unsigned short bgcolor, int doublesize)
{
tft.drawText(x, y, text, fgcolor, bgcolor, doublesize?true:false);
}
/********************************
* OSKB handling
********************************/
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
// On screen keyboard position
#define KXOFF 28 //64
#define KYOFF 96
#define KWIDTH 11 //22
#define KHEIGHT 3
static bool oskbOn = false;
static int cxpos = 0;
static int cypos = 0;
static int oskbMap = 0;
static uint16_t oskbBLastState = 0;
static void lineOSKB2(int kxoff, int kyoff, char * str, int row)
{
char c[2] = {'A',0};
const char * cpt = str;
for (int i=0; i<KWIDTH; i++)
{
c[0] = *cpt++;
c[1] = 0;
uint16_t bg = RGBVAL16(0x00,0x00,0xff);
if ( (cxpos == i) && (cypos == row) ) bg = RGBVAL16(0xff,0x00,0x00);
tft.drawTextNoDma(kxoff+8*i,kyoff, &c[0], RGBVAL16(0x00,0xff,0xff), bg, ((i&1)?false:true));
}
}
static void lineOSKB(int kxoff, int kyoff, char * str, int row)
{
char c[4] = {' ',0,' ',0};
const char * cpt = str;
for (int i=0; i<KWIDTH; i++)
{
c[1] = *cpt++;
uint16_t bg;
if (row&1) bg = (i&1)?RGBVAL16(0xff,0xff,0xff):RGBVAL16(0xe0,0xe0,0xe0);
else bg = (i&1)?RGBVAL16(0xe0,0xe0,0xe0):RGBVAL16(0xff,0xff,0xff);
if ( (cxpos == i) && (cypos == row) ) bg = RGBVAL16(0x00,0xff,0xff);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+0 , " ", RGBVAL16(0x00,0x00,0x00), bg, false);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+8 , &c[0], RGBVAL16(0x00,0x00,0x00), bg, true);
tft.drawTextNoDma(kxoff+24*i,kyoff+32*row+24, " ", RGBVAL16(0x00,0x00,0x00), bg, false);
}
}
static void drawOskb(void)
{
// lineOSKB2(KXOFF,KYOFF+0, (char *)"Q1W2E3R4T5Y6U7I8O9P0<=", 0);
// lineOSKB2(KXOFF,KYOFF+16, (char *)" A!S@D#F$G%H+J&K*L-EN", 1);
// lineOSKB2(KXOFF,KYOFF+32, (char *)" Z(X)C?V/B\"N<M>.,SP ", 2);
if (oskbMap == 0) {
lineOSKB(KXOFF,KYOFF, keylables_map1_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map1_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map1_2, 2);
}
else if (oskbMap == 1) {
lineOSKB(KXOFF,KYOFF, keylables_map2_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map2_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map2_2, 2);
}
else {
lineOSKB(KXOFF,KYOFF, keylables_map3_0, 0);
lineOSKB(KXOFF,KYOFF, keylables_map3_1, 1);
lineOSKB(KXOFF,KYOFF, keylables_map3_2, 2);
}
}
void toggleOskb(bool forceoff) {
if (forceoff) oskbOn=true;
if (oskbOn) {
oskbOn = false;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,32, "Press USER2 to toggle onscreen keyboard.", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0x00,0x00,0x00), true);
} else {
oskbOn = true;
tft.fillScreenNoDma(RGBVAL16(0x00,0x00,0x00));
tft.drawTextNoDma(0,32, " Press USER2 to exit onscreen keyboard. ", RGBVAL16(0xff,0xff,0xff), RGBVAL16(0x00,0x00,0x00), true);
tft.drawTextNoDma(0,64, " (USER1 to toggle between keymaps) ", RGBVAL16(0x00,0xff,0xff), RGBVAL16(0x00,0x00,0xff), true);
tft.drawRectNoDma(KXOFF,KYOFF, 22*8, 3*16, RGBVAL16(0x00,0x00,0xFF));
drawOskb();
}
}
static int handleOskb(void)
{
int retval = 0;
uint16_t bClick = bLastState & ~oskbBLastState;
oskbBLastState = bLastState;
/*
static const char * digits = "0123456789ABCDEF";
char buf[5] = {0,0,0,0,0};
int val = bClick;
buf[0] = digits[(val>>12)&0xf];
buf[1] = digits[(val>>8)&0xf];
buf[2] = digits[(val>>4)&0xf];
buf[3] = digits[val&0xf];
tft.drawTextNoDma(0,KYOFF+ 64,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),1);
*/
if (bClick & MASK_KEY_USER2)
{
toggleOskb(false);
}
if (oskbOn)
{
bool updated = true;
if (bClick & MASK_KEY_USER1)
{
oskbMap += 1;
if (oskbMap == 3) oskbMap = 0;
}
else if (bClick & MASK_JOY2_LEFT)
{
cxpos++;
if (cxpos >= KWIDTH) cxpos = 0;
}
else if (bClick & MASK_JOY2_RIGHT)
{
cxpos--;
if (cxpos < 0) cxpos = KWIDTH-1;
}
else if (bClick & MASK_JOY2_DOWN)
{
cypos++;
if (cypos >= KHEIGHT) cypos = 0;
}
else if (bClick & MASK_JOY2_UP)
{
cypos--;
if (cypos < 0) cypos = KHEIGHT-1;
}
else if (oskbBLastState & MASK_JOY2_BTN)
{
retval = cypos*KWIDTH+cxpos+1;
if (retval) {
retval--;
//if (retval & 1) retval = key_map2[retval>>1];
//else retval = key_map1[retval>>1];
if (oskbMap == 0) {
retval = key_map1[retval];
}
else if (oskbMap == 1) {
retval = key_map2[retval];
}
else {
retval = key_map3[retval];
}
}
}
else {
updated=false;
}
if (updated) drawOskb();
}
return retval;
}
#endif
/********************************
* Input and keyboard
@ -235,13 +492,15 @@ int emu_ReadKeys(void)
keymatrix_hitrow = -1;
unsigned char row;
unsigned short cols[6]={1,2,3,4,5,14};
unsigned char keymatrixtmp[6];
for (int i=0;i<6;i++){
// gpio_set_dir(cols[i], GPIO_OUT);
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
@ -252,27 +511,81 @@ int emu_ReadKeys(void)
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
// gpio_set_dir(cols[i], GPIO_IN);
keymatrix[i]=row;
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] = row;
}
#ifdef MULTI_DEBOUNCE
for (int i=0;i<6;i++){
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(8) ? 0 : 0x02);
row |= (gpio_get(6) ? 0 : 0x04);
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
for (int i=0;i<6;i++){
gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 0);
#ifdef SWAP_ALT_DEL
sleep_us(1);
//__asm volatile ("nop\n"); // 4-8ns
#endif
row=0;
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(9) ? 0 : 0x01);
row |= (gpio_get(8) ? 0 : 0x02);
row |= (gpio_get(6) ? 0 : 0x04);
row |= (gpio_get(15) ? 0 : 0x08);
row |= (gpio_get(7) ? 0 : 0x10);
row |= (gpio_get(22) ? 0 : 0x20);
//gpio_set_dir(cols[i], GPIO_OUT);
gpio_put(cols[i], 1);
gpio_set_dir(cols[i], GPIO_IN);
gpio_disable_pulls(cols[i]);
keymatrixtmp[i] |= row;
}
#endif
#ifdef SWAP_ALT_DEL
// Swap ALT and DEL
unsigned char alt = keymatrix[0] & 0x02;
unsigned char del = keymatrix[5] & 0x20;
keymatrix[0] &= ~0x02;
keymatrix[5] &= ~0x20;
if (alt) keymatrix[5] |= 0x20;
if (del) keymatrix[0] |= 0x02;
unsigned char alt = keymatrixtmp[0] & 0x02;
unsigned char del = keymatrixtmp[5] & 0x20;
keymatrixtmp[0] &= ~0x02;
keymatrixtmp[5] &= ~0x20;
if (alt) keymatrixtmp[5] |= 0x20;
if (del) keymatrixtmp[0] |= 0x02;
#endif
bool alt_pressed=false;
if ( keymatrix[5] & 0x20 ) {alt_pressed=true; keymatrix[5] &= ~0x20;};
if ( keymatrixtmp[5] & 0x20 ) {alt_pressed=true; keymatrixtmp[5] &= ~0x20;};
for (int i=0;i<6;i++){
row = keymatrix[i];
row = keymatrixtmp[i];
if (row) keymatrix_hitrow=i;
keymatrix[i] = row;
}
//6,9,15,8,7,22
@ -316,7 +629,8 @@ int emu_ReadKeys(void)
hundred_ms_cnt += 1; // 2
if (hundred_ms_cnt >= 2)
{
hundred_ms_cnt = 0;
hundred_ms_cnt = 0;
/*
if ( (time_ms-keypress_t_ms) < 500)
{
if (key_alt == false)
@ -328,13 +642,14 @@ int emu_ReadKeys(void)
key_alt = false;
}
}
*/
}
}
}
else {
// Keep press
if (hundred_ms_cnt == 1) {
if ((to_ms_since_boot (get_absolute_time())-keypress_t_ms) > 1000)
if ((to_ms_since_boot (get_absolute_time())-keypress_t_ms) > 2000)
{
if (key_alt == false)
{
@ -377,6 +692,12 @@ int emu_ReadKeys(void)
|| (retval & MASK_KEY_USER4 ) )
{
}
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
if (oskbOn) {
retval |= MASK_OSKB;
}
#endif
return (retval);
}
@ -404,8 +725,6 @@ int emu_ReadI2CKeyboard(void) {
}
if (keymatrix_hitrow >=0 ) {
unsigned short match = ((unsigned short)keymatrix_hitrow<<8) | keymatrix[keymatrix_hitrow];
//if ( (match == 0x002 ) ) return 0; // shift or fn
//if (match < 0x100 ) match = match & ~0x002; // ignore shift key
for (int i=0; i<sizeof(matkeys)/sizeof(unsigned short); i++) {
if (match == matkeys[i]) {
hundred_ms_cnt = 0;
@ -414,6 +733,11 @@ int emu_ReadI2CKeyboard(void) {
}
}
#endif
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
if (!menuOn) {
retval = handleOskb();
}
#endif
return(retval);
}
@ -538,35 +862,26 @@ void emu_InitJoysticks(void) {
gpio_set_dir(4, GPIO_OUT);
gpio_set_dir(5, GPIO_OUT);
gpio_set_dir(14, GPIO_OUT);
gpio_put(1, 1);
gpio_put(2, 1);
gpio_put(3, 1);
gpio_put(4, 1);
gpio_put(5, 1);
gpio_put(14, 1);
/*
gpio_put(1, 0);
gpio_put(2, 0);
gpio_put(3, 0);
gpio_put(4, 0);
gpio_put(5, 0);
gpio_put(14, 0);
gpio_set_pulls(1,true,true);
gpio_set_pulls(2,true,true);
gpio_set_pulls(3,true,true);
gpio_set_pulls(4,true,true);
gpio_set_pulls(5,true,true);
gpio_set_pulls(14,true,true);
// but set as input floating when not used!
gpio_set_dir(1, GPIO_IN);
gpio_set_dir(2, GPIO_IN);
gpio_set_dir(3, GPIO_IN);
gpio_set_dir(4, GPIO_IN);
gpio_set_dir(5, GPIO_IN);
gpio_set_dir(14, GPIO_IN);
*/
gpio_set_dir(14, GPIO_IN);
gpio_disable_pulls(1);
gpio_disable_pulls(2);
gpio_disable_pulls(3);
gpio_disable_pulls(4);
gpio_disable_pulls(5);
gpio_disable_pulls(14);
// Input pins (cols)
gpio_init(6);
gpio_init(9);
@ -574,18 +889,18 @@ void emu_InitJoysticks(void) {
gpio_init(8);
gpio_init(7);
gpio_init(22);
gpio_set_pulls(6,true,false);
gpio_set_dir(6,GPIO_IN);
gpio_set_pulls(9,true,false);
gpio_set_dir(9,GPIO_IN);
gpio_set_pulls(15,true,false);
gpio_set_dir(15,GPIO_IN);
gpio_set_pulls(8,true,false);
gpio_set_dir(8,GPIO_IN);
gpio_set_pulls(7,true,false);
gpio_set_dir(7,GPIO_IN);
gpio_set_pulls(22,true,false);
gpio_set_dir(22,GPIO_IN);
gpio_pull_up(6);
gpio_pull_up(9);
gpio_pull_up(15);
gpio_pull_up(8);
gpio_pull_up(7);
gpio_pull_up(22);
#endif
}
@ -594,8 +909,17 @@ int emu_setKeymap(int index) {
/********************************
* Initialization
********************************/
void emu_init(void)
{
{
// Dual display config, initialize TFT
#if (defined(ILI9341) || defined(ST7789)) && defined(USE_VGA)
tft.begin();
#endif
emu_InitJoysticks();
#ifdef SWAP_JOYSTICK
joySwapped = true;
@ -627,7 +951,6 @@ void emu_init(void)
void emu_start(void)
{
usbnavpad = 0;
keyMap = 0;

Wyświetl plik

@ -11,19 +11,42 @@
#ifdef KEYMAP_PRESENT
#define keylables_map1_0 (char *)"qwertyuiop\x1a"
#define keylables_map1_1 (char *)" asdfghjkl\x19"
#define keylables_map1_2 (char *)" zxcvbnm.\x10 "
const unsigned short key_map1[] = {
1,2,3,4,5,6,7,8,9,10,11,
0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0 };
#ifdef PICOMPUTER
'Q','W','E','R','T','Y','U','I','O','P',157,
0,'A','S','D','F','G','H','J','K','L',0x0D,
0,'Z','X','C','V','B','N','M','.',' ',
145,157,29,17
};
#define keylables_map2_0 (char *)"1234567890 "
#define keylables_map2_1 (char *)" !@#$%+&*- "
#define keylables_map2_2 (char *)" ()?/\"<>,: "
const unsigned short key_map2[] = {
'1','2','3','4','5','6','7','8','9','0',0,
0, '!','@','#','$','%','+','&','*','-','\/',
0, '(',')','?','\/','"','<','>',',',':',
0,0,0,0
};
#define keylables_map3_0 (char *)"\x11\x12\x13\x14\x15\x16\x17\x18 "
#define keylables_map3_1 (char *)" "
#define keylables_map3_2 (char *)" ;= "
const unsigned short key_map3[] = {
133,134,135,136,137,138,139,140,0,0,0, // function keys
0, 0,0,0,0,0,0,0,0,0,0,
0, 0,0,0,0,0,0,0,';','=',
0,0,0,0
};
const unsigned short matkeys[] = {
0x020,0x120,0x220,0x320,0x420, 0x408,0x308,0x208,0x108,0x008 ,0x002, // row 1
0x510, 0x010,0x110,0x210,0x310,0x410, 0x401,0x301,0x201,0x101,0x001, // row 2
0x520,0x102,0x202,0x302,0x402, 0x404,0x304,0x204,0x104,0x004, // row 3
0x020,0x120,0x220,0x320,0x420,0x408,0x308,0x208,0x108,0x008,0x002, // row 1
0x510,0x010,0x110,0x210,0x310,0x410,0x401,0x301,0x201,0x101,0x001, // row 2
0x520,0x102,0x202,0x302,0x402,0x404,0x304,0x204,0x104,0x004, // row 3
0x508,0x501,0x502,0x504 }; // cursor keys
#endif
#endif

Wyświetl plik

@ -25,10 +25,19 @@ static int fb_width, fb_height;
#include "hardware/vreg.h"
static const char * digits = "0123456789ABCDEF";
static int hk = 0;
static int prevhk = 0;
static int col=0;
static int row=0;
void emu_Input(uint16_t bClick) {
hk = emu_ReadI2CKeyboard();
}
bool repeating_timer_callback(struct repeating_timer *t) {
uint16_t bClick = emu_DebounceLocalKeys();
//emu_Input(bClick);
emu_Input(bClick);
return true;
}
@ -49,14 +58,14 @@ int main(void) {
emu_start();
//tft.startDMA();
struct repeating_timer timer;
add_repeating_timer_ms(25, repeating_timer_callback, NULL, &timer);
add_repeating_timer_ms(20, repeating_timer_callback, NULL, &timer);
tft.fillScreenNoDma(LIGHT_BLUE);
tft.get_frame_buffer_size(&fb_width, &fb_height);
tft.drawRectNoDma((fb_width-320)/2,(fb_height-200)/2, 320,200, BLUE);
tft.drawTextNoDma((fb_width-320)/2,(fb_height-200)/2+1*8," **** COMMODORE 64 BASIC V2 **** ",LIGHT_BLUE,BLUE,false);
tft.drawTextNoDma((fb_width-320)/2,(fb_height-200)/2+3*8," 64K RAM SYSTEM 38911 BASIC BYTES FREE ",LIGHT_BLUE,BLUE,false);
tft.drawTextNoDma((fb_width-320)/2,(fb_height-200)/2+5*8,"READY.",LIGHT_BLUE,BLUE,false);
//tft.drawTextNoDma((fb_width-320)/2,(fb_height-200)/2+1*8," **** COMMODORE 64 BASIC V2 **** ",LIGHT_BLUE,BLUE,false);
//tft.drawTextNoDma((fb_width-320)/2,(fb_height-200)/2+3*8," 64K RAM SYSTEM 38911 BASIC BYTES FREE ",LIGHT_BLUE,BLUE,false);
//tft.drawTextNoDma((fb_width-320)/2,(fb_height-200)/2+5*8,"READY.",LIGHT_BLUE,BLUE,false);
char buf[4] = {32,32,32,0};
uint sys_clk = clock_get_hz(clk_sys)/1000000;
@ -68,7 +77,7 @@ int main(void) {
buf[0] = digits[r1];
buf[1] = digits[r2];
buf[2] = digits[r3];
tft.drawTextNoDma(4*8,0,buf,BLUE,LIGHT_BLUE,false);
tft.drawTextNoDma(0,0,buf,BLUE,LIGHT_BLUE,false);
while (true) {
uint16_t bClick = emu_GetPad();
@ -77,40 +86,61 @@ int main(void) {
buf[1] = digits[(bClick>>8)&0xf];
buf[2] = digits[(bClick>>4)&0xf];
buf[3] = digits[bClick&0xf];
tft.drawTextNoDma(4*8,16,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),true);
tft.drawTextNoDma(4*8,0,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),false);
buf[3] = 0;
int key = emu_ReadI2CKeyboard();
buf[0] = digits[(key>>8)&0xf];
buf[1] = digits[(key>>4)&0xf];
buf[2] = digits[key&0xf];
tft.drawTextNoDma(4*8,16*2,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),true);
tft.drawTextNoDma(4*8,8,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),false);
buf[2] = 0;
key = emu_ReadI2CKeyboard2(0);
buf[0] = digits[(key>>4)&0xf];
buf[1] = digits[key&0xf];
tft.drawTextNoDma(4*8,16*4,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),true);
tft.drawTextNoDma(9*8+0*24,0*8,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),true);
key = emu_ReadI2CKeyboard2(1);
buf[0] = digits[(key>>4)&0xf];
buf[1] = digits[key&0xf];
tft.drawTextNoDma(4*8,16*5,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),true);
tft.drawTextNoDma(9*8+1*24,0*8,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),true);
key = emu_ReadI2CKeyboard2(2);
buf[0] = digits[(key>>4)&0xf];
buf[1] = digits[key&0xf];
tft.drawTextNoDma(4*8,16*6,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),true);
tft.drawTextNoDma(9*8+2*24,0*8,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),true);
key = emu_ReadI2CKeyboard2(3);
buf[0] = digits[(key>>4)&0xf];
buf[1] = digits[key&0xf];
tft.drawTextNoDma(4*8,16*7,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),true);
tft.drawTextNoDma(9*8+3*24,0*8,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),true);
key = emu_ReadI2CKeyboard2(4);
buf[0] = digits[(key>>4)&0xf];
buf[1] = digits[key&0xf];
tft.drawTextNoDma(4*8,16*8,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),true);
tft.drawTextNoDma(9*8+4*24,0*8,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),true);
key = emu_ReadI2CKeyboard2(5);
buf[0] = digits[(key>>4)&0xf];
buf[1] = digits[key&0xf];
tft.drawTextNoDma(4*8,16*9,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),true);
tft.drawTextNoDma(9*8+5*24,0*8,buf,RGBVAL16(0x00,0x00,0x00),RGBVAL16(0xFF,0xFF,0xFF),true);
if ( (hk != 0) && (hk < 128) ) {
buf[0] = (char)(hk&0xff);
buf[1] = 0;
tft.drawTextNoDma(col*8,(row+3)*8,buf,LIGHT_BLUE,BLUE,false);
col += 1;
if (col >= 40) {
col=0;
row += 1;
if (row >= 25) {
row=0;
}
}
if (hk != prevhk) {
sleep_ms(200);
}
else {
sleep_ms(100);
}
}
prevhk = hk;
sleep_ms(20);
/*