BigW Consortium Gitlab

Commit e5e9f225 by Forest Godfrey

Add initial key handling. Can now track key status and send I2C interrupts.

parent 76c6fe42
......@@ -79,6 +79,11 @@
#define AI2C_REGISTER_MAX 0x53 /* Must be set to the max register address */
/*
* Commands
*/
#define AI2C_CMD_CMD_COMPLETE 0x00 /* Previous command completed - must be read back */
/*
* Device ID
*/
#define AI2C_ID 0x4242
......
......@@ -22,27 +22,107 @@
*/
#include <Wire.h>
/*
* Project Includes
*/
#include "ai2c_interface.h"
#include "Timer.h"
//#define DEBUG_KEYS 1
#ifndef DEBUG_KEYS
#define KEY_CHECK_INTERVAL 10
#else
#define KEY_CHECK_INTERVAL 5000
uint16_t keytest = 0;
#endif
#define INTERRUPT_PIN 10
#define INTERRUPT_PIN 9
typedef struct {
int8_t pin;
bool enable_pullup;
} key_pin_t;
#define MAX_KEY_COUNT 16
static key_pin_t keypins[MAX_KEY_COUNT] = {
{9, true}, /* 0 - Up */
{7, true}, /* 1 - Down */
{8, true}, /* 2 - Left */
{6, true}, /* 3 - Right */
{4, true}, /* 4 - "A" */
{5, true}, /* 5 - "B" */
{1, true}, /* 6 - Select */
{0, true}, /* 7 - Start */
{11, true}, /* 8 - Screen On/Off */
{-1, false}, /* 9 - Unused */
{-1, false}, /* 10 - Unused */
{-1, false}, /* 11 - Unused */
{-1, false}, /* 12 - Unused */
{-1, false}, /* 13 - Unused */
{-1, false}, /* 14 - Unused */
{-1, false}, /* 15 - Unused */
};
/*
* Interrupt to host generation
*/
bool intr_running;
bool send_intr;
/* Test Code */
unsigned long next_send_intr;
int current_intr_val;
/*
* The I2C read routine read/write routines come directly out of the register file.
*/
unsigned char register_file[AI2C_REGISTER_MAX];
/*
* Interval timers
*/
Timer *keytimer = new Timer(KEY_CHECK_INTERVAL);
Timer *intrtimer = new Timer(2);
void
i2cRequest(void) {
unsigned char shadow_register_file[AI2C_REGISTER_MAX];
int addr = register_file[AI2C_REGISTER_READ_ADDR];
int len = register_file[AI2C_REGISTER_READ_BYTES];
if (addr >= AI2C_REGISTER_MAX) addr = 0;
if (len >= (AI2C_REGISTER_MAX - addr)) len = 1;
//noInterrupts();
memcpy(shadow_register_file, register_file, sizeof(shadow_register_file));
/*
* Deal with read/clear registers.
*/
switch (addr) {
case AI2C_REGISTER_KEY_DOWN_LOW:
case AI2C_REGISTER_KEY_DOWN_HIGH:
case AI2C_REGISTER_KEY_UP_LOW:
case AI2C_REGISTER_KEY_UP_HIGH:
register_file[addr] = 0;
break;
default:
/* No-op */
break;
}
//interrupts();
Wire.write(&(register_file[addr]), len);
Wire.write(&(shadow_register_file[addr]), len);
#if 1
Serial.print("Read addr = 0x");
Serial.print(addr, HEX);
Serial.print(" len = ");
Serial.print(len);
Serial.print(" First byte = 0x");
Serial.println(shadow_register_file[addr], HEX);
#endif
}
void
......@@ -67,11 +147,12 @@ i2cReceive(int bytes) {
char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character
}
Serial.print("I2C Write: addr = ");
Serial.print(addr);
Serial.print(" data = ");
Serial.println(data);
#if 1
Serial.print("I2C Write: addr = 0x");
Serial.print(addr, HEX);
Serial.print(" data = 0x");
Serial.println(data, HEX);
#endif
switch (addr) {
case AI2C_REGISTER_CAMERA_FRAC_LOW:
......@@ -94,9 +175,77 @@ i2cReceive(int bytes) {
}
}
/*
* handleKeys: Check current key status. Set bits for any keys pressed or released.
* Triggers an interrupt when necessary.
*/
void
handleKeys(void) {
bool needintr;
int i;
uint32_t current_keys;
uint8_t keys_low, keys_high;
current_keys = 0;
#ifndef DEBUG_KEYS
for (i = 0; i < MAX_KEY_COUNT; i++) {
uint32_t val;
if (keypins[i].pin < 0) continue;
val = digitalRead(keypins[i].pin);
val &= 1;
current_keys |= val << i;
}
#else
keytest = keytest << 1;
if (!keytest) keytest = 1;
current_keys = keytest;
Serial.print("Current keys: 0x");
Serial.println(current_keys, HEX);
#endif
keys_low = current_keys & 0xff;
keys_high = (current_keys >> 8) & 0xff;
/*
* This needs to be an atomic update so we need to shut off interrupts.
*/
//noInterrupts();
/*
* All keys that have changed AND with current keys that are currently up is keys that have been released.
*/
register_file[AI2C_REGISTER_KEY_UP_LOW] |= (register_file[AI2C_REGISTER_KEY_STATUS_LOW] ^ keys_low) & keys_low;
register_file[AI2C_REGISTER_KEY_UP_HIGH] |= (register_file[AI2C_REGISTER_KEY_STATUS_HIGH] ^ keys_high) & keys_high;
/*
* All keys that have changed AND with keys that were release is all keys that have been pressed.
*/
register_file[AI2C_REGISTER_KEY_DOWN_LOW] |= (register_file[AI2C_REGISTER_KEY_STATUS_LOW] ^ keys_low) & register_file[AI2C_REGISTER_KEY_STATUS_LOW];
register_file[AI2C_REGISTER_KEY_DOWN_HIGH] |= (register_file[AI2C_REGISTER_KEY_STATUS_HIGH] ^ keys_high) & register_file[AI2C_REGISTER_KEY_STATUS_HIGH];
/* Set the current key status */
needintr = (register_file[AI2C_REGISTER_KEY_STATUS_LOW] != keys_low) || (register_file[AI2C_REGISTER_KEY_STATUS_HIGH] != keys_high);
register_file[AI2C_REGISTER_KEY_STATUS_LOW] = keys_low;
register_file[AI2C_REGISTER_KEY_STATUS_HIGH] = keys_high;
/* Re-enable interrupts */
//interrupts();
if (needintr) send_intr = true;
}
/*
* sendInterruptDone: Callback on interrupt->host completion.
*/
void
sendInterruptDone(void) {
digitalWrite(INTERRUPT_PIN, 1);
intr_running = false;
}
void
setup() {
// Initialize console
delay(5000);
Serial.begin(9600);
Serial.println("Arduino I2C Keyboard Driver Built " __DATE__ " " __TIME__);
......@@ -122,10 +271,48 @@ setup() {
snprintf(&(register_file[AI2C_REGISTER_VERS_STR]), AI2C_VER_STR_LEN,
"AI2C Built: " __DATE__ " " __TIME__);
register_file[AI2C_REGISTER_READ_BYTES] = 1;
/*
* Set up key pins
*/
#if 1
for (int i = 0; i < MAX_KEY_COUNT; i++) {
int pinmode = keypins[i].enable_pullup ? INPUT_PULLUP : INPUT;
if (keypins[i].pin < 0) continue;
pinMode(keypins[i].pin, pinmode);
}
#endif
/*
* Set up timers
*/
keytimer->setOnTimer(handleKeys);
keytimer->Start();
intrtimer->setOnTimer(sendInterruptDone);
intrtimer->setSingleShot(true);
intr_running = false;
}
/*
* sendInterrupt: Send an interrupt to the host. Interrupts are falling edge triggered.
*/
void
sendInterrupt(void) {
Serial.println("Sending interrupt...");
digitalWrite(INTERRUPT_PIN, 0);
send_intr = false;
intr_running = true;
intrtimer->Resume();
}
void
loop() {
/* Test Code */
#if 0
if (millis() > next_send_intr) {
current_intr_val = current_intr_val ? 0 : 1;
digitalWrite(INTERRUPT_PIN, current_intr_val);
......@@ -133,7 +320,17 @@ loop() {
Serial.print("Interupt pin now ");
Serial.println(current_intr_val);
}
delay(10);
#endif
if (send_intr & !intr_running) {
Serial.print("Keys: 0x");
Serial.print(register_file[AI2C_REGISTER_KEY_STATUS_HIGH], HEX);
Serial.println(register_file[AI2C_REGISTER_KEY_STATUS_LOW], HEX);
sendInterrupt();
}
keytimer->Update();
intrtimer->Update();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment