static void applyQuickSwap(void) { static uint8_t prevModifier = 0; if(getDownBufferAt(0) > 0){ enabledQuickSwapCount = 0; return; } uint8_t gModi = getModifierDownBuffer(); if(gModi != prevModifier) { if(gModi == (MODI_RSHIFT|MODI_LALT|MODI_LGUI) || gModi == (MODI_RSHIFT|MODI_RALT|MODI_RGUI) || gModi == (MODI_RSHIFT|MODI_LALT|MODI_RGUI) || gModi == (MODI_RSHIFT|MODI_LALT|MODI_LGUI)){ // ALT + GUI + R SHIFT _quickSwapCount = 0; enabledQuickSwapCount = COUNT_TYPE_QUICKSWAP_ALT_GUI; }else{ enabledQuickSwapCount = 0; } prevModifier = gModi; } //} //static void countQuickSwapEnabled(void){ if(enabledQuickSwapCount && ++_quickSwapCount > quickSwapCountMax){ if(enabledQuickSwapCount == COUNT_TYPE_QUICKSWAP_ALT_GUI){ blinkOnce(50); if((quickSwapMode & QUICKSWAP_ALT_GUI) == QUICKSWAP_ALT_GUI){ quickSwapMode &= ~QUICKSWAP_ALT_GUI; }else{ quickSwapMode |= QUICKSWAP_ALT_GUI; _delay_ms(50); blinkOnce(100); } } eeprom_update_byte((uint8_t *)EEPROM_QUICK_SWAP, quickSwapMode); enabledQuickSwapCount = 0; } }
/*static uint8_t pushKeyCodeDummy(uint8_t keyidx, bool isDown){ return 0; }*/ static uint8_t pushKeyCode(uint8_t keyidx, bool isDown) { if(keyidx == KEY_NONE) return 0; // keyidx = getDualActionKeyWhenCompound(keyidx); keyidx = getDualActionDownKeyIndexWhenIsCancel(keyidx); if(keyidx >= KEY_MAX) return 0; DBG1(0x20, (uchar *)&keyidx, 2); // if prev and current state are different, uint8_t keyVal = pgm_read_byte(&keycode_set2[keyidx]); if(isDown) { // make code lastMAKE_keyidx = keyidx; loopCnt=0; m_state = STA_NORMAL; if(KFLA[keyidx]&KFLA_SPECIAL) { switch(keyidx) { case KEY_PRNSCR: push(START_MAKE); push(0xE0); push(0x12); push(0xE0); push(0x7C); push(END_MAKE); push(SPLIT); // SPLIT is for make sure all key codes are transmitted before disturbed by RX break; case KEY_PAUSE: push(NO_REPEAT); push(0xE1); push(0x14); push(0x77); push(0xE1); push(0xF0); push(0x14); push(0xF0); push(0x77); push(SPLIT); break; } }else if(KFLA[keyidx]&KFLA_MAKEONLY) { push(keyVal); push(SPLIT); }else{ push(START_MAKE); if(KFLA[keyidx]&KFLA_EXTEND) push(0xE0); push(keyVal); push(END_MAKE); push(SPLIT); } // 2 연속으로 waiting rx 키가 입력 되면 오류로 키보드가 멈춘다. 이를 방지 하기 위해서 isAlreadyPushedWaitingRx를 설정; if((KFLA[keyidx] & KFLA_WAIT_UNTIL_RX) && isAlreadyPushedWaitingRx == false){ isAlreadyPushedWaitingRx = true; if(keyidx == KEY_SCRLCK){ // ctrl + scroll lock 키는 LED 반응을 하지 않으니 설정안함 // ctrl + alt + s/l 등 다른 조합키와 섞이면 반응함 uint8_t gModi = getModifierDownBuffer(); if(!(gModi == 0x01) || !(gModi == 0x10) || !(gModi == 0x11)){ push(WAIT_RX); } }else{ push(WAIT_RX); } } } else // break code - key realeased { if(lastMAKE_keyidx == keyidx) // repeat is resetted only if last make key is released lastMAKE_SIZE=0; if(KFLA[keyidx]&KFLA_SPECIAL) { switch(keyidx) { case KEY_PRNSCR: push(0xE0); push(0xF0); push(0x7C); push(0xE0); push(0xF0); push(0x12); push(SPLIT); break; } }else if(KFLA[keyidx]&KFLA_MAKEONLY) { }else{ if(KFLA[keyidx]&KFLA_EXTEND) push(0xE0); push(0xF0); push(keyVal); push(SPLIT); // DBG1(0x21, (uchar *)&keyidx, 1); } } return 1; }
void enterFrameForQuickSwap(void){ applyQuickSwap(getModifierDownBuffer()); countQuickSwapEnabled(); }
// 키를 누르거나 땔때 FN 및 LED등 을 컨트롤한다. bool applyFN(uint8_t xKeyidx, uint8_t xCol, uint8_t xRow, bool xIsDown) { // DEBUG_PRINT(("applyFN : %d xIsDown : %d\n", xKeyidx, xIsDown)); applyKeyDownForFullLED(xKeyidx, xCol, xRow, xIsDown); if(isFnKey(xKeyidx)) return false; setDualAction(xKeyidx, xIsDown); // 듀얼액션 키의 기본 키를 가져온다. xKeyidx = getDualActionDefaultKey(xKeyidx); if(isFnKey(xKeyidx)) return false; if(xIsDown) { if((xKeyidx == KEY_BEYOND_FN || xKeyidx == KEY_BEYOND_FN3) || (_isExtraFNDown && xKeyidx == BEYOND_FN_CANCEL_KEY)){ // beyond_fn을 활성화; if( xKeyidx == BEYOND_FN_CANCEL_KEY ) { // 취소만 가능한 키 _beyondFnIndex = false; }else{ if(_beyondFnIndex == 0){ if(xKeyidx == KEY_BEYOND_FN){ _beyondFnIndex = LAYER_FN2; }else{ _beyondFnIndex = LAYER_FN3; } }else{ if(xKeyidx == KEY_BEYOND_FN){ if(_beyondFnIndex == LAYER_FN2){ _beyondFnIndex = LAYER_NORMAL; }else{ _beyondFnIndex = LAYER_FN2; } }else if(xKeyidx == KEY_BEYOND_FN3){ if(_beyondFnIndex == LAYER_FN3){ _beyondFnIndex = LAYER_NORMAL; }else{ _beyondFnIndex = LAYER_FN3; } } } } #ifndef DISABLE_FN2_TOGGLE_LED_BLINK if(isBeyondFnLedEnabled() == false){ if(_beyondFnIndex == 0){ blinkOnce(100); }else{ blinkOnce(100); _delay_ms(80); blinkOnce(70); } } #endif if(isBeyondFnLedEnabled()){ setLed(LED_STATE_NUM, isBeyondFN()); } return 0; }else if(_isQuickMacroDown && isEepromMacroKey(xKeyidx)){ _quickMacroIndex = xKeyidx - KEY_MAC1; _isReadyQuickMacro = true; return 0; }else if(xKeyidx == EXTRA_FN){ _isExtraFNDown = true; }else if((_isExtraFNDown && xKeyidx == LED_KEY)){ uint8_t gModi = getModifierDownBuffer(); if(gModi == 0x02 || gModi == 0x20){ changeFullLedState(FULL_LED_MODE2); }else{ changeFullLedState(FULL_LED_MODE1); } return 0; }else if(xKeyidx == KEY_LED){ changeFullLedState(FULL_LED_MODE1); return 0; }else if(xKeyidx == KEY_LED2){ changeFullLedState(FULL_LED_MODE2); return 0; }else if(xKeyidx == KEY_LED_UP){ uint8_t gModi = getModifierDownBuffer(); if(gModi == 0x02 || gModi == 0x20){ increaseLedBrightness(FULL_LED_MODE2); }else{ increaseLedBrightness(FULL_LED_MODE1); } return 0; }else if(xKeyidx == KEY_LED_DOWN){ uint8_t gModi = getModifierDownBuffer(); if(gModi == 0x02 || gModi == 0x20){ reduceLedBrightness(FULL_LED_MODE2); }else{ reduceLedBrightness(FULL_LED_MODE1); } return 0; }else if(xKeyidx == KEY_LED_ON_OFF){ _ledOff ^= true; if(_ledOff == false){ turnOnLedAll(); }else{ turnOffLedAll(); } }else if(xKeyidx == KEY_QUICK_MACRO){ if(isQuickMacro()){ stopQuickMacro(); }else{ _isQuickMacroDown = true; } return 0; } }else{ // up if(xKeyidx == KEY_BEYOND_FN){ // beyond_fn return 0; }else if(xKeyidx == EXTRA_FN){ _isExtraFNDown = false; }else if(xKeyidx == KEY_QUICK_MACRO){ _isQuickMacroDown = false; return 0; } } return 1; }
/** * Main function, containing the main loop that manages timer- and * USB-functionality. * /return the obligatory integer that nobody cares about... */ void usb_main(void) { // USB Reset by device only required on Watchdog Reset P2U_PS2_PORT &= ~((1 << P2U_PS2_CLOCK_PIN)|(1 << P2U_PS2_DATA_PIN)); // input:tri-state output:low P2U_USB_CFG_DDR &= ~((1 << P2U_USB_CFG_DPLUS_BIT)|(1 << P2U_USB_CFG_DMINUS_BIT));// input, remove USB reset condition // configure timer 0 for a rate of 12M/(1024 * 256) = 45.78Hz (~22ms) //TCCR0 |= (1<<CS02)|(1<<CS00); // timer 0 prescaler: 1024 // TCCR0 &= ~((1<<CS02)|(1<<CS01)|(1<<CS00)); // timer stop usbInit(); uint8_t idleCounter = 0; uchar i = 0; usbDeviceDisconnect(); /* do this while interrupts are disabled */ do{ /* fake USB disconnect for > 250 ms */ // wdt_reset(); _delay_ms(1); }while(--i); usbDeviceConnect(); // init setKeyScanDriver(&driverKeyScanUsb); setUpdateDriver(&updateUsb); clearReportBuffer(); sei(); #if USB_COUNT_SOF bool _isSuspended = false; int suspendCount = 0; #endif for(;;){ #ifndef INTERFACE_ONLY_USB // 카운트 이내에 신호가 잡히지 않으면 이동; // 특별한 경우에만 발생하는 현상이다. if(INTERFACE == INTERFACE_USB && interfaceReady == false && interfaceCount++ > 3000){ // move to ps/2 INTERFACE = INTERFACE_PS2; DBG1(0x88, 0, 0); break; } #endif #if USB_COUNT_SOF if (usbSofCount != 0) { // DBG1(0x55, (uchar *)&usbSofCount, 1); _isSuspended = false; usbSofCount = 0; suspendCount = 0; _usbReset = false; wakeUp(); } else if(_usbReset == true){ // DBG1(0x56, (uchar *)&usbSofCount, 1); _isSuspended = false; usbSofCount = 1; wakeUp(); }else{ // Suspend when no SOF in 3ms-10ms(7.1.7.4 Suspending of USB1.1) if (_isSuspended == false && suspendCount++ > 10000 && getModifierDownBuffer() == 0 && getDownBufferAt(0) == 0) { // DBG1(0x5a, (uchar *)&usbSofCount, 2); _isSuspended = true; sleep(); } } #endif // main event loop usbPoll(); #if USB_COUNT_SOF /*if(_isSuspended == true) { continue; }*/ #endif // check timer if we need periodic reports if (TIFR & (1 << TOV0)) { TIFR = (1 << TOV0); // reset flag if (idleRate != 0) { // do we need periodic reports? if(idleCounter > 4){ // yes, but not yet idleCounter -= 5; // 22ms in units of 4ms } else { // yes, it is time now updateNeeded = 1; idleCounter = idleRate; } } } // if an update is needed, send the report if (usbInterruptIsReady()) { scanKeyUsbWithMacro(); // changes? // ps2avrU loop, must be after scan matrix; enterFrame(); if(updateNeeded){ if(interfaceReady==false) continue; memset(reportKeyboard, 0, REPORT_SIZE_KEYBOARD); reportKeyboard[0] = _modifiers; reportKeyboard[1] = 0; memcpy ( reportKeyboard+2, reportBuffer, strlen((char *)reportBuffer) ); // DBG1(0x06, (uchar *)&reportKeyboard[0], 1); usbSetInterrupt((void *)&reportKeyboard, sizeof(reportKeyboard)); updateNeeded = 0; #if !USB_COUNT_SOF wakeUpUsb(); #endif }else if(_initState == INIT_INDEX_SET_IDLE){ DBG1(0x99, (uchar *)&_initState, 1); _initState = INIT_INDEX_INITED; // 재부팅시 첫키 입력 오류를 방지하기 위해서 HID init 후 all release 전송; memset(reportKeyboard, 0, REPORT_SIZE_KEYBOARD); usbSetInterrupt((void *)&reportKeyboard, sizeof(reportKeyboard)); clearMatrix(); #if !USB_COUNT_SOF wakeUpUsb(); #endif // 플러깅 후 출력되는 메세지는 넘락등 LED가 반응한 후에 보여진다. // usbInterruptIsReady() 일지라도 LED 반응 전에는 출력이 되지 않는다. // LED 반응 후에 처리하려고 하면 MAC OS에서 실행되지 않는다. // (MAC OS에서는 플러깅 시 LED가 반응하지 않는다. 대신 바로 출력이 된다.) // for os x if(idleRate > 0) { startKeyMappingOnBoot(); } // DBG1(0xAA, (uchar *)&idleRate, 1); }else if(_ledInitState == INIT_INDEX_INITED){ _ledInitState = INIT_INDEX_COMPLETE; // for windows if(idleRate == 0) { startKeyMappingOnBoot(); } } } if(usbInterruptIsReady3()){ if(_extraHasChanged){ report_extra_t gReportExtra = { .report_id = REPORT_ID_CONSUMER, .usage = extraData }; usbSetInterrupt3((void *)&gReportExtra, sizeof(gReportExtra)); _extraHasChanged = false; #if !USB_COUNT_SOF wakeUpUsb(); #endif } if(_systemHasChanged){ report_extra_t gReportExtra = { .report_id = REPORT_ID_SYSTEM, .usage = systemData }; usbSetInterrupt3((void *)&gReportExtra, sizeof(gReportExtra)); _systemHasChanged = false; #if !USB_COUNT_SOF wakeUpUsb(); #endif } } if(_initState == INIT_INDEX_INITED){ if(initCount++ == 200){ // delay for OS X USB multi device // all platform init led initAfterInterfaceMount(); }else if(initCount > 200){ initCount = 201; _initState = INIT_INDEX_COMPLETE; } } #if !USB_COUNT_SOF // 입력이 한동안 없으면 슬립모드로; countSleepUsb(); #endif } #ifndef INTERFACE_ONLY_USB // data line reset; USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT); #endif }