mirror of
https://github.com/google/mozc-devices.git
synced 2025-11-08 16:53:28 +03:00
Add mozc-mageru/ for Gboard Spoon Bending Version
This commit is contained in:
185
mozc-mageru/wired/firmware/firmware.ino
Normal file
185
mozc-mageru/wired/firmware/firmware.ino
Normal file
@@ -0,0 +1,185 @@
|
||||
//
|
||||
// Copyright 2019 Google LLC
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// https://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.
|
||||
|
||||
#include <Keyboard.h>
|
||||
#include <avr/eeprom.h>
|
||||
|
||||
#ifdef JAPANESE_
|
||||
|
||||
// Japanese (hiragana) mode. Must be used with romaji input mode.
|
||||
#define ROWS 5
|
||||
#define COLS 10
|
||||
#define N_KEYS (ROWS * COLS)
|
||||
|
||||
// clang-format off
|
||||
const char* characters[N_KEYS] = {
|
||||
"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", "ya", "yu", "yu", "yo",
|
||||
"ra", "ri", "ru", "re", "ro",
|
||||
"wa", "wo", "nn", ",", "."
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
#else
|
||||
|
||||
// English alphabet mode.
|
||||
#define N_KEYS 27
|
||||
const char* characters[N_KEYS] = {"a", "b", "c", "d", "e", "f", "g", "h", "i",
|
||||
"j", "k", "l", "m", "n", "o", "p", "q", "r",
|
||||
"s", "t", "u", "v", "w", "x", "y", "z", " "};
|
||||
|
||||
#endif
|
||||
|
||||
const int kAnalogInPin = A5;
|
||||
const int kLedPin = 13;
|
||||
const uint8_t kMagicNumber = 0xa5;
|
||||
|
||||
// Decay ratio of the low-pass filter for smoothing the sensor input.
|
||||
// Between 0.0 and 1.0.
|
||||
const float kFilterDecay = 0.9;
|
||||
|
||||
struct Configuration {
|
||||
int min;
|
||||
int max;
|
||||
int home;
|
||||
};
|
||||
|
||||
Configuration config;
|
||||
float filtered = 0;
|
||||
float max_bend = 0;
|
||||
int prev_key = 0;
|
||||
bool active = false;
|
||||
bool enable_key_output = true;
|
||||
|
||||
void LoadDefaultConfig() {
|
||||
config.min = 612;
|
||||
config.max = 757;
|
||||
config.home = 580;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
LoadConfig();
|
||||
pinMode(kLedPin, OUTPUT);
|
||||
digitalWrite(kLedPin, LOW);
|
||||
}
|
||||
|
||||
void SetupKeyboard() {
|
||||
enable_key_output = true;
|
||||
Keyboard.begin();
|
||||
}
|
||||
|
||||
void OutputKey(const char* str) {
|
||||
if (!enable_key_output) {
|
||||
Serial.print(str);
|
||||
return;
|
||||
}
|
||||
Keyboard.print(str);
|
||||
}
|
||||
|
||||
uint8_t Checksum(uint8_t initial_value, void* data, size_t size) {
|
||||
uint8_t result = initial_value;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
result += ((uint8_t*)data)[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void SaveConfig() {
|
||||
eeprom_write_block(&config, (void*)0, sizeof(config));
|
||||
int8_t checksum = Checksum(kMagicNumber, &config, sizeof(config));
|
||||
eeprom_write_block(&checksum, sizeof(config), 1);
|
||||
}
|
||||
|
||||
void LoadConfig() {
|
||||
eeprom_read_block(&config, (void*)0, sizeof(config));
|
||||
uint8_t checksum_in_eeprom;
|
||||
eeprom_read_block(&checksum_in_eeprom, sizeof(config), 1);
|
||||
if (Checksum(kMagicNumber, &config, sizeof(config)) != checksum_in_eeprom) {
|
||||
Serial.print("No data in EEPROM. Loading default config.");
|
||||
LoadDefaultConfig();
|
||||
}
|
||||
Serial.print("home=");
|
||||
Serial.print(config.home);
|
||||
Serial.print(" min=");
|
||||
Serial.print(config.min);
|
||||
Serial.print(" max=");
|
||||
Serial.println(config.max);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
int sensor_value = analogRead(kAnalogInPin);
|
||||
float normalized_bend =
|
||||
(sensor_value - config.min) / (float)(config.max - config.min);
|
||||
filtered = (filtered * kFilterDecay + normalized_bend * (1 - kFilterDecay));
|
||||
if (Serial.available()) {
|
||||
int key = Serial.read();
|
||||
switch (key) {
|
||||
// Sensor calibration commands.
|
||||
case '0':
|
||||
config.home = sensor_value;
|
||||
break;
|
||||
case '1':
|
||||
config.min = sensor_value;
|
||||
break;
|
||||
case '2':
|
||||
config.max = sensor_value;
|
||||
break;
|
||||
case 'w':
|
||||
SaveConfig();
|
||||
break;
|
||||
case 'r':
|
||||
LoadConfig();
|
||||
break;
|
||||
|
||||
// Other debug commands.
|
||||
case '!':
|
||||
SetupKeyboard();
|
||||
break;
|
||||
case ' ':
|
||||
// Show sensor status for debugging.
|
||||
Serial.print(sensor_value);
|
||||
Serial.print("\t");
|
||||
Serial.print(normalized_bend);
|
||||
Serial.print("\t");
|
||||
Serial.print(filtered);
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
if (sensor_value < config.home && active) {
|
||||
active = false;
|
||||
filtered = 0;
|
||||
max_bend = 0;
|
||||
} else if (filtered > 0) {
|
||||
max_bend = max(max_bend, filtered);
|
||||
int new_key = min(N_KEYS - 1, (int)(max_bend * N_KEYS));
|
||||
if (new_key != prev_key) {
|
||||
if (active) {
|
||||
OutputKey("\b");
|
||||
}
|
||||
OutputKey(characters[new_key]);
|
||||
prev_key = new_key;
|
||||
}
|
||||
active = true;
|
||||
}
|
||||
digitalWrite(kLedPin, active);
|
||||
delay(2);
|
||||
}
|
||||
Reference in New Issue
Block a user