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 @@ ...@@ -79,6 +79,11 @@
#define AI2C_REGISTER_MAX 0x53 /* Must be set to the max register address */ #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 * Device ID
*/ */
#define AI2C_ID 0x4242 #define AI2C_ID 0x4242
......
...@@ -22,27 +22,107 @@ ...@@ -22,27 +22,107 @@
*/ */
#include <Wire.h> #include <Wire.h>
/* /*
* Project Includes * Project Includes
*/ */
#include "ai2c_interface.h" #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; unsigned long next_send_intr;
int current_intr_val; 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]; unsigned char register_file[AI2C_REGISTER_MAX];
/*
* Interval timers
*/
Timer *keytimer = new Timer(KEY_CHECK_INTERVAL);
Timer *intrtimer = new Timer(2);
void void
i2cRequest(void) { i2cRequest(void) {
unsigned char shadow_register_file[AI2C_REGISTER_MAX];
int addr = register_file[AI2C_REGISTER_READ_ADDR]; int addr = register_file[AI2C_REGISTER_READ_ADDR];
int len = register_file[AI2C_REGISTER_READ_BYTES]; int len = register_file[AI2C_REGISTER_READ_BYTES];
if (addr >= AI2C_REGISTER_MAX) addr = 0; if (addr >= AI2C_REGISTER_MAX) addr = 0;
if (len >= (AI2C_REGISTER_MAX - addr)) len = 1; 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 void
...@@ -67,11 +147,12 @@ i2cReceive(int bytes) { ...@@ -67,11 +147,12 @@ i2cReceive(int bytes) {
char c = Wire.read(); // receive byte as a character char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character Serial.print(c); // print the character
} }
#if 1
Serial.print("I2C Write: addr = "); Serial.print("I2C Write: addr = 0x");
Serial.print(addr); Serial.print(addr, HEX);
Serial.print(" data = "); Serial.print(" data = 0x");
Serial.println(data); Serial.println(data, HEX);
#endif
switch (addr) { switch (addr) {
case AI2C_REGISTER_CAMERA_FRAC_LOW: case AI2C_REGISTER_CAMERA_FRAC_LOW:
...@@ -94,9 +175,77 @@ i2cReceive(int bytes) { ...@@ -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 void
setup() { setup() {
// Initialize console // Initialize console
delay(5000);
Serial.begin(9600); Serial.begin(9600);
Serial.println("Arduino I2C Keyboard Driver Built " __DATE__ " " __TIME__); Serial.println("Arduino I2C Keyboard Driver Built " __DATE__ " " __TIME__);
...@@ -122,10 +271,48 @@ setup() { ...@@ -122,10 +271,48 @@ setup() {
snprintf(&(register_file[AI2C_REGISTER_VERS_STR]), AI2C_VER_STR_LEN, snprintf(&(register_file[AI2C_REGISTER_VERS_STR]), AI2C_VER_STR_LEN,
"AI2C Built: " __DATE__ " " __TIME__); "AI2C Built: " __DATE__ " " __TIME__);
register_file[AI2C_REGISTER_READ_BYTES] = 1; 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 void
loop() { loop() {
/* Test Code */
#if 0
if (millis() > next_send_intr) { if (millis() > next_send_intr) {
current_intr_val = current_intr_val ? 0 : 1; current_intr_val = current_intr_val ? 0 : 1;
digitalWrite(INTERRUPT_PIN, current_intr_val); digitalWrite(INTERRUPT_PIN, current_intr_val);
...@@ -133,7 +320,17 @@ loop() { ...@@ -133,7 +320,17 @@ loop() {
Serial.print("Interupt pin now "); Serial.print("Interupt pin now ");
Serial.println(current_intr_val); 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