2025年3月1日土曜日

picoのHIDデバイス化備忘録

いろいろ至らない部分があるが、ほかにやりたいことがあるので、こちらはいったん終了。
作業メモだけ残す。

配線:
ボタン1~10をGNDと、GP0,GP1,GP2,GP3,GP4,GP28,GP27,GP26,GP5,GP6に接続
ロータリーエンコーダ1を、GP17,GND,GP16に接続。
ロータリーエンコーダ2を、GP19,GND,GP18に接続。
SSD1302の、GND,VCC,SCL,SDAを、GND,3.3V,GP15,GP14に接続。

ライブラリファイル配置。
PIのボタンを押しながらPCに接続する。
PIのドライブにflash_nuke.uf2をコピーしてストレージを初期化。
PIのドライブにadafruit-circuitpython-raspberry_pi_pico2-ja-9.2.3.uf2をコピーしてcircuitpy環境にする。
adafruit-circuitpython-bundle-py-20250201\examples\framebuf\font5x8.bin をcircuitpyドライブ直下にコピー。
adafruit-circuitpython-bundle-py-20250201\libの
adafruit_framebuf.mpy,adafruit_ssd1306.mpy,adafruit_hid/をcircuitpyのlibフォルダにコピー。
pico_MicroPython_misakifont-main.zip\pico_MicroPython_misakifont-main\の
misakifontフォルダをcircuitpyのlibフォルダにコピー。
mode.iniをcircuitpyドライブ直下に作成。内容は0の1バイトのみ。

circuitpyドライブ直下のboot.pyを以下の内容に差し替える。

import os
import storage
import board
import digitalio

switch = digitalio.DigitalInOut(board.GP6)

switch.direction = digitalio.Direction.INPUT
switch.pull = digitalio.Pull.UP

if switch.value:
    #NormalMode
    storage.disable_usb_drive()
    usb_cdc.disable()
else :
  #Maintenance
    pass            


circuitpyドライブ直下のcode.pyを以下の内容に差し替える。


import digitalio
import busio
import adafruit_ssd1306
import time
import usb_hid
import json
from board import *
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard import Keycode
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from adafruit_hid.consumer_control import ConsumerControl
from adafruit_hid.consumer_control_code import ConsumerControlCode
from adafruit_hid.mouse import Mouse
from misakifont import MisakiFont
i2c = busio.I2C(GP15, GP14)
display = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3C)
mode=0
try:
    with open('mode.ini', 'r') as file:
        mode=int(file.read())
    with open('mode.ini', 'w') as file:
        file.write("{}".format(mode))
except Exception as e:
    display.text("MAINTENANCE MODE", 16, 30, True, font_name="font5x8.bin", size=1)
    display.show()
#    raise e


cc = ConsumerControl(usb_hid.devices)
keyboard = Keyboard(usb_hid.devices)
layout=KeyboardLayoutUS(keyboard)
mouse = Mouse(usb_hid.devices)

s1 = digitalio.DigitalInOut(GP17)
s1.direction = digitalio.Direction.INPUT
s1.pull = digitalio.Pull.UP
s2 = digitalio.DigitalInOut(GP16)
s2.direction = digitalio.Direction.INPUT
s2.pull = digitalio.Pull.UP
n_s1=o_s1=s1.value
n_s2=o_s2=s2.value

s3 = digitalio.DigitalInOut(GP19)
s3.direction = digitalio.Direction.INPUT
s3.pull = digitalio.Pull.UP
s4 = digitalio.DigitalInOut(GP18)
s4.direction = digitalio.Direction.INPUT
s4.pull = digitalio.Pull.UP
n_s3=o_s3=s3.value
n_s4=o_s4=s4.value
mf = MisakiFont()
sw=[]
n_sws=[True,True,True,True,True,True,True,True,True,True]
o_sws=[True,True,True,True,True,True,True,True,True,True]

isDisplay=False

