Files
retrobsd/sys/pic32/kbd.c
Serge Vakulenko 717ab59efd Switch to kconfig completely.
All configsys stuff moved to tools/configsys/ directory, not used anymore.
2015-09-07 22:22:35 -07:00

342 lines
13 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
*
* RetroBSD - PS2 keyboard driver for the Maximite PIC32 board
*
* Copyright (C) 2011 Rob Judd <judd@ob-wan.com>
* All rights reserved. The three clause ("New" or "Modified")
* Berkeley software License Agreement specifies the terms and
* conditions for redistribution.
*
*/
/*
../kbd.c: In function 'initKBD':
../kbd.c:155:8: error: request for member 'ON' in something not a structure or union
../kbd.c:156:8: error: request for member 'CNPUE15' in something not a structure or union
../kbd.c:157:8: error: request for member 'CNPUE16' in something not a structure or union
../kbd.c: In function 'readKBD':
../kbd.c:173:9: error: request for member 'RD7' in something not a structure or union
../kbd.c:174:9: error: request for member 'RD6' in something not a structure or union
*
* This driver uses a 20uS timer, probably too fast
*/
#include "sys/types.h"
#include "machine/io.h"
#include "kbd.h"
//#define TRACE printf
#ifndef TRACE
#define TRACE(...)
#endif
// I2C registers
struct kbdreg {
//
};
#define USASCII 1
//#define RUSSIAN 1
#define true 1
#define false 0
#define PS2CLOCK 1//PORTD.RD6
#define PS2DATA 2//PORTD.RD7
#define QUEUE_SIZE 256
extern volatile char in_queue[QUEUE_SIZE];
extern volatile int in_queue_head, in_queue_tail;
volatile int abort;
#define POLL 20*(CPU_KHZ/1000) // # clock cycles for 20uS between keyboard reads
#define TIMEOUT 500*(CPU_KHZ/1000) // # clock cycles for 500uS timeout
enum {PS2START, PS2BIT, PS2PARITY, PS2STOP};
// Keyboard state machine and buffer
int state;
unsigned char key_buff;
int key_state, key_count, key_parity, key_timer;
// IBM keyboard scancode set 2 - Special Keys
#define F1 0x0e
#define F2 0x0f
#define F3 0x10
#define F4 0x11
#define F5 0x12
#define F6 0x13
#define F7 0x14 // maps to F5
#define F8 0x15
#define F9 0x16
#define F10 0x17
#define F11 0x18
#define F12 0x19
#define NUM 0x00
#define BKSP 0x08
#define TAB 0x09
#define L_ALT 0x11
#define L_SHF 0x12
#define L_CTL 0x14
#define CAPS 0x58
#define R_SHF 0x59
#define ENTER 0x0d
#define ESC 0x1b
#define SCRL 0x7e
#ifdef USASCII
//
// Map of standard keyboard, US ASCII layout
//
const char lowerKey[128]={
0, F9, 0, F5, F3, F1, F2, F12, //00
0, F10, F8, F6, F4, TAB, '`', 0, //08
0, 0, L_SHF, 0, L_CTL, 'q', '1', 0, //10
0, 0, 'z', 's', 'a', 'w', '2', 0, //18
0, 'c', 'x', 'd', 'e', '4', '3', 0, //20
0, ' ', 'v', 'f', 't', 'r', '5', 0, //28
0, 'n', 'b', 'h', 'g', 'y', '6', 0, //30
0, 0, 'm', 'j', 'u', '7', '8', 0, //38
0, ',', 'k', 'i', 'o', '0', '9', 0, //40
0, '.', '/', 'l', ';', 'p', '-', 0, //48
0, 0, '\'', 0, '[', '=', 0, 0, //50
CAPS, R_SHF, ENTER, ']', 0, '\\', 0, 0, //58
0, 0, 0, 0, 0, 0, BKSP, 0, //60
0, '1', 0, '4', '7', 0, 0, 0, //68
'0', '.', '2', '5', '6', '8', ESC, NUM, //70
F11, '+', '3', '-', '*', '9', 0, 0 //78
};
const char upperKey[128] = {
0, F9, 0, F5, F3, F1, F2, F12, //00
0, F10, F8, F6, F4, TAB, '~', 0, //08
0, 0, L_SHF, 0, L_CTL, 'Q', '!', 0, //10
0, 0, 'Z', 'S', 'A', 'W', '@', 0, //18
0, 'C', 'X', 'D', 'E', '$', '#', 0, //20
0, ' ', 'V', 'F', 'T', 'R', '%', 0, //28
0, 'N', 'B', 'H', 'G', 'Y', '^', 0, //30
0, 0, 'M', 'J', 'U', '&', '*', 0, //38
0, '<', 'K', 'I', 'O', ')', '(', 0, //40
0, '>', '?', 'L', ':', 'P', '_', 0, //48
0, 0, '\"', 0, '{', '+', 0, 0, //50
CAPS, R_SHF, ENTER, '}', 0, '|', 0, 0, //58
0, 0, 0, 0, 0, 0, BKSP, 0, //60
0, '1', 0, '4', '7', 0, 0, 0, //68
'0', '.', '2', '5', '6', '8', ESC, NUM, //70
F11, '+', '3', '-', '*', '9', 0, 0 //78
};
#elif defined RUSSIAN
//
// Map of standard keyboard, Russian Windows layout
//
const char lowerKey[128]={
0, F9, 0, F5, F3, F1, F2, F12, //00
0, F10, F8, F6, F4, TAB, 'ё', 0, //08
0, 0, L_SHF, 0, L_CTL, 'й', '1', 0, //10
0, 0, 'я', 'ы', 'ф', 'ц', '2', 0, //18
0, 'с', 'ч', 'в', 'у', '4', '3', 0, //20
0, ' ', 'м', 'а', 'е', 'к', '5', 0, //28
0, 'т', 'и', 'р', 'п', 'н', '6', 0, //30
0, 0, 'ь', 'о', 'г', '7', '8', 0, //38
0, 'б', 'л', 'ш', 'щ', '0', '9', 0, //40
0, 'ю', '.', 'д', 'ж', 'з', '-', 0, //48
0, 0, 'э', 0, 'х', '=', 0, 0, //50
CAPS, R_SHF, ENTER, 'ъ', 0, '\\', 0, 0, //58
0, 0, 0, 0, 0, 0, BKSP, 0, //60
0, '1', 0, '4', '7', 0, 0, 0, //68
'0', ',', '2', '5', '6', '8', ESC, NUM, //70
F11, '+', '3', '-', '*', '9', 0, 0 //78
};
const char upperKey[128] = {
0, F9, 0, F5, F3, F1, F2, F12, //00
0, F10, F8, F6, F4, TAB, 'Ё', 0, //08
0, 0, L_SHF, 0, L_CTL, 'Й', '!', 0, //10
0, 0, 'Я', 'Ы', 'Ф', 'Ц', '\"', 0, //18
0, 'С', 'Ч', 'В', 'У', ';', '', 0, //20
0, ' ', 'М', 'А', 'Е', 'К', '%', 0, //28
0, 'Т', 'И', 'Р', 'П', 'Н', ':', 0, //30
0, 0, 'Ь', 'О', 'Г', '?', '*', 0, //38
0, 'Б', 'Л', 'Ш', 'Щ', ')', '(', 0, //40
0, 'Ю', ',', 'Д', 'Ж', 'З', '_', 0, //48
0, 0, 'Э', 0, 'Х', '+', 0, 0, //50
CAPS, R_SHF, ENTER, 'Ъ', 0, '/', 0, 0, //58
0, 0, 0, 0, 0, 0, BKSP, 0, //60
0, '1', 0, '4', '7', 0, 0, 0, //68
'0', ',', '2', '5', '6', '8', ESC, NUM, //70
F11, '+', '3', '-', '*', '9', 0, 0 //78
};
#endif
/*
Standard PC init sequence:
Keyboard: AA Self-test passed ;Keyboard controller init
Host: ED Set/Reset Status Indicators
Keyboard: FA Acknowledge
Host: 00 Turn off all LEDs
Keyboard: FA Acknowledge
Host: F2 Read ID
Keyboard: FA Acknowledge
Keyboard: AB First byte of ID
Host: ED Set/Reset Status Indicators ;BIOS init
Keyboard: FA Acknowledge
Host: 02 Turn on Num Lock LED
Keyboard: FA Acknowledge
Host: F3 Set Typematic Rate/Delay ;Windows init
Keyboard: FA Acknowledge
Host: 20 500 ms / 30.0 reports/sec
Keyboard: FA Acknowledge
Host: F4 Enable
Keyboard: FA Acknowledge
Host: F3 Set Typematic Rate/delay
Keyboard: FA Acknowledge
Host: 00 250 ms / 30.0 reports/sec
Keyboard: FA Acknowledge
*/
char init_kbd(void)
{
// enable pullups on the clock and data lines.
// This stops them from floating and generating random chars when no keyboard is attached
// CNCON.ON = 1; // turn on Change Notice for interrupt
// CNPUE.CNPUE15 = 1; // turn on the pullup for pin D6 also called CN15
// CNPUE.CNPUE16 = 1; // turn on the pullup for pin D7 also called CN16
return false;
}
void read_kbd(void)
{
int data = PS2DATA;
int clock = PS2CLOCK;
static char key_up = false;
static unsigned char code = 0;
static unsigned then = 0;
unsigned now = mips_read_c0_register (C0_COUNT, 0);
// Is it time to poll the keyboard yet?
if ((int) (now - then) < POLL)
return;
else
then = now;
if (key_state) { // if clock was high, key_state = 1
if (!clock) { // PS2CLOCK == 0, falling edge detected
key_state = 0; // transition to state 0
key_timer = TIMEOUT; // restart the counter
switch(state){
default:
case PS2START:
if(!data) { // PS2DATA == 0
key_count = 8; // init bit counter
key_parity = 0; // init parity check
code = 0;
state = PS2BIT;
}
break;
case PS2BIT:
code >>= 1; // shift in data bit
if(data) // PS2DATA == 1
code |= 0x80;
key_parity ^= code;
if (--key_count == 0)
state = PS2PARITY; // all bits read
break;
case PS2PARITY:
if(data)
key_parity ^= 0x80;
if(key_parity & 0x80) // parity odd, continue
state = PS2STOP;
else
state = PS2START;
break;
case PS2STOP:
if(data) {
if(code == 0xf0)
key_up = true;
else {
char chr;
static char LShift = 0;
static char RShift = 0;
static char LCtrl = 0;
static char LAlt = 0;
static char CapsLock = 0;
if(key_up) { // check for special key release
key_up = false;
switch(code) {
case L_SHF: LShift = 0;
case R_SHF: RShift = 0;
case L_CTL: LCtrl = 0;
case L_ALT: LAlt = 0;
}
goto exit;
} else { // check for special key press
switch(code) {
case L_SHF: LShift = 1;
case R_SHF: RShift = 1;
case L_CTL: LCtrl = 1;
case L_ALT: LAlt = 1;
case CAPS: CapsLock = !CapsLock;
default: break;
goto exit;
}
}
if(LShift || RShift) // get the ASCII code
chr = lowerKey[code%128];
else
chr = upperKey[code%128];
if(!chr) // it was an unmapped key
break;
if(CapsLock && chr >= 'a' && chr <= 'z') // check for altered keys
chr -= 32;
if(LCtrl)
chr &= 0x1F;
in_queue[in_queue_head] = chr;
in_queue_head = (in_queue_head + 1) % QUEUE_SIZE;
if(chr == 3) { // check for CTL-C
in_queue_head = in_queue_tail = 0;
abort = true;
}
// PrintSignonToUSB = false; // show that the keyboard is in use
LAlt = LAlt; // not used yet
} // if key_up
exit:
code = 0;
} // if(data)
state = PS2START;
} // switch(state)
} // if(!clock)
} else // if(key_state)
key_state = 1; // PS2CLOCK == 1, rising edge detected
if ((key_timer -= POLL) <= 0)
state = PS2START; // timeout, reset state machine
return;
}
char write_kbd(u_char data)
{
// do something here
return false;
}