// // Keyboard to UART // version 0.1 2025.9.5 // OKIRAKU AUDIO // #include "18F47Q43.H" #fuses RSTOSC_HFINTRC_64MHZ,NOPROTECT,NOMCLR,NOBROWNOUT,NOLVP #use delay(clock=64MHz) #PIN_SELECT U1TX = PIN_C6 #PIN_SELECT U1RX = PIN_C7 #use RS232(BAUD=115200,STREAM=UART1,XMIT=PIN_C6, RCV=PIN_C7) #use fast_io(A) #use fast_io(B) #use fast_io(C) #use fast_io(D) #use fast_io(E) #define KEY0 PIN_A0 #define KEY1 PIN_A1 #define KEY2 PIN_A2 #define KEY3 PIN_A3 #define KEY4 PIN_A4 #define LED0 PIN_D1 #define LED1 PIN_D0 #define LED2 PIN_C3 #define LED3 PIN_C2 #define LED4 PIN_C1 #define COM0 PIN_B5 #define COM1 PIN_B4 #define COM2 PIN_B3 #define COM3 PIN_B2 #define COM4 PIN_B1 #define COM5 PIN_B0 #define COM6 PIN_D7 #define COM7 PIN_D6 #define COM8 PIN_D5 #define COM9 PIN_D4 #define COM10 PIN_C5 #define COM11 PIN_C4 #define COM12 PIN_D3 #define COM13 PIN_D2 #define SHIFT_KEY (0x80) #define CTRL_KEY (0x81) #define ALT_KEY (0x82) #define WIN_KEY (0x83) #define FN_KEY (0x84) #define CAPS_KEY (0x85) #define SHIFT_MASK (0x80) #define CTRL_MASK (0x40) #define ALT_MASK (0x20) int key_table[256]; // [b7:4] COMMON LINE // [b3] SHIFT ON // [b2:0] KEY SENSE LINE void make_key_table() { int16 i; for(i=0;i<256;i++) key_table[i]=0; key_table[0x12]='a';key_table[0x12 | 0x08]='A'; key_table[0x53]='b';key_table[0x53 | 0x08]='B'; key_table[0x33]='c';key_table[0x33 | 0x08]='C'; key_table[0x32]='d';key_table[0x32 | 0x08]='D'; key_table[0x31]='e';key_table[0x31 | 0x08]='E'; key_table[0x42]='f';key_table[0x42 | 0x08]='F'; key_table[0x52]='g';key_table[0x52 | 0x08]='G'; key_table[0x62]='h';key_table[0x62 | 0x08]='H'; key_table[0x81]='i';key_table[0x81 | 0x08]='I'; key_table[0x72]='j';key_table[0x72 | 0x08]='J'; key_table[0x82]='k';key_table[0x82 | 0x08]='K'; key_table[0x92]='l';key_table[0x92 | 0x08]='L'; key_table[0x73]='m';key_table[0x73 | 0x08]='M'; key_table[0x63]='n';key_table[0x63 | 0x08]='N'; key_table[0x91]='o';key_table[0x91 | 0x08]='O'; key_table[0xa1]='p';key_table[0xa1 | 0x08]='P'; key_table[0x11]='q';key_table[0x11 | 0x08]='Q'; key_table[0x41]='r';key_table[0x41 | 0x08]='R'; key_table[0x22]='s';key_table[0x22 | 0x08]='S'; key_table[0x51]='t';key_table[0x51 | 0x08]='T'; key_table[0x71]='u';key_table[0x71 | 0x08]='U'; key_table[0x43]='v';key_table[0x43 | 0x08]='V'; key_table[0x21]='w';key_table[0x21 | 0x08]='W'; key_table[0x23]='x';key_table[0x23 | 0x08]='X'; key_table[0x61]='y';key_table[0x61 | 0x08]='Y'; key_table[0x13]='z';key_table[0x13 | 0x08]='Z'; key_table[0x10]='1';key_table[0x10 | 0x08]='!'; key_table[0x20]='2';key_table[0x20 | 0x08]='@'; key_table[0x30]='3';key_table[0x30 | 0x08]='#'; key_table[0x40]='4';key_table[0x40 | 0x08]='$'; key_table[0x50]='5';key_table[0x50 | 0x08]='%'; key_table[0x60]='6';key_table[0x60 | 0x08]='^'; key_table[0x70]='7';key_table[0x70 | 0x08]='&'; key_table[0x80]='8';key_table[0x80 | 0x08]='*'; key_table[0x90]='9';key_table[0x90 | 0x08]='('; key_table[0xa0]='0';key_table[0xa0 | 0x08]=')'; key_table[0xb0]='-' ;key_table[0xb0 | 0x08]='_' ; key_table[0xc0]='=' ;key_table[0xc0 | 0x08]='+' ; key_table[0xd0]=0x08;key_table[0xd0 | 0x08]=0x08; //Back Space key_table[0xb1]='[' ;key_table[0xb1 | 0x08]='{' ; key_table[0xc1]=']' ;key_table[0xc1 | 0x08]='}' ; key_table[0xd1]=0x5c;key_table[0xd1 | 0x08]='|' ; // back slash key_table[0xa2]=';' ;key_table[0xa2 | 0x08]=':' ; key_table[0xb2]=''' ;key_table[0xb2 | 0x08]='"' ; key_table[0x83]='.' ;key_table[0x83 | 0x08]='<' ; key_table[0x93]=',' ;key_table[0x93 | 0x08]='>' ; key_table[0xa3]='/' ;key_table[0xa3 | 0x08]='?' ; key_table[0xd2]=0x0d;key_table[0xd2 | 0x08]=0x0d; // CR key_table[0x01]=0x09;key_table[0x01 | 0x08]=0x09; // TAB key_table[0x00]=0x1b;key_table[0x00 | 0x08]='~'; //ESC key_table[0x54]=0x20;key_table[0x54 | 0x08]='~'; //SPACE key_table[0x84]=0x13; //CTRL-S RIGHT ALT // LEFT ARRLOW key_table[0x94]=0x18; //CTRL-X RIGHT NOTE // DOWN ARRLOW key_table[0xa4]=0x04; //CTRL-D RIGHT CTRL // RIGHT ARRLOW key_table[0x04]=CTRL_KEY; //CTRL(LEFT) key_table[0x02]=CAPS_KEY; //CAPS LOCK key_table[0x03]=SHIFT_KEY; //SHIFT_KEY(LEFT) key_table[0xc3]=SHIFT_KEY; //SHIFT_KEY(RIGHT) key_table[0x14]=WIN_KEY; key_table[0x24]=ALT_KEY; // ALT(LEFT) key_table[0xd4]=FN_KEY; } void io_select() { output_drive(PIN_C6); //TX output_drive(LED0);output_high(LED0); output_drive(LED1);output_high(LED1); output_drive(LED2);output_high(LED2); output_drive(LED3);output_high(LED3); output_drive(LED4);output_high(LED4); output_drive(COM0);output_low(COM0); output_drive(COM1);output_low(COM1); output_drive(COM2);output_low(COM2); output_drive(COM3);output_low(COM3); output_drive(COM4);output_low(COM4); output_drive(COM5);output_low(COM5); output_drive(COM6);output_low(COM6); output_drive(COM7);output_low(COM7); output_drive(COM8);output_low(COM8); output_drive(COM9);output_low(COM9); output_drive(COM10);output_low(COM10); output_drive(COM11);output_low(COM11); output_drive(COM12);output_low(COM12); output_drive(COM13);output_low(COM13); } void com_high(int com) { switch(com){ case 0:output_high(COM0);break; case 1:output_high(COM1);break; case 2:output_high(COM2);break; case 3:output_high(COM3);break; case 4:output_high(COM4);break; case 5:output_high(COM5);break; case 6:output_high(COM6);break; case 7:output_high(COM7);break; case 8:output_high(COM8);break; case 9:output_high(COM9);break; case 10:output_high(COM10);break; case 11:output_high(COM11);break; case 12:output_high(COM12);break; case 13:output_high(COM13);break; default:break; } } void com_low(int com) { switch(com){ case 0:output_low(COM0);break; case 1:output_low(COM1);break; case 2:output_low(COM2);break; case 3:output_low(COM3);break; case 4:output_low(COM4);break; case 5:output_low(COM5);break; case 6:output_low(COM6);break; case 7:output_low(COM7);break; case 8:output_low(COM8);break; case 9:output_low(COM9);break; case 10:output_low(COM10);break; case 11:output_low(COM11);break; case 12:output_low(COM12);break; case 13:output_low(COM13);break; default:break; } } void led_on(int com,int led) { com_high(com); switch(led){ case 0:output_low(LED0);break; case 1:output_low(LED1);break; case 2:output_low(LED2);break; case 3:output_low(LED3);break; case 4:output_low(LED4);break; default:break; } } void led_off(int com,int led) { com_low(com); switch(led){ case 0:output_high(LED0);break; case 1:output_high(LED1);break; case 2:output_high(LED2);break; case 3:output_high(LED3);break; case 4:output_high(LED4);break; default:break; } } void led_all_off() { output_high(LED0); output_high(LED1); output_high(LED2); output_high(LED3); output_high(LED4); output_low(COM0); output_low(COM1); output_low(COM2); output_low(COM3); output_low(COM4); output_low(COM5); output_low(COM6); output_low(COM7); output_low(COM8); output_low(COM9); output_low(COM10); output_low(COM11); output_low(COM12); output_low(COM13); } void key_sense_ready() { output_high(COM0); output_high(COM1); output_high(COM2); output_high(COM3); output_high(COM4); output_high(COM5); output_high(COM6); output_high(COM7); output_high(COM8); output_high(COM9); output_high(COM10); output_high(COM11); output_high(COM12); output_high(COM13); } void key_sense_off() { output_low(COM0); output_low(COM1); output_low(COM2); output_low(COM3); output_low(COM4); output_low(COM5); output_low(COM6); output_low(COM7); output_low(COM8); output_low(COM9); output_low(COM10); output_low(COM11); output_low(COM12); output_low(COM13); } int key_sense(int com,int key) { int flag=1; com_low(com); flag = 0; switch(key){ case 0:if(input(KEY0)==0) flag = 1;break; case 1:if(input(KEY1)==0) flag = 1;break; case 2:if(input(KEY2)==0) flag = 1;break; case 3:if(input(KEY3)==0) flag = 1;break; case 4:if(input(KEY4)==0) flag = 1;break; default:break; } com_high(com); return(flag); } int current_key_mask; int caps_lock=0; int arrow_lock = 0; int scan_key() { int i,j,key,i2,j2,n; int keyelse; key = keyelse = 0; key_sense_ready(); for(i=0;i<14;i++){ for(j=0;j<5;j++){ if(key_sense(i,j)){ n = (i << 4)&0xf0; n |= j; key = key_table[n]; switch(key){ case SHIFT_KEY:current_key_mask |= SHIFT_MASK;key=0;break; case CTRL_KEY:current_key_mask |= CTRL_MASK;key=0;break; case ALT_KEY:current_key_mask |= ALT_MASK;key=0;break; default: i2 = i; j2 = j; keyelse = key; break; } } } } key_sense_off(); key = keyelse; if(key>0 && key<128){ if(arrow_lock && key=='/') key = 0x05; else { switch(current_key_mask){ case CTRL_MASK: if(key>='a' && key<='z') key=key-'a'+1; else key=0; break; case SHIFT_MASK: n = (i2 << 4)&0xf0; n |= j2; n |= 0x08; key = key_table[n]; if(caps_lock){ if(key>='A' && key<='Z') key +=0x20; else if(key>='a' && key<='z') key -=0x20; } break; default: if(caps_lock){ if(key>='A' && key<='Z') key +=0x20; else if(key>='a' && key<='z') key -=0x20; } break; } } } return(key); } void putkey(int key) { /* if(key>=' '){ printf("[%2x:%c]",key,key); } else{ printf("[%2x]",key); } */ putc(key); } #define REPEAT_TIME (500) #define REPEAT_INTERVAL (60) #INT_TIMER0 rtcc_isr() { int i,j,key; static int old_key=0; static int loop=0; static int16 loop_timer=0; set_timer0(7); // if(kbhit()) getc(); loop_timer++; if(loop==10){ current_key_mask = 0; led_all_off(); key = scan_key(); if(key>0 && key<128 && key == old_key){ if(loop_timer > REPEAT_TIME){ putkey(key); loop_timer-=REPEAT_INTERVAL; } } else loop_timer=0; if(key && key !=old_key){ switch(key){ case CAPS_KEY: switch(current_key_mask){ case SHIFT_MASK: if(caps_lock) caps_lock = 0; else caps_lock = 1; break; default:break; } break; case FN_KEY: if(arrow_lock) arrow_lock = 0; else arrow_lock = 1; break; default: if((key&0x80)==0){ putkey(key); } break; } } old_key = key; } loop++; if(loop==11) loop=0; switch(loop){ case 0: if(caps_lock)led_on(0,2); break; case 5: led_off(0,2); if(arrow_lock)led_on(13,4); break; case 10:led_off(13,4); break; default: break; } } void main() { setup_oscillator(OSC_HFINTRC_8MHZ); delay_ms(10); setup_oscillator(OSC_HFINTRC_16MHZ); delay_ms(10); setup_oscillator(OSC_HFINTRC_64MHZ); delay_ms(10); io_select(); make_key_table(); setup_timer_0(T0_INTERNAL | T0_DIV_64 | T0_8_BIT); set_timer0(7); /* 64MHz/4/32/(256+1-7)=1000Hz 8 Bit mode */ enable_interrupts(INT_TIMER0); enable_interrupts(GLOBAL); while(1){} }