def show_bitmap(x,y,fd):
    for row in range(0,7):
        for col in range(0,7):
            display.pixel(x+col,y+row,1 if (0x80>>col) & fd[row] else 0)


def DisplayMenu(menuNo):
    global isDisplay,strs,i2c,display
    i2c.deinit()
    i2c = busio.I2C(GP15, GP14)
    display = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3C)

    display.fill(0) # 表示内容消去
    y=1
    for str in strs[menuNo]:
        i=0
        for c in str:
            d = mf.font(ord(c))
            show_bitmap(i,y,d)
            i+=8
        y+=10
    display.show()
    isDisplay=True


strs=(
    ("――モード1 スタンダード――",
     "1.コピー 2.カット",         #Ctrl+C,Ctrl+X
     "3.はりつけ4.すべてせんたく",   #Ctrl+V,Ctrl+A
     "5.やり直し6.再実行",       #Ctrl+Z,Ctrl+Y
     "7.デスク 8.ウィンドウ閉じる", #Win+D,Ctrl+W
     "上ボリューム下Ctrl+ホイール",),
    ("――モード2 YouTube――",
     "1.停止再生 2.ミュート",      #k,m
     "3.10秒進む4.10秒もどる",  #l,j
     "5.前フレーム 6.次フレーム",    #.,,
     "7.全画面8.小ウィンドウ",      #f,i
     "上.ボリューム 下.明るさ",),
    ("――モード3 Winキー ――",
     "1.ゲームバー 2.文字起こし", #G,H
     "3.設定画面 4.Winロック",   #I,L
     "5.画面設定6.クリップりれき",       #P,V
     "7.拡大表示 8.縮小表示",   #+,-
     "上マウス左右 下マウス上下",),
    ("――モード4 メッセージ送信 ――",
     "1.Hello 2.Bye", 
     "3.OK    4.NG", 
     "5.login 6.logout",
     "7.prev  8.next",
     "上マウス左右 下マウス上下",),
    )
#command 1:kbd.press&release,2:cc.press&release,3:layout.write,4:Mouse.X,5:Mouse.Y,6:MouseWheel,7:Ctrl+MouseWheel,8:MenuChange,9:MenuDisplayOn/OFF
btn_cmds=((
    (1,(Keycode.LEFT_CONTROL,Keycode.C,)),(1,(Keycode.LEFT_CONTROL,Keycode.X,)),
    (1,(Keycode.LEFT_CONTROL,Keycode.V,)),(1,(Keycode.LEFT_CONTROL,Keycode.A,)),
    (1,(Keycode.LEFT_CONTROL,Keycode.Z,)),(1,(Keycode.LEFT_CONTROL,Keycode.Y,)),
    (1,(Keycode.WINDOWS,Keycode.D,)),(1,(Keycode.LEFT_CONTROL,Keycode.W,)),
    (8,),(9,)),
   (
    (1,(Keycode.K,)),(1,(Keycode.M,)),(1,(Keycode.L,)),(1,(Keycode.J,)),
    (1,(Keycode.PERIOD,)),(1,(Keycode.COMMA,)),(1,(Keycode.F,)),(1,(Keycode.I,)),
    (8,),(9,)),
   (
    (1,(Keycode.WINDOWS,Keycode.G,)),(1,(Keycode.WINDOWS,Keycode.H,)),(1,(Keycode.WINDOWS,Keycode.I,)),(1,(Keycode.WINDOWS,Keycode.L,)),
    (1,(Keycode.WINDOWS,Keycode.P,)),(1,(Keycode.WINDOWS,Keycode.V,)),(1,(Keycode.WINDOWS,Keycode.KEYPAD_PLUS,)),(1,(Keycode.WINDOWS,Keycode.KEYPAD_MINUS,)),
    (8,),(9,)),
   (
    (3,"Hello"),(3,"Bye"),(3,"OK"),(3,"NG"),(3,"login"),(3,"logout"),(3,"prev"),(3,"next"),(8,),(9,))
   )
