Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

修正macOS上的全键无冲自动切换,增加GUI的视频播放功能 #27

Merged
merged 2 commits into from
Sep 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions firmware/keyboard/sipeed_keyboard_68/include/smk_hid.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
0x91, 0x02, /*OUTPUT (Data,Var,Abs)*/\
0xc0, /*END_COLLECTION*/

#define NKRO_KAYBOARD_DR_SIZE (57-18)
#define NKRO_KAYBOARD_DR_SIZE 57
#define NKRO_KAYBOARD_RD(...) \
0x05, 0x01, /*USAGE_PAGE (Generic Desktop)*/\
0x09, 0x06, /*USAGE (Keyboard)*/\
Expand All @@ -80,15 +80,15 @@
0x75, 0x01, /*REPORT_SIZE (1)*/\
0x95, 0x08, /*REPORT_COUNT (8)*/\
0x81, 0x02, /*INPUT (Data,Var,Abs)*/\
/*0x95, 0x05,*/ /*REPORT_COUNT (5)*/\
/*0x75, 0x01,*/ /*REPORT_SIZE (1)*/\
/*0x05, 0x08,*/ /*USAGE_PAGE (LEDs)*/\
/*0x19, 0x01,*/ /*USAGE_MINIMUM (Num Lock)*/\
/*0x29, 0x05,*/ /*USAGE_MAXIMUM (Kana)*/\
/*0x91, 0x02,*/ /*OUTPUT (Data,Var,Abs)*/\
/*0x95, 0x01,*/ /*REPORT_COUNT (1)*/\
/*0x75, 0x03,*/ /*REPORT_SIZE (3)*/\
/*0x91, 0x03,*/ /*OUTPUT (Cnst,Var,Abs)*/\
0x95, 0x05, /*REPORT_COUNT (5)*/\
0x75, 0x01, /*REPORT_SIZE (1)*/\
0x05, 0x08, /*USAGE_PAGE (LEDs)*/\
0x19, 0x01, /*USAGE_MINIMUM (Num Lock)*/\
0x29, 0x05, /*USAGE_MAXIMUM (Kana)*/\
0x91, 0x02, /*OUTPUT (Data,Var,Abs)*/\
0x95, 0x01, /*REPORT_COUNT (1)*/\
0x75, 0x03, /*REPORT_SIZE (3)*/\
0x91, 0x03, /*OUTPUT (Cnst,Var,Abs)*/\
0x05, 0x07, /*USAGE_PAGE (Keyboard)*/\
0x15, 0x00, /*LOGICAL_MINIMUM (0)*/\
0x25, 0x01, /*LOGICAL_MAXIMUM (1)*/\
Expand Down
45 changes: 42 additions & 3 deletions firmware/keyboard/sipeed_keyboard_68/smk_hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "FreeRTOS.h"
#include "queue.h"
#include "task.h"
#include "timers.h"

#include "keyboard/smk_event.h"
#include "keyboard/smk_keycode.h"
Expand All @@ -19,10 +20,14 @@ volatile int current_nkro_interface =NKRO_REPORT_ID;

static atomic_t kb_isupdate=0;
static int kb_idle=0;
static int kb_idle_dur=0;
static atomic_t kb_report_update=0;
static int use_nkro=0;
int kb_configured=0;
int force_basic_keyboard=0;

TimerHandle_t hid_timer;

