mirror of
https://github.com/google/mozc-devices.git
synced 2025-11-08 16:53:28 +03:00
Initial upload of the Physical Flick keyboard files.
This commit is contained in:
93
mozc-furikku/README.md
Normal file
93
mozc-furikku/README.md
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
Copyright 2016 Google Inc.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
Summary
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
Circuit diagram and firmware of Google Japanese Input physical flick version.
|
||||||
|
|
||||||
|
|
||||||
|
Files
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
* README.md -- this file
|
||||||
|
* arduino/flick/* -- firmware source code (Arduino sketch)
|
||||||
|
* circuit.png -- circuit diagram
|
||||||
|
|
||||||
|
|
||||||
|
Building your device
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
## Electronic parts
|
||||||
|
|
||||||
|
* Arduino Nano * 1
|
||||||
|
* RN-42-I/RM * 1
|
||||||
|
* SJoys 2-axes joystick module (Sainsmart) * 12
|
||||||
|
* 0.1uF ceramic capacitor * 4
|
||||||
|
* 470 ohm resistor * 1
|
||||||
|
* 1k ohm resistor * 1
|
||||||
|
* Connectors
|
||||||
|
|
||||||
|
## RN42 configuration
|
||||||
|
|
||||||
|
This step is required for the first time, or when changing the device's name.
|
||||||
|
See Microchip's documents for detail.
|
||||||
|
|
||||||
|
1. Run a terminal emulator and open the serial port for Arduino.
|
||||||
|
2. Type '!' to enter pass-through mode.
|
||||||
|
3. Type '$$$'.
|
||||||
|
4. Configure the module by these commands:
|
||||||
|
|
||||||
|
* * * * * *
|
||||||
|
SU,115k
|
||||||
|
SM,6
|
||||||
|
SA,2
|
||||||
|
S~,6
|
||||||
|
SH,0000
|
||||||
|
SN,MY_PHYSICAL_FLICK_KEYBOARD
|
||||||
|
R,1
|
||||||
|
* * * * * *
|
||||||
|
MY\_PHYSICAL\_FLICK\_KEYBOARD is a device name that will appear when you scan
|
||||||
|
Bluetooth devices, and can be replaced by your preferred name.
|
||||||
|
|
||||||
|
The commands will configure the module as follows:
|
||||||
|
|
||||||
|
* 115200bps
|
||||||
|
* Pairing mode
|
||||||
|
* SSP "just works" mode
|
||||||
|
* SPP profile
|
||||||
|
* HID flag register = 0 (keyboard)
|
||||||
|
|
||||||
|
|
||||||
|
Using flick input
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
## Power supply
|
||||||
|
|
||||||
|
When operating the device, supply power by USB cables to Arduino Nano.
|
||||||
|
|
||||||
|
## Bluetooth pairing
|
||||||
|
|
||||||
|
Using your device (e.g. Android phone), scan Bluetooth devices and you will
|
||||||
|
find MY\_PHYSICAL\_FLICK\_KEYBOARD (or the name you set up) in the available
|
||||||
|
device list.
|
||||||
|
|
||||||
|
After pairing, find the device in the "physical keyboard" section and choose
|
||||||
|
"English - U.S." keyboard layout for it.
|
||||||
|
|
||||||
|
## How to input
|
||||||
|
|
||||||
|
Switch the Japanese IME on the paired device to romaji input mode.
|
||||||
|
Characters will be input as flick or press a key.
|
||||||
110
mozc-furikku/arduino/flick/flick.ino
Normal file
110
mozc-furikku/arduino/flick/flick.ino
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
#include <SPI.h>
|
||||||
|
#include "flick_keyboard.h"
|
||||||
|
|
||||||
|
// Number of A/D converter ICs.
|
||||||
|
const int kNumAdcIc = 3;
|
||||||
|
const int kCsPins[kNumAdcIc] = {10, 9, 8};
|
||||||
|
|
||||||
|
const int kButtonPins[12] = {
|
||||||
|
// If you use Arduino Nano version 2, use A6 and A7 instead of A0 and A1.
|
||||||
|
// (which are actually port C, thus used as digital input)
|
||||||
|
A0, A1, A2, A3, A4, A5,
|
||||||
|
7, 6, 5, 4, 3, 2
|
||||||
|
};
|
||||||
|
|
||||||
|
FlickKeyboard keyboard;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
for (size_t i = 0; i < kNumAdcIc; i++) {
|
||||||
|
pinMode(kCsPins[i], OUTPUT);
|
||||||
|
digitalWrite(kCsPins[i], HIGH);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < 12; i++) {
|
||||||
|
pinMode(kButtonPins[i], INPUT_PULLUP);
|
||||||
|
}
|
||||||
|
SPI.begin();
|
||||||
|
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectChip(uint8_t id) {
|
||||||
|
if (id > kNumAdcIc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < kNumAdcIc; i++) {
|
||||||
|
digitalWrite(kCsPins[i], HIGH);
|
||||||
|
}
|
||||||
|
digitalWrite(kCsPins[id], LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeselectChips() {
|
||||||
|
for (size_t i = 0; i < kNumAdcIc; i++) {
|
||||||
|
digitalWrite(kCsPins[i], HIGH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch a ADC result of a specified channel from a MCP3208.
|
||||||
|
int16_t ReadMcp3208Adc(uint8_t chipId, uint8_t channel) {
|
||||||
|
SelectChip(chipId);
|
||||||
|
// MCP3208 receives only 5 bits for start.
|
||||||
|
// Since the SPI library only supports bytewise tramsmission,
|
||||||
|
// we send dummy (high-level) bits before the start bit.
|
||||||
|
// Send data :
|
||||||
|
// 3 dummy bits (000)
|
||||||
|
// start bit (1)
|
||||||
|
// select single-end (1)
|
||||||
|
// 3 address bits: d2, d1, d0
|
||||||
|
SPI.transfer(0x18 | channel);
|
||||||
|
uint16_t b0 = SPI.transfer(0x00);
|
||||||
|
uint16_t b1 = SPI.transfer(0x00);
|
||||||
|
DeselectChips();
|
||||||
|
// The first output bit is high-Z (sampling period).
|
||||||
|
// The second bit is always 0.
|
||||||
|
// Then the ADC value follows in MSB first format.
|
||||||
|
// Therefore the first received byte contains 6 bits from MSB,
|
||||||
|
// and the second byte contains the remainder.
|
||||||
|
return ((b0 & 0x3f) << 6) | ((b1 & 0xfc) >> 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadSwitches(bool* button) {
|
||||||
|
for (size_t i = 0; i < 12; i++) {
|
||||||
|
button[i] = (digitalRead(kButtonPins[i]) == LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadVolumes(uint16_t* data) {
|
||||||
|
byte inByte = 0;
|
||||||
|
for (uint8_t j = 0; j < kNumAdcIc; j++) {
|
||||||
|
for (uint8_t i = 0; i < 8; i++) {
|
||||||
|
data[j * 8 + i] = ReadMcp3208Adc(j, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Passes through any serial input to the output.
|
||||||
|
// This mode can be used to configure RN-42 using serial terminal
|
||||||
|
// connected to Arduino.
|
||||||
|
void EchoBackMode() {
|
||||||
|
while (true) {
|
||||||
|
if (Serial.available()) {
|
||||||
|
Serial.print((char)Serial.read());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (Serial.available() && Serial.read() == '!') {
|
||||||
|
EchoBackMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
SensorData keys;
|
||||||
|
ReadVolumes(keys.axes);
|
||||||
|
ReadSwitches(keys.button);
|
||||||
|
int nOutputs;
|
||||||
|
const char* outputs[COLS];
|
||||||
|
keyboard.ProcessSensorData(keys, COLS, outputs, &nOutputs);
|
||||||
|
for (size_t i = 0; i < nOutputs; i++) {
|
||||||
|
Serial.print(outputs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
67
mozc-furikku/arduino/flick/flick_keyboard.cpp
Normal file
67
mozc-furikku/arduino/flick/flick_keyboard.cpp
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#include "flick_keyboard.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define ADC_BITS 12
|
||||||
|
|
||||||
|
void FlickKeyboard::ProcessSensorData(const SensorData& data, size_t maxKeyNum,
|
||||||
|
const char** outputStrings, int* nOutputs) {
|
||||||
|
const char* characters[COLS][ROWS] = {
|
||||||
|
{"a", "i", "u", "e", "o"},
|
||||||
|
{"ka", "ki", "ku", "ke", "ko"},
|
||||||
|
{"sa", "si", "su", "se", "so"},
|
||||||
|
{"ta", "ti", "tu", "te", "to"},
|
||||||
|
{"na", "ni", "nu", "ne", "no"},
|
||||||
|
{"ha", "hi", "hu", "he", "ho"},
|
||||||
|
{"ma", "mi", "mu", "me", "mo"},
|
||||||
|
{"ya", "(", "yu", ")", "yo"},
|
||||||
|
{"ra", "ri", "ru", "re", "ro"},
|
||||||
|
{"\n", "\b", "", " ", ""},
|
||||||
|
{"wa", "wo", "nn", "-", "~"},
|
||||||
|
{",", ".", "?", "!", "..."}
|
||||||
|
};
|
||||||
|
*nOutputs = 0;
|
||||||
|
for (size_t i = 0; i < COLS; i++) {
|
||||||
|
Direction s = ConvertToFlickState(data.axes[i * 2 + 1],
|
||||||
|
data.axes[i * 2], data.button[i]);
|
||||||
|
if (lastState[i] == NONE && s != NONE) {
|
||||||
|
if (*nOutputs < maxKeyNum) {
|
||||||
|
outputStrings[(*nOutputs)++] = characters[i][s];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastState[i] = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FlickKeyboard::FlickKeyboard() {
|
||||||
|
for (size_t i = 0; i < COLS; i++) {
|
||||||
|
lastState[i] = NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Direction FlickKeyboard::ConvertToFlickState(
|
||||||
|
int16_t x, int16_t y, bool buttonPressed) {
|
||||||
|
const int16_t adScale = 1 << ADC_BITS;
|
||||||
|
const int16_t adCenter = adScale / 2;
|
||||||
|
const int16_t threshold = adScale * 0.4;
|
||||||
|
|
||||||
|
int16_t diffX = x - adCenter;
|
||||||
|
int16_t diffY = y - adCenter;
|
||||||
|
if (buttonPressed) {
|
||||||
|
return CENTER;
|
||||||
|
}
|
||||||
|
if (abs(diffX) > abs(diffY)) {
|
||||||
|
if (diffX < -threshold) {
|
||||||
|
return LEFT;
|
||||||
|
} else if (diffX > threshold) {
|
||||||
|
return RIGHT;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (diffY < -threshold) {
|
||||||
|
return UP;
|
||||||
|
} else if (diffY > threshold) {
|
||||||
|
return DOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NONE;
|
||||||
|
}
|
||||||
|
|
||||||
28
mozc-furikku/arduino/flick/flick_keyboard.h
Normal file
28
mozc-furikku/arduino/flick/flick_keyboard.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define ROWS 5
|
||||||
|
#define COLS 12 // Equals to the number of the keys.
|
||||||
|
|
||||||
|
enum Direction {
|
||||||
|
CENTER, LEFT, UP, RIGHT, DOWN, NONE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SensorData {
|
||||||
|
uint16_t axes[COLS * 2];
|
||||||
|
bool button[COLS];
|
||||||
|
};
|
||||||
|
|
||||||
|
class FlickKeyboard {
|
||||||
|
private:
|
||||||
|
Direction lastState[COLS];
|
||||||
|
Direction ConvertToFlickState(int16_t x, int16_t y,
|
||||||
|
bool buttonPressed);
|
||||||
|
public:
|
||||||
|
FlickKeyboard();
|
||||||
|
void ProcessSensorData(const SensorData& data, size_t maxKeyNum,
|
||||||
|
const char** outputStrings, int* nOutputs);
|
||||||
|
};
|
||||||
|
|
||||||
BIN
mozc-furikku/circuit.png
Normal file
BIN
mozc-furikku/circuit.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 73 KiB |
Reference in New Issue
Block a user