summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Kramkowski <tk@the-tk.com>2017-05-25 21:56:08 +0100
committerTomasz Kramkowski <tk@the-tk.com>2017-05-25 22:00:15 +0100
commitacb403bcbcbc05256500083d1caea7e22ce4db11 (patch)
treeca9d4ebe25cc0bd000e4ec6fbad3eda46d8f3e03
parent69b0c9e9ca6af68e96e5ff665e61ad3be882a622 (diff)
downloadfmk-acb403bcbcbc05256500083d1caea7e22ce4db11.tar.gz
fmk-acb403bcbcbc05256500083d1caea7e22ce4db11.tar.xz
fmk-acb403bcbcbc05256500083d1caea7e22ce4db11.zip
Basic keyboard implementation
-rw-r--r--Makefile2
-rw-r--r--pit.c126
-rw-r--r--pit.h1
-rw-r--r--setup.c4
-rw-r--r--usb/descriptors.h42
-rw-r--r--usb/endpt1.c71
-rw-r--r--usb/endpt1.h7
-rw-r--r--vectors.s2
8 files changed, 202 insertions, 53 deletions
diff --git a/Makefile b/Makefile
index c9f111c..f270a6d 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@ CFLAGS = -std=c11 $(WARNINGS) -O2 -flto -MMD -MP -ffreestanding -nostdlib
LDFLAGS = -T layout.ld -O2 -flto -ffreestanding -nostdlib
ASFLAGS = $(TARGET_ARCH)
-OBJ := crt0.o vectors.o flashconf.o setup.o fmk.o lib/le.o usb/usb.o \
+OBJ := crt0.o vectors.o flashconf.o setup.o fmk.o lib/le.o pit.o usb/usb.o \
usb/endpt0.o usb/endpt1.o usb/txhandler.o uart.o
include $(MK20DX256)/mk20dx256.mk
diff --git a/pit.c b/pit.c
index d52292e..1241766 100644
--- a/pit.c
+++ b/pit.c
@@ -16,13 +16,133 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <arrlen.h>
+#include <cm4.h>
+#include <reg/gpio.h>
#include <reg/pit.h>
+#include <reg/port.h>
+#include <reg/sim.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
#include "pit.h"
+#include "usb/endpt1.h"
+#include "usb/keycodes.h"
+
+enum {
+ T0_CYCLES = 5000,
+};
+
+struct gpio {
+ uint32_t port;
+ uint32_t gpio;
+ uint32_t bit;
+ unsigned char pin;
+};
+#define GPIO_PIN(port, pin) { \
+ PORT##port##_BASE, \
+ GPIO##port##_BASE, \
+ BV((pin)), \
+ (pin), \
+}
+
+static const struct gpio cols[] = {
+ GPIO_PIN(B, 2),
+ GPIO_PIN(B, 3),
+ GPIO_PIN(B, 18),
+ GPIO_PIN(B, 19),
+ GPIO_PIN(C, 0),
+ GPIO_PIN(C, 8),
+ GPIO_PIN(C, 9),
+ GPIO_PIN(C, 10),
+ GPIO_PIN(C, 11),
+};
+
+static const struct gpio rows[] = {
+ GPIO_PIN(D, 0),
+ GPIO_PIN(D, 1),
+ GPIO_PIN(D, 4),
+ GPIO_PIN(D, 5),
+ GPIO_PIN(D, 6),
+ GPIO_PIN(D, 7),
+ GPIO_PIN(C, 1),
+ GPIO_PIN(C, 2),
+};
+
+/* COL AND ROW SWAPPED!!! */
+static enum keycode keymap[ARRLEN(rows)][ARRLEN(cols)] = {
+ { /* S01 */ KEY_ESCAPE, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, },
+ { /* S10 */ KEY_9, KEY_0, KEY_MINUS, KEY_EQUAL, KEY_NONE, KEY_BACKSPACE, KEY_GRAVE, KEY_TAB, KEY_Q, },
+ { /* S19 */ KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P, },
+ { /* S28 */ KEY_LSQUARE, KEY_RSQUARE, KEY_NONE, KEY_DELETE, KEY_CAPSLK, KEY_A, KEY_S, KEY_D, KEY_F, },
+ { /* S37 */ KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, KEY_SEMICOLON, KEY_QUOTE, KEY_BACKSLASH, KEY_ENTER, },
+ { /* S46 */ KEY_PGUP, KEY_LSHIFT, KEY_NU_BACKSLASH, KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, },
+ { /* S55 */ KEY_M, KEY_COMMA, KEY_PERIOD, KEY_SLASH, KEY_RSHIFT, KEY_UP, KEY_PGDN, KEY_LCTRL, KEY_LGUI, },
+ { /* S64 */ KEY_LALT, KEY_SPACE, KEY_RALT, KEY_NONE, KEY_RCTRL, KEY_LEFT, KEY_DOWN, KEY_RIGHT, KEY_NONE, },
+};
void pit_setup(void)
{
- /* TODO */
- while (1)
- ;
+ /* Set up ports (could be done with GPC registers */
+ for (size_t i = 0; i < ARRLEN(cols); i++) {
+ SET_BIT(GPIO_PDDR(cols[i].gpio), cols[i].pin);
+ GPIO_PCOR(cols[i].gpio) = cols[i].bit;
+ PORT_PCR(cols[i].port, cols[i].pin) = BV(PCR_SRE) | BV(PCR_DSE)
+ | 1 << PCR_MUX;
+ }
+ for (size_t i = 0; i < ARRLEN(rows); i++) {
+ UNSET_BIT(GPIO_PDDR(rows[i].gpio), rows[i].pin);
+ PORT_PCR(rows[i].port, rows[i].pin) = BV(PCR_PFE) | BV(PCR_PE)
+ | 1 << PCR_MUX;
+ }
+
+ /* Enable clock */
+ SET_BIT(SIM_SCGC6, SCGC6_PIT);
+
+ /* NVIC Enable interrupt */
+ ISR_CLRPEND(68);
+ ISR_SETENA(68);
+ INTPRI(68) = 0x10;
+
+ /* First column strobe */
+ GPIO_PSOR(cols[0].gpio) = cols[0].bit;
+
+ /* Set up PIT0 */
+ PIT_MCR = 0;
+
+ PIT_LDVAL(0) = T0_CYCLES - 1;
+ PIT_TFLG(0) = BV(TFLG_TIF);
+ PIT_TCTRL(0) = BV(TCTRL_TIE) | BV(TCTRL_TEN);
+}
+
+static uint8_t kstates[ARRLEN(cols)][ARRLEN(rows)] = { 0 };
+
+static void key_state(int col, int row, bool state)
+{
+ uint8_t kstate;
+
+ kstate = kstates[col][row] = kstates[col][row] << 1 | state;
+
+ if (kstate == 0x7f)
+ usb_endpt1_setkey(keymap[row][col], true);
+ else if (kstate == 0x80)
+ usb_endpt1_setkey(keymap[row][col], false);
+}
+
+void pit0_isr(void)
+{
+ static unsigned char col = 0;
+
+ for (size_t row = 0; row < ARRLEN(rows); row++)
+ key_state(col, row, !!(GPIO_PDIR(rows[row].gpio) & rows[row].bit));
+
+ GPIO_PCOR(cols[col].gpio) = cols[col].bit;
+ col = (col + 1) % ARRLEN(cols);
+ GPIO_PSOR(cols[col].gpio) = cols[col].bit;
+
+ if (col == 0)
+ usb_endpt1_send();
+
+ PIT_TFLG(0) = BV(TFLG_TIF);
}
diff --git a/pit.h b/pit.h
index d82587a..811f024 100644
--- a/pit.h
+++ b/pit.h
@@ -20,5 +20,6 @@
#define FMK_PIT_H
void pit_setup(void);
+void pit0_isr(void);
#endif /* FMK_PIT_H */
diff --git a/setup.c b/setup.c
index 568caaf..89a7762 100644
--- a/setup.c
+++ b/setup.c
@@ -20,8 +20,9 @@
#include <reg.h>
#include <stddef.h>
-#include "usb/usb.h"
+#include "pit.h"
#include "uart.h"
+#include "usb/usb.h"
extern unsigned char _ldata[], _sdata[], _edata[];
extern unsigned char _sbss[], _ebss[];
@@ -108,6 +109,7 @@ void setup(void)
uart_setup();
usb_setup();
+ pit_setup();
/* Enable interrupts for setup */
STI();
diff --git a/usb/descriptors.h b/usb/descriptors.h
index df603a5..a81a0f7 100644
--- a/usb/descriptors.h
+++ b/usb/descriptors.h
@@ -67,17 +67,17 @@ unsigned char ds_conf[] = {
1, // Number of endpoints
3, // Interface class
1, // Interface sub class
- 2, // Interface protocol
+ 1, // Interface protocol
0, // Interface string
/* HID */
9, // Length
33, // Descriptor type
U16LE(0x0111), // HID Class spec version
- 0, // Country code
+ 32, // Country code
1, // Number of descriptors
34, // Descriptor type
-#define DS_HIDREP_SIZE 52
+#define DS_HIDREP_SIZE 29
U16LE(DS_HIDREP_SIZE), // Descriptor length
/* Endpoint */
@@ -93,31 +93,19 @@ _Static_assert(sizeof ds_conf == DS_CONF_SIZE, "sizeof ds_conf != DS_CONF_SIZE")
/* HID Report descriptor */
unsigned char ds_hidrep[] = {
HR_USAGE_PAGE(1), HR_PAGE_GENERIC_DESKTOP,
- HR_USAGE(1), HR_GD_MOUSE,
+ HR_USAGE(1), HR_GD_KEYBOARD,
HR_COLLECTION(1), HR_APPLICATION,
- HR_USAGE(1), HR_GD_POINTER,
- HR_COLLECTION(1), HR_PHYSICAL,
- HR_USAGE_PAGE(1), HR_PAGE_BUTTON,
- HR_USAGE_MINIMUM(1), 1,
- HR_USAGE_MAXIMUM(1), 5,
- HR_LOGICAL_MINIMUM(1), 0,
- HR_LOGICAL_MAXIMUM(1), 1,
- HR_REPORT_COUNT(1), 5,
- HR_REPORT_SIZE(1), 1,
- HR_INPUT(1), HR_DATA | HR_VARIABLE | HR_ABSOLUTE | HR_BIT_FIELD,
- HR_REPORT_COUNT(1), 1,
- HR_REPORT_SIZE(1), 3,
- HR_INPUT(1), HR_CONSTANT | HR_ARRAY | HR_ABSOLUTE | HR_BIT_FIELD,
- HR_USAGE_PAGE(1), HR_PAGE_GENERIC_DESKTOP,
- HR_USAGE(1), HR_GD_X,
- HR_USAGE(1), HR_GD_Y,
- HR_USAGE(1), HR_GD_WHEEL,
- HR_LOGICAL_MINIMUM(1), -127,
- HR_LOGICAL_MAXIMUM(1), 127,
- HR_REPORT_SIZE(1), 8,
- HR_REPORT_COUNT(1), 3,
- HR_INPUT(1), HR_DATA | HR_VARIABLE | HR_RELATIVE | HR_BIT_FIELD,
- HR_END_COLLECTION(0),
+ HR_USAGE_PAGE(1), HR_PAGE_KEYBOARD,
+ HR_USAGE_MINIMUM(1), 4,
+ HR_USAGE_MAXIMUM(1), 231,
+ HR_LOGICAL_MINIMUM(1), 0,
+ HR_LOGICAL_MAXIMUM(1), 1,
+ HR_REPORT_SIZE(1), 1,
+ HR_REPORT_COUNT(1), 228,
+ HR_INPUT(1), HR_DATA | HR_VARIABLE | HR_ABSOLUTE | HR_BIT_FIELD,
+ HR_REPORT_SIZE(1), 4,
+ HR_REPORT_COUNT(1), 1,
+ HR_INPUT(1), HR_CONSTANT | HR_ARRAY | HR_ABSOLUTE | HR_BIT_FIELD,
HR_END_COLLECTION(0),
};
_Static_assert(sizeof ds_hidrep == DS_HIDREP_SIZE, "sizeof ds_hidrep != DS_HIDREP_SIZE");
diff --git a/usb/endpt1.c b/usb/endpt1.c
index 0580349..dcfc61b 100644
--- a/usb/endpt1.c
+++ b/usb/endpt1.c
@@ -19,40 +19,73 @@
#include <reg/usbotg.h>
#include <stddef.h>
#include <stdint.h>
+#include <stdbool.h>
+
+#include <reg/gpio.h>
#include "../uart.h"
#include "bdt.h"
#include "endpt1.h"
+#include "keycodes.h"
+#include "txhandler.h"
#define MAX_PACKET 64
-static unsigned char report[4][4] = {
- { 0x00, 5, 0, 0x00, },
- { 0x00, 0, 5, 0x00, },
- { 0x00, -5, 0, 0x00, },
- { 0x00, 0, -5, 0x00, },
-};
-static int nextrep;
+static struct tx_ctx tx;
+#define THIS_EP 1
+static volatile struct usb0_bd (* const this_bdt)[2] = usb_bdt[THIS_EP];
-void usb_endpt1_enable(void)
+unsigned char report[29];
+volatile bool sendrep;
+
+void usb_endpt1_setkey(enum keycode keycode, bool state)
{
- nextrep = 0;
+ unsigned char byte, bit;
+
+ if (keycode == KEY_NONE)
+ return;
+
+ keycode -= 4;
+ byte = keycode / 8;
+ bit = keycode % 8;
+
+ if (state)
+ SET_BIT(report[byte], bit);
+ else
+ UNSET_BIT(report[byte], bit);
+
+ sendrep = true;
+}
- usb_bdt[1][BDT_TX][BDT_EVEN].addr = &report[0];
- usb_bdt[1][BDT_TX][BDT_EVEN].desc = USB0_BD_INIT(4, nextrep % 2);
- nextrep++;
+void usb_endpt1_send(void)
+{
+ if (!sendrep)
+ return;
+ if (!tx_isempty(&tx)) {
+ return;
+ }
+
+ tx_que(&tx, report, sizeof report);
+ sendrep = false;
+}
+
+void usb_endpt1_enable(void)
+{
+ this_bdt[BDT_TX][BDT_EVEN].addr = NULL;
+ this_bdt[BDT_TX][BDT_EVEN].desc = 0;
- usb_bdt[1][BDT_TX][BDT_ODD].addr = &report[1];
- usb_bdt[1][BDT_TX][BDT_ODD].desc = USB0_BD_INIT(4, nextrep % 2);
- nextrep++;
+ this_bdt[BDT_TX][BDT_ODD].addr = NULL;
+ this_bdt[BDT_TX][BDT_ODD].desc = 0;
- USB0_ENDPT(1) = BV(ENDPT_EPTXEN) | BV(ENDPT_EPHSHK);
+ USB0_ENDPT(THIS_EP) = BV(ENDPT_EPTXEN) | BV(ENDPT_EPHSHK);
+ tx = TX_CTX(this_bdt[BDT_TX], MAX_PACKET);
+ tx_que(&tx, report, sizeof report);
}
void usb_endpt1_disable(void)
{
- USB0_ENDPT(1) = 0;
+ USB0_ENDPT(THIS_EP) = 0;
}
void usb_endpt1_token(uint8_t state)
@@ -63,9 +96,7 @@ void usb_endpt1_token(uint8_t state)
switch (GET_BITS(bd->desc, BD_TOK_PID)) {
case BD_TOK_PID_IN:
- bd->addr = &report[nextrep];
- bd->desc = USB0_BD_INIT(4, nextrep % 2);
- nextrep = (nextrep + 1) % 4;
+ tx_push(&tx);
break;
}
}
diff --git a/usb/endpt1.h b/usb/endpt1.h
index fa26bd9..35e1a2c 100644
--- a/usb/endpt1.h
+++ b/usb/endpt1.h
@@ -19,6 +19,13 @@
#ifndef FMK_USB_ENDPT1_H
#define FMK_USB_ENDPT1_H
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "keycodes.h"
+
+void usb_endpt1_setkey(enum keycode keycode, bool state);
+void usb_endpt1_send(void);
void usb_endpt1_enable(void);
void usb_endpt1_disable(void);
void usb_endpt1_token(uint8_t state);
diff --git a/vectors.s b/vectors.s
index 794d194..c0d382c 100644
--- a/vectors.s
+++ b/vectors.s
@@ -92,7 +92,7 @@
.long 0 // 81 CMT: -
.long 0 // 82 RTC: Alarm interrupt
.long 0 // 83 RTC: Seconds interrupt
-.long 0 // 84 PIT: Channel 0
+.long pit0_isr// 84 PIT: Channel 0
.long 0 // 85 PIT: Channel 1
.long 0 // 86 PIT: Channel 2
.long 0 // 87 PIT: Channel 3