BigW Consortium Gitlab

Commit 14d9b079 by Forest Godfrey

Add basic register file and also add common interface definition.

parent 222ac6b2
/*
* This file is part of the Arduino I2C keyboard.
* Copyright (C) 2018 Forest Godfrey <fgodfrey@bigw.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef _AI2C_INTERFACE_H
#define _AI2C_INTERFACE_H
/*
* Address on the I2C Bus
*/
#define AI2C_DEVICE_ADDRESS 0x42
/*
* The basic interface is as follows:
* The device generates an interrupt on any of the following conditions:
* - Key pressed
* - Key released
* - Camera operation finished
* - Battery status change
*
* To write data, the host sends a write message with three 8 bit words:
* <i2c address> <register address> <register data>
*
* To read data, the host writes AI2C_REGISTER_READ_ADDR and
* AI2C_REGISTER_READ_BYTES. The host can then repeatedly read the device.
* Each read will produce the amount of data requested starting at the written
* address. For instance, the host could set the read address to
* AI2C_REGISTER_KEY_DOWN_LOW and the length to 6 bytes and read all 6 bytes
* of keyboard status every time a read is generated.
*
* The following abreviations are used for each register:
* - RO: Read Only - The register is managed by the Arduino. Writes will be silently dropped
* - RC: Read Clear - Reading this register clears its contents
* - RW: Read Write - This register can be read or written.
* - RWC: Read Write/Clear - Register can be read. Write 1 to a bit to clear it. Individual bits may be RO
*/
/*
* AI2C Registers
*/
#define AI2C_REGISTER_ID_LOW 0x00 /* (RO) Device ID Low 8 bits */
#define AI2C_REGISTER_ID_HIGH 0x01 /* (RO) Device ID High 8 bits */
#define AI2C_REGISTER_REG_REV 0x02 /* (RO) Register interface compatibility version */
#define AI2C_REGISTER_VERS_STR 0x03 /* (RO) Version string - 64 bytes */
#define AI2C_REGISTER_KEY_STATUS_LOW 0x44 /* (RO) Keys down/up */
#define AI2C_REGISTER_KEY_STATUS_HIGH 0x45
#define AI2C_REGISTER_KEY_DOWN_LOW 0x46 /* (RC) Keys pressed since last check - Read-Clear */
#define AI2C_REGISTER_KEY_DOWN_HIGH 0x47
#define AI2C_REGISTER_KEY_UP_LOW 0x48 /* (RC) Keys released since last check - Read-Clear */
#define AI2C_REGISTER_KEY_UP_HIGH 0x49
#define AI2C_REGISTER_CAMERA_FRAC_LOW 0x4a /* (RW) Fractional Camera Shutter Speed in 100's of uSecs */
#define AI2C_REGISTER_CAMERA_FRAC_HIGH 0x4b
#define AI2C_REGISTER_CAMERA_SECS 0x4c /* (RW) Shutter Speed in Seconds - added to fraction */
#define AI2C_REGISTER_COMMAND 0x4d /* (RW) Execute command (like "focus" or "fire") */
#define AI2C_REGISTER_READ_ADDR 0x4e /* (RW) Address to read on a read command */
#define AI2C_REGISTER_READ_BYTES 0x4f /* (RW) Number of bytes to receive on a read */
#define AI2C_REGISTER_STATUS 0x50 /* (RWC) Various status bits */
#define AI2C_INTR_MASK_LOW 0x51 /* (RW) Interrupt mask */
#define AI2C_INTR_MASK_HIGH 0x52
#define AI2C_POWER_STATUS 0x53 /* (RO) Battery status */
#define AI2C_BAT_VOLTAGE_LOW 0x54 /* (RO) Battery voltage XXX - units? */
#define AI2C_BAT_VOLTAGE_HIGH 0x55
#define AI2C_REGISTER_MAX 0x53 /* Must be set to the max register address */
/*
* Device ID
*/
#define AI2C_ID 0x4242
/*
* Register revision ID. Change when register interface becomes incompatible
*/
#define AI2C_REV 0x01
/*
* Max length of build version string. Registers will be padded with zeros
*/
#define AI2C_VER_STR_LEN 64
#endif /* _AI2C_INTERFACE_H */
/*
* This file is part of the Arduino I2C keyboard.
* Copyright (C) 2018 Forest Godfrey <fgodfrey@bigw.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*
* Global Includes
*/
#include <Wire.h>
/*
* Project Includes
*/
#include "ai2c_interface.h"
#define INTERRUPT_PIN 9
#define I2C_ADDRESS 0x42
unsigned long next_send_intr;
int current_intr_val;
void i2cReceive(int bytes) {
unsigned char register_file[AI2C_REGISTER_MAX];
void
i2cRequest(void) {
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;
Wire.write(&(register_file[addr]), len);
}
void
i2cReceive(int bytes) {
int addr, data;
Serial.print("Bytes available: ");
Serial.println(bytes);
addr = data = 0;
/*
* We should always get two bytes, but we don't want to block if we didn't.
*/
if (Wire.available() > 0) {
addr = Wire.read();
}
if (Wire.available() > 0) {
data = Wire.read();
}
while (1 < Wire.available()) { // loop through all but the last
while (Wire.available()) { // loop through all but the last
char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character
}
int x = Wire.read(); // receive byte as an integer
Serial.println(x); // print the integer
Serial.print("I2C Write: addr = ");
Serial.print(addr);
Serial.print(" data = ");
Serial.println(data);
switch (addr) {
case AI2C_REGISTER_CAMERA_FRAC_LOW:
case AI2C_REGISTER_CAMERA_FRAC_HIGH:
case AI2C_REGISTER_CAMERA_SECS:
case AI2C_REGISTER_READ_ADDR:
case AI2C_REGISTER_READ_BYTES:
case AI2C_INTR_MASK_LOW:
case AI2C_INTR_MASK_HIGH:
/*
* "Normal" writeable registers that don't cause any actions.
*/
register_file[addr] = data;
break;
default:
/*
* Bad address or it was read-only - ignore
*/
break;
}
}
void setup() {
void
setup() {
// Initialize console
Serial.begin(9600);
Serial.println("Arduino I2C Keyboard Driver Built " __DATE__ " " __TIME__);
......@@ -28,15 +105,27 @@ void setup() {
pinMode(INTERRUPT_PIN, OUTPUT);
// Initialize I2C Slave Interface
Wire.begin(I2C_ADDRESS); // join i2c bus with address #8
Wire.begin(AI2C_DEVICE_ADDRESS); // join i2c bus with address
Wire.onReceive(i2cReceive);
Wire.onRequest(i2cRequest);
next_send_intr = 0;
current_intr_val = 1;
/*
* Initialize register file.
*/
memset(register_file, 0, sizeof(register_file));
register_file[AI2C_REGISTER_ID_LOW] = AI2C_ID & 0xff;
register_file[AI2C_REGISTER_ID_HIGH] = (AI2C_ID >> 8) & 0xff;
register_file[AI2C_REGISTER_REG_REV] = AI2C_REV;
snprintf(&(register_file[AI2C_REGISTER_VERS_STR]), AI2C_VER_STR_LEN,
"AI2C Built: " __DATE__ " " __TIME__);
register_file[AI2C_REGISTER_READ_BYTES] = 1;
}
void loop() {
// put your main code here, to run repeatedly:
void
loop() {
if (millis() > next_send_intr) {
current_intr_val = current_intr_val ? 0 : 1;
digitalWrite(INTERRUPT_PIN, current_intr_val);
......
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