mirror of
https://github.com/google/mozc-devices.git
synced 2025-11-08 16:53:28 +03:00
Add mozc-dial nine dial edition.
Co-authored-by: Takashi Toyoshima <toyoshim@google.com> Co-authored-by: Shun Ikejima <ikejima@google.com>
This commit is contained in:
@@ -16,6 +16,10 @@ We have included pre-built firmware under `prebuilt/`, so you can use them as is
|
||||
|
||||
Use `main.uf2` and `sub.uf2` for the 9-dial edition, and `one_dial.uf2` for the 1-dial edition.
|
||||
|
||||
We have also prepared `main_no_pull.uf2`, `sub_no_pull.uf2`, and `one_dial_no_pull.uf2` that do not use internal pull-up for the sensors. For details, please see [About Sensor Adjustment](#about-sensor-adjustment).
|
||||
|
||||
If the dial rotation is reversed, try using the firmware with `backward` in its name. It seems that the direction of rotation may differ depending on the shipping time even for the same model number product.
|
||||
|
||||
## Guide to Developing Your Own Firmware
|
||||
|
||||
Install [Visual Studio Code](https://code.visualstudio.com/) and add the [Raspberry Pi Pico extension](https://marketplace.visualstudio.com/items?itemName=raspberry-pi.raspberry-pi-pico).
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
- common/ : 各ボード共通で用いられるライブラリのソースファイル
|
||||
- main/ : 9ダイヤル版メインチップ用のソースファイルとプロジェクト
|
||||
- sub/ : 9ダイヤル版サブチップ用のソースファイルとプロジェクト
|
||||
- one_dial/ : 1ダイヤル版 Raspberry Pi Pico用のソーとファイルとプロジェクト
|
||||
- one_dial/ : 1ダイヤル版 Raspberry Pi Pico用のソースファイルとプロジェクト
|
||||
|
||||
## 事前にビルドしたファームウェア
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
|
||||
9ダイヤル板は`main.uf2`と`sub.uf2`を、1ダイヤル板は`one_dial.uf2`を使用します。
|
||||
|
||||
それぞれセンサに内部pull-upを使わない`main_no_pull.uf2`、`sub_no_pull.uf2`、`one_dial_no_pull.uf2`も用意しています。詳しくは[センサの調整について](#センサの調整について)をご覧ください。
|
||||
|
||||
ダイヤルの回転方向が逆だった場合には`backward`の名前がついたものを使用してみてください。同じ型番の製品でも出荷時期により回転方向が異なるようです。
|
||||
|
||||
## 独自のファームウェア開発の手引き
|
||||
|
||||
[Visual Studio Code](https://code.visualstudio.com/) をインストールし、[Raspberry Pi Pico拡張](https://marketplace.visualstudio.com/items?itemName=raspberry-pi.raspberry-pi-pico) を追加します。
|
||||
@@ -52,9 +56,9 @@ Activity Barの`Raspberry Pi Pico Projects`の拡張機能から`Import Project`
|
||||
|
||||
などを定義し、`CMakeFiles.txt`のボード設定で指定する事で、キャッシュミス時のQSPI経由でのEEPROMアクセスを最適化し、さらなる性能を引き出す事も可能です。
|
||||
|
||||
### センサーの調整について
|
||||
### センサの調整について
|
||||
|
||||
標準ではセンサーは内部抵抗でpull-upされています。外部抵抗によりpull-upで調整したい場合、`photo_sensor.cc`の`PhotoSensor::PhotoSensor()`内にある`gpio_pull_up(gpio);`を`gpio_disable_pulls(gpio);`に変更してください。
|
||||
標準ではセンサは内部抵抗でpull-upされています。外部抵抗によりpull-upで調整したい場合、`photo_sensor.cc`の`PhotoSensor::PhotoSensor()`内にある`gpio_pull_up(gpio);`を`gpio_disable_pulls(gpio);`に変更してください。
|
||||
|
||||
あるいは、内部抵抗を有効にしたまま外部抵抗との合成抵抗でpull-upする事も可能です。この場合、内部抵抗は公称値で50-80KΩ、外部抵抗とは並列接続になります。
|
||||
|
||||
|
||||
@@ -49,9 +49,10 @@ bool MotorController::OnAlarm(repeating_timer* t) {
|
||||
return true;
|
||||
}
|
||||
|
||||
MotorController::MotorController(Mode mode) {
|
||||
MotorController::MotorController(Mode mode, Direction direction)
|
||||
: direction_(direction) {
|
||||
if (mode == Mode::k9Motor) {
|
||||
// Each decoder is responsible for a specific phase to driver 1 of 8 motor
|
||||
// Each decoder is responsible for a specific phase to drive 1 of 8 motor
|
||||
// drivers. As we have 4 phases, it can drive 4 motors at the same time, and
|
||||
// by time division multiplexing, we make them drive 8 motors.
|
||||
decoder_[0] = std::make_unique<Decoder>(1, 2, 3, 4);
|
||||
@@ -88,7 +89,7 @@ void MotorController::Step() {
|
||||
size_t start_index = (phase_ & 1) ? kNumOfPhases : 0;
|
||||
size_t half_phase = phase_ >> 1;
|
||||
for (size_t i = start_index; i < start_index + kNumOfPhases; ++i) {
|
||||
if (!decoder_[i]) {
|
||||
if (!decoder_[i % kNumOfPhases]) {
|
||||
continue;
|
||||
}
|
||||
if (started_[i]) {
|
||||
@@ -104,5 +105,9 @@ void MotorController::Step() {
|
||||
gpio_put(19, on && half_phase == 2);
|
||||
gpio_put(20, on && half_phase == 3);
|
||||
|
||||
phase_ = (phase_ + 7) % 8;
|
||||
if (direction_ == Direction::kForward) {
|
||||
phase_ = (phase_ + 1) % 8;
|
||||
} else if (direction_ == Direction::kBackward) {
|
||||
phase_ = (phase_ + 7) % 8;
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,8 @@
|
||||
class MotorController final {
|
||||
public:
|
||||
enum class Mode { k1Motor, k9Motor };
|
||||
explicit MotorController(Mode = Mode::k9Motor);
|
||||
enum class Direction { kForward, kBackward };
|
||||
explicit MotorController(Mode = Mode::k9Motor, Direction = Direction::kForward);
|
||||
MotorController(const MotorController&) = delete;
|
||||
MotorController& operator=(const MotorController&) = delete;
|
||||
~MotorController();
|
||||
@@ -33,6 +34,7 @@ class MotorController final {
|
||||
bool started_[kNumOfMotors] = { false };
|
||||
uint8_t phase_ = 0;
|
||||
repeating_timer timer_;
|
||||
Direction direction_ = Direction::kForward;
|
||||
};
|
||||
|
||||
#endif // COMMON_MOTOR_CONTROLLER_H_
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
#include "hardware/gpio.h"
|
||||
|
||||
//#define NO_SENSOR_PULL
|
||||
|
||||
PhotoSensor::PhotoSensor(int8_t bit0,
|
||||
int8_t bit1,
|
||||
int8_t bit2,
|
||||
@@ -16,7 +18,13 @@ PhotoSensor::PhotoSensor(int8_t bit0,
|
||||
for (int8_t gpio : bits) {
|
||||
gpio_init(gpio);
|
||||
gpio_set_dir(gpio, GPIO_IN);
|
||||
gpio_pull_up(gpio); // Built-in 50-80K pull-up
|
||||
#ifdef NO_SENSOR_PULL
|
||||
gpio_disable_pulls(gpio);
|
||||
#else
|
||||
// Built-in 50-80K pull-up is expected, but the actual value appears to
|
||||
// depend on the RP2040's shipping years?
|
||||
gpio_pull_up(gpio);
|
||||
#endif // NO_SENSOR_PULL
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,8 +41,8 @@ const std::vector<uint8_t> a = {
|
||||
0x14, // q
|
||||
0x04, // a
|
||||
0x1d, // z
|
||||
0x39, // <CAPS>
|
||||
0x2c, // <SPACE>
|
||||
0x39, // <CAPS>
|
||||
};
|
||||
const std::vector<uint8_t> fn_a = {};
|
||||
const std::vector<uint8_t> modifier_a = {};
|
||||
|
||||
@@ -43,6 +43,8 @@ int main() {
|
||||
PhotoSensor(24, 25, 26, 27), // I
|
||||
};
|
||||
|
||||
const std::array<int8_t, 9> sensor_indices = { 0, 1, 2, 3, 4, 5, 6, -1, 7 };
|
||||
|
||||
std::array<DialController, 9> dials = {
|
||||
DialController(), // A
|
||||
DialController(), // B
|
||||
@@ -98,37 +100,39 @@ int main() {
|
||||
UsbHidKeyboard usb_hid_keyboard(
|
||||
/*vendor_id=*/0x6666, /*product_id=*/0x2025,
|
||||
/*version=*/0x0109, /*vendor_name=*/"Gboard DIY prototype",
|
||||
/*product_name=*/"Gboard Dial version", /*version_name=*/"9 Dial");
|
||||
/*product_name=*/"Gboard Dial version", /*version_name=*/"9 Dial rev2");
|
||||
usb_hid_keyboard.SetAutoKeyRelease(true);
|
||||
|
||||
// Wait for a while, just in case, so that the sub-controller can be ready on
|
||||
// I2C.
|
||||
sleep_ms(100);
|
||||
|
||||
std::vector<uint8_t> i2c_buffer(2);
|
||||
std::vector<uint8_t> i2c_buffer(1);
|
||||
bool fn = false;
|
||||
|
||||
while (true) {
|
||||
uint16_t motor_start_bitmap = 0;
|
||||
for (size_t i = 0; i < sensors.size(); ++i) {
|
||||
dials[i].Update(sensors[i].Read());
|
||||
for (size_t i = 0; i < sensor_indices.size(); ++i) {
|
||||
if (sensor_indices[i] < 0) {
|
||||
// Read the remote sensor H value via I2C.
|
||||
if (i2c.Read(68, 0, i2c_buffer)) {
|
||||
dials[i].Update(i2c_buffer[0]);
|
||||
}
|
||||
} else {
|
||||
// Read one of the local sensors.
|
||||
dials[i].Update(sensors[sensor_indices[i]].Read());
|
||||
}
|
||||
if (!dials[i].IsBasePosition()) {
|
||||
motor_start_bitmap |= (1 << i);
|
||||
}
|
||||
}
|
||||
// Read the remote sensor H value via I2C.
|
||||
bool rc = i2c.Read(68, 0, std::span<uint8_t>({i2c_buffer.data(), 1}));
|
||||
if (rc) {
|
||||
dials[8].Update(i2c_buffer[0]);
|
||||
if (!dials[8].IsBasePosition()) {
|
||||
motor_start_bitmap |= (1 << 8);
|
||||
}
|
||||
}
|
||||
|
||||
// Drive all motors via I2C.
|
||||
// Use non-burst mode for better stability.
|
||||
i2c_buffer[0] = motor_start_bitmap & 0xff;
|
||||
i2c_buffer[1] = motor_start_bitmap >> 8;
|
||||
rc = i2c.Write(68, 0, i2c_buffer);
|
||||
i2c.Write(68, 0, i2c_buffer);
|
||||
i2c_buffer[0] = motor_start_bitmap >> 8;
|
||||
i2c.Write(68, 1, i2c_buffer);
|
||||
|
||||
// Check all dials to see if we have pending inputs to send over USB HID.
|
||||
for (size_t i = 0; i < dials.size(); ++i) {
|
||||
|
||||
@@ -14,12 +14,16 @@
|
||||
#include "../common/usage_tables.h"
|
||||
#include "../common/usb_hid_keyboard.h"
|
||||
|
||||
#define MOTOR_DIRECTION MotorController::Direction::kForward
|
||||
//#define MOTOR_DIRECTION MotorController::Direction::kBackward
|
||||
|
||||
int main() {
|
||||
// GPIO0 and 1 are used for stdout, and stdin by default.
|
||||
stdio_init_all();
|
||||
|
||||
// GPIO17, 18, 19, and 20 are used for motor phase control.
|
||||
MotorController motor_controller(MotorController::Mode::k1Motor);
|
||||
MotorController motor_controller(MotorController::Mode::k1Motor,
|
||||
MOTOR_DIRECTION);
|
||||
|
||||
// GPIO2, 3, 4, 5, 6, and 7 are used for 6bit photo sensing.
|
||||
PhotoSensor photo_sensor(2, 3, 4, 5, 6, 7);
|
||||
|
||||
Binary file not shown.
BIN
mozc-dial/firmware/prebuilt/main_no_pull.uf2
Normal file
BIN
mozc-dial/firmware/prebuilt/main_no_pull.uf2
Normal file
Binary file not shown.
Binary file not shown.
BIN
mozc-dial/firmware/prebuilt/one_dial_backward.uf2
Normal file
BIN
mozc-dial/firmware/prebuilt/one_dial_backward.uf2
Normal file
Binary file not shown.
BIN
mozc-dial/firmware/prebuilt/one_dial_backward_no_pull.uf2
Normal file
BIN
mozc-dial/firmware/prebuilt/one_dial_backward_no_pull.uf2
Normal file
Binary file not shown.
BIN
mozc-dial/firmware/prebuilt/one_dial_no_pull.uf2
Normal file
BIN
mozc-dial/firmware/prebuilt/one_dial_no_pull.uf2
Normal file
Binary file not shown.
Binary file not shown.
BIN
mozc-dial/firmware/prebuilt/sub_backward.uf2
Normal file
BIN
mozc-dial/firmware/prebuilt/sub_backward.uf2
Normal file
Binary file not shown.
BIN
mozc-dial/firmware/prebuilt/sub_backward_no_pull.uf2
Normal file
BIN
mozc-dial/firmware/prebuilt/sub_backward_no_pull.uf2
Normal file
Binary file not shown.
BIN
mozc-dial/firmware/prebuilt/sub_no_pull.uf2
Normal file
BIN
mozc-dial/firmware/prebuilt/sub_no_pull.uf2
Normal file
Binary file not shown.
@@ -24,7 +24,6 @@ if (EXISTS ${picoVscode})
|
||||
endif()
|
||||
# ====================================================================================
|
||||
set(PICO_BOARD none CACHE STRING "Board type")
|
||||
#set(PICO_BOARD pico CACHE STRING "Board type")
|
||||
|
||||
# Pull in Raspberry Pi Pico SDK (must be before project)
|
||||
include(pico_sdk_import.cmake)
|
||||
|
||||
@@ -14,9 +14,13 @@
|
||||
#include "../common/photo_sensor.h"
|
||||
#include "i2c_device.h"
|
||||
|
||||
#define MOTOR_DIRECTION MotorController::Direction::kForward
|
||||
//#define MOTOR_DIRECTION MotorController::Direction::kBackward
|
||||
|
||||
namespace {
|
||||
|
||||
MotorController motor_controller;
|
||||
MotorController motor_controller(MotorController::Mode::k9Motor,
|
||||
MOTOR_DIRECTION);
|
||||
PhotoSensor sensor_h(26, 27);
|
||||
|
||||
uint8_t i2c_reader(uint8_t address) {
|
||||
|
||||
Reference in New Issue
Block a user