#1:NormalWheel,2:Ctrl+Wheel,3:Volume,4:Brightness,5:MouseX,6:MouseY
rotally_cmds=((3,2),(3,4),(5,6),(5,6))


def buttonAction(button):
    global mode
    global isDisplay
    global btn_cmds
    global display
    global keyboard,cc,layout
    if btn_cmds[mode][button][0] == 1:
        keyboard.press(*(btn_cmds[mode][button][1]))
        keyboard.release(*(btn_cmds[mode][button][1]))
    elif btn_cmds[mode][button][0] == 2:
        cc.press(*(btn_cmds[mode][button][1]))
        cc.release(*(btn_cmds[mode][button][1]))
    elif btn_cmds[mode][button][0] == 3:
        layout.write(btn_cmds[mode][button][1])

    elif btn_cmds[mode][button][0] == 8:
        mode= (mode +1 )%4
        DisplayMenu(mode)
        with open('mode.ini', 'w') as file:
            file.write("{}".format(mode))
    elif btn_cmds[mode][button][0] == 9:
        if isDisplay :
            display.fill(0)
            display.show()
            isDisplay=False
        else :
            DisplayMenu(mode)

#1:NormalWheel,2:Ctrl+Wheel,3:Volume,4:Brightness,5:MouseX,6:MouseY
def rotallyAction(kind,direction):
    global mode
    global rotally_cmds
    global keyboard,cc,mouse
    if rotally_cmds[mode][kind] == 1:
        mouse.move(0,0,direction)
    elif rotally_cmds[mode][kind] == 2:
        keyboard.press(Keycode.LEFT_CONTROL)
        mouse.move(0,0,direction)
        keyboard.release(Keycode.LEFT_CONTROL)
    elif rotally_cmds[mode][kind] == 3:
        if direction > 0 :
            cc.send(ConsumerControlCode.VOLUME_INCREMENT)
        else :
            cc.send(ConsumerControlCode.VOLUME_DECREMENT)
    elif rotally_cmds[mode][kind] == 4:
        if direction > 0 :
            cc.send(ConsumerControlCode.BRIGHTNESS_INCREMENT)
        else :
            cc.send(ConsumerControlCode.BRIGHTNESS_DECREMENT)
    elif rotally_cmds[mode][kind] == 5:
        mouse.move(direction,0,0)
    elif rotally_cmds[mode][kind] == 6:
        mouse.move(0,direction,0)

for _gpio in GP0,GP1,GP2,GP3,GP4,GP28,GP27,GP26,GP5,GP6:
    s = digitalio.DigitalInOut(_gpio)
    s.direction = digitalio.Direction.INPUT
    s.pull = digitalio.Pull.UP
    sw.append(s)
    try:
        while True:
            nn_s1 , nn_s2= s1.value , s2.value
            if (nn_s1 != n_s1 or nn_s2 != n_s2) :
                n_s1,n_s2 =nn_s1,nn_s2
            elif(n_s1 != o_s1 or n_s2 != o_s2) :
                if n_s1 ^ o_s2 == 0 :
                    rotallyAction(0,1)
                else:
                    rotallyAction(0,-1)
                o_s1,o_s2=n_s1,n_s2

            nn_s3 , nn_s4= s3.value , s4.value
            if (nn_s3 != n_s3 or nn_s4 != n_s4) :
                n_s3,n_s4 =nn_s3,nn_s4
            elif(n_s3 != o_s3 or n_s4 != o_s4) :
                if n_s3 ^ o_s4 == 0 :
                    rotallyAction(1,1)
                else:
                    rotallyAction(1,-1)
                o_s3,o_s4=n_s3,n_s4
            for i in range(10):
                n_sws[i] = sw[i].value
                if ((o_sws[i]==True)  and (n_sws[i]==False)):
                    buttonAction(i)
                o_sws[i]=n_sws[i]
                time.sleep(0.0002)
    except KeyboardInterrupt:
    #        raise
            pass
    except Exception as e:
            pass


0 件のコメント: