I2c Keyboard

From Projects Wiki
Jump to: navigation, search

This small snipped of code will turn a Digispark into a i2c USB keyboard. That means any project you have using 5v i2c (3.3 works as well if you only use data/clock/ground) can write data to a computer as if it were a keyboard.

#include "DigiKeyboard.h"
#include <TinyWireS.h>
// By Mark Balliet <posicat@pobox.com>
#define I2C_SLAVE_ADDRESS 0x4
#define LED 1
uchar   reportBuffer[2];
uchar	recieveBuffer[16];
byte	bufferIdx=0;
void setup() { 
  pinMode(LED, OUTPUT);
  digitalWrite(LED, HIGH);
  TinyWireS.begin(I2C_SLAVE_ADDRESS);
  TinyWireS.onReceive(receiveEvent);
  TinyWireS.onRequest(requestEvent);
  blinkLED();
} 
void loop() { 
  tws_delay(500);
  digitalWrite(LED, HIGH);
  DigiKeyboard.update();
  DigiKeyboard.sendKeyStroke(0);  
  digitalWrite(LED, LOW);
}
void receiveEvent(uint8_t howMany) {
	if (howMany < 1) { return; } // Sanity-check
	digitalWrite(LED, HIGH); 
	
	if (bufferIdx>16) {
		blinkLED();
		bufferIdx=0;
	}
	// Write the data into the recieveBuffer
	byte data = TinyWireS.receive();
	recieveBuffer[bufferIdx]=data;
	bufferIdx++;
	
	// Recieve data until we get a 0xFF then we transmit unless it's the first character (keyboard modifier)
	if (bufferIdx>0 && data == 255) {
		processBuffer();
		// Clear recieve buffer, by reseting pointer
		bufferIdx=0;
	}
}
void processBuffer() {
	digitalWrite(LED, LOW); 
	byte modifiers=recieveBuffer[0];
	
	for(byte i=1;i<bufferIdx;i++) {
		digitalWrite(LED, HIGH); 
		byte keyStroke=recieveBuffer[i];
		// Make sure the USB bus knows we're here.
		DigiKeyboard.update();
		waitForTransmitToFinish();
		// Clear reportBuffer
		memset(reportBuffer, 0, sizeof(reportBuffer));
		// Set our data
		reportBuffer[0] = modifiers;
		reportBuffer[1] = recieveBuffer[i];
		// Send data via USB
		usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
		waitForTransmitToFinish();
		// Stop transmitting key
		memset(reportBuffer, 0, sizeof(reportBuffer));      
		usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
		digitalWrite(LED, LOW); 
	}
}
void waitForTransmitToFinish() {
		while (!usbInterruptIsReady()) {
			usbPoll();
			_delay_ms(5);
		}
}
void blinkLED() {
	for (byte i=0;i<5;i++) {
		digitalWrite(LED, HIGH); 
		tws_delay(200);
		digitalWrite(LED, LOW); 
		tws_delay(200);
	}
}
void requestEvent() {
  TinyWireS.send(255);
}