static const uint8_t hid_keyboard_report_desc[HID_KEYBOARD_REPORT_DESC_SIZE] = {
STANDERD_KAYBOARD_RD()
};
Expand Down Expand Up @@ -134,8 +139,11 @@ void usbd_hid_kb_int_callback(uint8_t ep)
times[0]++;
if(use_nkro&&!force_basic_keyboard)
return;
if((!kb_idle)||atomic_set(&kb_isupdate,0))
if((!kb_idle&&kb_report_update)||atomic_set(&kb_isupdate,0)){
kb_report_update=0;
usbd_ep_write(HID_KB_INT_EP,hid_usb.buf[hid_usb.flag] , 8, NULL);
//USBD_LOG_DBG("times:%u,%u,%u,%u\r\n",times[0],times[1],times[2],times[3]);
}
}
void usbd_hid_nkro_int_callback(uint8_t ep)
{
Expand Down Expand Up @@ -219,7 +227,13 @@ void nkro_set_idle_callback(uint8_t reportid, uint8_t duration){

void kb_set_idle_callback(uint8_t reportid, uint8_t duration){
USBD_LOG_DBG("kb_set_idle_callback:%d,%d\r\n",reportid,duration);
USBD_LOG_DBG("kb_set_idle:%dms\r\n",duration*4);
kb_idle=duration==0;
kb_idle_dur=duration*4;
if(duration==0)
xTimerChangePeriod(hid_timer,portMAX_DELAY,portMAX_DELAY);
else
xTimerChangePeriod(hid_timer,pdMS_TO_TICKS(kb_idle_dur),portMAX_DELAY);
}

void smk_reset_callback(){
Expand All @@ -233,11 +247,20 @@ void smk_configured_callback(){
kb_configured=1;
}

static void smk_hidreport_update(TimerHandle_t xTimer)
{
kb_report_update=1;
}
void kb_set_protocol_callback(uint8_t protocal)
{
USBD_LOG_DBG("kb_set_protocol_callback:switch to nkro mode\r\n");
use_nkro=protocal;
}
void smk_hid_usb_init()
{
usbd_hid_add_interface(&hid_class, &hid_intf_kb);
usbd_interface_add_endpoint(&hid_intf_kb, &hid_kb_in_ep);
usbd_hid_callback_register(hid_intf_kb.intf_num,keyboard_led_cb,NULL,kb_set_idle_callback,NULL,NULL,NULL,smk_reset_callback,smk_configured_callback);
usbd_hid_callback_register(hid_intf_kb.intf_num,keyboard_led_cb,NULL,kb_set_idle_callback,NULL,NULL,kb_set_protocol_callback,smk_reset_callback,smk_configured_callback);
usbd_hid_report_descriptor_register(hid_intf_kb.intf_num, hid_keyboard_report_desc, HID_KEYBOARD_REPORT_DESC_SIZE);

usbd_hid_add_interface(&hid_class, &hid_intf_data);
Expand All @@ -247,10 +270,26 @@ void smk_hid_usb_init()

usbd_hid_add_interface(&hid_class, &hid_intf_nkro);
usbd_interface_add_endpoint(&hid_intf_nkro, &hid_nkro_in_ep);
usbd_hid_callback_register(hid_intf_nkro.intf_num,keyboard_led_cb,NULL,nkro_set_idle_callback,NULL,NULL,NULL,smk_reset_callback,NULL);
usbd_hid_callback_register(hid_intf_nkro.intf_num,keyboard_led_cb,NULL,nkro_set_idle_callback,NULL,NULL,kb_set_protocol_callback,smk_reset_callback,NULL);
usbd_hid_report_descriptor_register(hid_intf_nkro.intf_num, hid_nkro_report_desc, HID_NKRO_REPORT_DESC_SIZE);

hid_data_protocol_init();

// Set daemon task to handle keyscan periodically
hid_timer = xTimerCreate(
"hid report timer", // pcTimerName
pdMS_TO_TICKS(1), // xTimerPeriodInTicks
pdTRUE, // uxAutoReload
xTaskGetCurrentTaskHandle(), // pvTimerID
smk_hidreport_update // pxCallbackFunction
);

// Start timer
xTimerStart(
hid_timer, // xTimer
portMAX_DELAY // xTicksToWait
);

}

void smk_usb_hid_daemon_task(void *pvParameters)
Expand Down
35 changes: 25 additions & 10 deletions software/hidtest/kbapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def __init__(self):
self.hidruning = False
self.isdeviceoen = False
self.lock=threading.Lock()
self.thid = threading.Thread(target=self.hidthread)

def newpackage(self, reportid, packageid, addr, len):
buffer = bytearray(8)
Expand Down Expand Up @@ -75,23 +76,27 @@ def writedata(self, addr, buffer: bytearray):
time.sleep(0.001)
wait -= 1
if wait == 0:
self.lock.release()
if self.lock.locked():
self.lock.release()
return -1
else:
datain = self.inputdatas.get()
reportid, retlen, packageid, retaddr = struct.unpack(self.Report_HEADER_Format, bytearray(datain[0:8]))
if packageid != self.getretid():
# print('pkgid error')
self.lock.release()
if self.lock.locked():
self.lock.release()
return -2
# else:
# print('succeed')
if (retlen != datatosent):
self.lock.release()
if self.lock.locked():
self.lock.release()
return -3
datasize -= datatosent
datapoint += datatosent
self.lock.release()
if self.lock.locked():
self.lock.release()
return datasize

def readdata(self, addr, len: int):
Expand All @@ -112,24 +117,28 @@ def readdata(self, addr, len: int):
time.sleep(0.001)
wait -= 1
if wait == 0:
self.lock.release()
if self.lock.locked():
self.lock.release()
return -1, retdata
else:
datain = self.inputdatas.get()
reportid, retlen, packageid, retaddr = struct.unpack(self.Report_HEADER_Format, bytearray(datain[0:8]))
if packageid != self.totalpackageid:
# print('pkgid error')
self.lock.release()
if self.lock.locked():
self.lock.release()
return -2, retdata
# else:
# print('succeed')
if (retlen != datatoget):
self.lock.release()
if self.lock.locked():
self.lock.release()
return -3, retdata
retdata += bytearray(datain[8:8 + retlen])
datasize -= datatoget
datapoint += datatoget
self.lock.release()
if self.lock.locked():
self.lock.release()
return datapoint, retdata

def hidthread(self):
Expand Down Expand Up @@ -171,12 +180,18 @@ def hidthread(self):
break

def init_hid_interface(self):
if self.thid.is_alive():
self.stop_and_wait()
self.thid = threading.Thread(target=self.hidthread)
self.hidruning = True
self.thid = threading.Thread(target=self.hidthread)
self.thid.start()
def stop_and_wait(self):
self.hidruning =False
self.thid.join()
self.isdeviceoen=False
if self.thid.is_alive():
self.thid.join()
self.thid = threading.Thread(target=self.hidthread)

def wait_for_kb(self,timeout=0):
timesecond=timeout/1000;
while not self.isdeviceoen:
Expand Down
3 changes: 2 additions & 1 deletion software/hidtest/kbled.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def gammafunction(self, r, g, b):

def play_frame_full(self, frame):
frame = cv2.resize(frame, (128, int(self.keyh / self.keyw * 128)), interpolation=cv2.INTER_NEAREST)
self.play_frame(frame)
return self.play_frame(frame)

def play_frame(self, frame):
xsize = frame.shape[1]
Expand Down Expand Up @@ -165,6 +165,7 @@ def play_frame(self, frame):
colordata += struct.pack('BBBB', int(colorb), int(colorg), int(colorr), 0)
keyid += 1
self.kb.writedata(0x9000, colordata)
return colordata
def switchmode(self,mode:int):
self.kb.writedata(0x8000, struct.pack('I', mode))
def getled(self):
Expand Down
69 changes: 66 additions & 3 deletions software/hidtest/maingui.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from PyQt5.QtGui import QPixmap

import sys
import cv2
import numpy as np
import threading

from kbled import keyboard_led
Expand All @@ -19,25 +21,40 @@ def __init__(self):
self.ui.tabWidget.setCurrentIndex(0)
self.kb = keyboard_ctl()
self.leds=keyboard_led(self.kb)
self.video_opened=False
self.video_running=False
self.leddata=bytearray(272)

self.ui.mode_set_btn.clicked.connect(self.set_mode_func)
self.ui.connect_btn.clicked.connect(self.connectfunc)
self.ui.stop_btn.clicked.connect(self.stopfunc)
self.ui.video_play_btn.clicked.connect(self.videofunc)

self.videothreadid = threading.Thread(target=self.videothread)

self.videolock=threading.Lock()

self.previewtimer=QTimer()
self.previewtimer.timeout.connect(self.updateperview)
self.videotimer=QTimer()
self.videotimer.timeout.connect(self.videotimerfunc)

def connectfunc(self):
self.kb.init_hid_interface()
if(self.kb.wait_for_kb(1000)==False):
self.ui.logbox.appendPlainText("Connect Failed\n")
self.kb.stop_and_wait()
return
self.startTimer()
def stopfunc(self):
self.stopTimer()
self.stopvideo()
self.kb.stop_and_wait()

def closeEvent(self, event):
self.kb.stop_and_wait()
self.stopvideo()

def set_mode_func(self):
if self.kb.isdeviceoen==False:
return
Expand All @@ -53,11 +70,13 @@ def stopTimer(self):
self.previewtimer.stop()
def updateperview(self):
if(self.kb.wait_for_kb(1000)==False):return
lens,data=self.leds.getled()
if(lens<0):return
if(self.video_running==False):
lens,self.leddata=self.leds.getled()
if(lens<0):
return
width=(self.ui.preview_box.width()-10)
height=(self.ui.preview_box.height()-10)
img=self.leds.getpreview_rgb(data,(width,height))
img=self.leds.getpreview_rgb(self.leddata,(width,height))
previewimg = QImage(img,
width, height, width*3,
QImage.Format_RGB888)
Expand All @@ -68,6 +87,50 @@ def updateperview(self):
self.prescene.addItem(self.preitem)
self.ui.preview_box.setScene(self.prescene)

def videofunc(self):
if self.kb.wait_for_kb(100)==False:
return
if self.videothreadid.is_alive():
self.video_running=False
self.videothreadid.join()
self.videolink=self.ui.video_link_box.text()
self.cvvideo=cv2.VideoCapture()
self.cvvideo.open(self.videolink)
if(self.cvvideo.isOpened()):
self.leds.switchmode(0xff)
fps=self.cvvideo.get(cv2.CAP_PROP_FPS)
self.videotimer.start(int(np.floor(1000/fps)))
self.video_opened=True
self.video_running=True
self.videothreadid = threading.Thread(target=self.videothread)
self.videothreadid.start()
def videotimerfunc(self):
if(self.videolock.locked()):
self.videolock.release()
def videothread(self):
kbresetflag=False
while self.video_running and self.video_opened:
self.videolock.acquire()
if kbresetflag:
self.leds.switchmode(0xff)
ret, frame1 = self.cvvideo.read()
if(ret):
if self.kb.wait_for_kb(100) == False:
kbresetflag=True
continue
self.leddata=self.leds.play_frame_full(frame1)
else:
self.cvvideo.set(cv2.CAP_PROP_POS_FRAMES,0)
# kb.stop_and_wait()
# sys.exit(0)
def stopvideo(self):
if self.videothreadid.is_alive():
self.video_running=False
self.videolock.release()
self.videothreadid.join()
self.cvvideo.release()
self.video_opened=False
self.videotimer.stop()

if __name__ == '__main__':
app = QApplication(sys.argv)
Expand Down