//***************************************************************************** // // Performs all necessary menu and control processing based on new button // states. // // \param ucButtons contains the current state of each of the front panel // buttons. A 1 in a bit position indicates that the corresponding button // is released while a 0 indicates that the button is pressed. // \param ucChanged contains bit flags showing which button states changed // since the last call to this function. A 1 indicates that the corresponding // button state changed while a 0 indicates that it remains unchanged. // \param ucRepeat contains bit flags indicating whether a key autorepeat // event is being signalled for each key. A 1 indicates that an autorepeat is // being signalled while a 0 indicates that it is not. // // This is the top level function called when any key changes state. This // updates the relevant control or controls on the screen and processes // the key appropriately for the control that currently has focus. // // \return Returns \b true if the menu was dismissed as a result of this // call (in which case the caller should refresh the main waveform // display area) or any control reported that a display update is required. // Returns \b false if the menu is still being displayed or if it // was not being displayed when the function was called and no control // reported needing a display update. // //***************************************************************************** tBoolean MenuProcess(unsigned char ucButtons, unsigned char ucChanged, unsigned char ucRepeat) { tGroup *pFocusGroup; tBoolean bRetcode; tBoolean bRedrawNeeded; // // Assume we won't be dismissing the menu until we find out otherwise. // bRedrawNeeded = false; // // Which group has focus? // pFocusGroup = g_sMenu.ppcGroups[g_sMenu.ucFocusGroup]; // // Is the menu currently visible? // if(!g_bMenuShown) { // // The menu is not currently shown. First check to see if we need to // show it and, if so, do this. We look for a release of the select // button to trigger the display of the menu. Note that we // deliberately ignore all other key notifications that may be present // at the same time. // if(BUTTON_RELEASED(SELECT_BUTTON, ucButtons, ucChanged)) { // // Draw the menu. // g_bMenuShown = MenuDisplay(&g_sMenu); // // Get rid of any alert message that may currently be displayed. // RendererClearAlert(); } else { // // We were not being asked to show the menu so we pass the // various events on to the group for it to decide what to do // with them. For the group, we pass on any button press or auto- // repeat indication. We ignore button releases in this case. // // // Left button press or repeat. // if(BUTTON_PRESSED(LEFT_BUTTON, ucButtons, ucChanged) || BUTTON_REPEAT(LEFT_BUTTON, ucRepeat)) { bRetcode = pFocusGroup->pfnGroupEventProc(pFocusGroup, MENU_EVENT_LEFT); if(bRetcode) { bRedrawNeeded = true; } } // // Right button press or repeat. // if(BUTTON_PRESSED(RIGHT_BUTTON, ucButtons, ucChanged) || BUTTON_REPEAT(RIGHT_BUTTON, ucRepeat)) { bRetcode = pFocusGroup->pfnGroupEventProc(pFocusGroup, MENU_EVENT_RIGHT); if(bRetcode) { bRedrawNeeded = true; } } // // Left button released. // if(BUTTON_RELEASED(LEFT_BUTTON, ucButtons, ucChanged)) { bRetcode = pFocusGroup->pfnGroupEventProc(pFocusGroup, MENU_EVENT_LEFT_RELEASE); if(bRetcode) { bRedrawNeeded = true; } } // // Right button released. // if(BUTTON_RELEASED(RIGHT_BUTTON, ucButtons, ucChanged)) { bRetcode = pFocusGroup->pfnGroupEventProc(pFocusGroup, MENU_EVENT_RIGHT_RELEASE); if(bRetcode) { bRedrawNeeded = true; } } // // Up button press. // if(BUTTON_PRESSED(UP_BUTTON, ucButtons, ucChanged) || BUTTON_REPEAT(UP_BUTTON, ucRepeat)) { bRetcode = pFocusGroup->pfnGroupEventProc(pFocusGroup, MENU_EVENT_UP); if(bRetcode) { bRedrawNeeded = true; } } // // Down button press. // if(BUTTON_PRESSED(DOWN_BUTTON, ucButtons, ucChanged) || BUTTON_REPEAT(DOWN_BUTTON, ucRepeat)) { bRetcode = pFocusGroup->pfnGroupEventProc(pFocusGroup, MENU_EVENT_DOWN); if(bRetcode) { bRedrawNeeded = true; } } } } else { // // The menu is already visible so we ignore left and right keys and // use up/down/select only to change the focus group. // // // If this button press will result in a group focus change we need to // redraw the current group in its non-focused colors, update the // focus to the new group then send an activate event to the group. // if(BUTTON_PRESSED(DOWN_BUTTON, ucButtons, ucChanged) || BUTTON_REPEAT(DOWN_BUTTON, ucRepeat) || BUTTON_PRESSED(UP_BUTTON, ucButtons, ucChanged) || BUTTON_REPEAT(UP_BUTTON, ucRepeat)) { // // Redraw the current focus button in its original colors // MenuDrawGroupButton(&g_sMenu, g_sMenu.ucFocusGroup, &g_psBtnColors); // // Update the group with the focus // if(BUTTON_PRESSED(DOWN_BUTTON, ucButtons, ucChanged) || BUTTON_REPEAT(DOWN_BUTTON, ucRepeat)) { if(g_sMenu.ucFocusGroup < (g_sMenu.ucNumGroups - 1)) { g_sMenu.ucFocusGroup++; } } else { if(g_sMenu.ucFocusGroup > 0) { g_sMenu.ucFocusGroup--; } } // // Redraw the new focus button with the focus colors. // MenuDrawGroupButton(&g_sMenu, g_sMenu.ucFocusGroup, &g_psFocusColors); // // Tell the new group that it has been activated. // pFocusGroup = g_sMenu.ppcGroups[g_sMenu.ucFocusGroup]; bRetcode = (pFocusGroup->pfnGroupEventProc)(pFocusGroup, MENU_EVENT_ACTIVATE); if(bRetcode) { bRedrawNeeded = true; } } // // Now look for a release of the SELECT key. This indicates that we // must dismiss the menu. // if(BUTTON_RELEASED(SELECT_BUTTON, ucButtons, ucChanged)) { // // We did receive a release message for the SELECT button so // tell the caller that the menu has been dismissed. // g_bMenuShown = false; bRedrawNeeded = true; } } // // Play the button click sound if any button was just pressed. // if((~ucButtons & ucChanged) && g_bClicksEnabled) { ClassDPlayADPCM(g_pucADPCMClick, sizeof(g_pucADPCMClick)); } return(bRedrawNeeded); }
//***************************************************************************** // // This is interrupt handler for the systick interrupt. // // This function handles the interrupts generated by the system tick. These // are used for button debouncing and updating the state of the buttons. // The buttons are stored in a bitmask indicating which buttons have been // release. If a button is pressed twice, only one press will be seen. There // is no press and hold detection. // // \return None. // //***************************************************************************** void SysTickHandler(void) { unsigned char ucButtons; unsigned char ucChanged; unsigned char ucRepeat; // // Determine the state of the pushbuttons. // ucButtons = ButtonsPoll(&ucChanged, &ucRepeat); // // Up button has been released. // if(BUTTON_RELEASED(UP_BUTTON, ucButtons, ucChanged)) { g_ulButtons |= BUTTON_UP_CLICK; } // // Up button has been held. // if(BUTTON_REPEAT(UP_BUTTON, ucRepeat)) { g_ulButtons |= BUTTON_UP_CLICK; } // // Down button has been released. // if(BUTTON_RELEASED(DOWN_BUTTON, ucButtons, ucChanged)) { g_ulButtons |= BUTTON_DOWN_CLICK; } // // Down button has been held. // if(BUTTON_REPEAT(DOWN_BUTTON, ucRepeat)) { g_ulButtons |= BUTTON_DOWN_CLICK; } // // Left button has been released. // if(BUTTON_RELEASED(LEFT_BUTTON, ucButtons, ucChanged)) { g_ulButtons |= BUTTON_LEFT_CLICK; } // // Right button has been released. // if(BUTTON_RELEASED(RIGHT_BUTTON, ucButtons, ucChanged)) { g_ulButtons |= BUTTON_RIGHT_CLICK; } // // Select button has been released. // if(BUTTON_RELEASED(SELECT_BUTTON, ucButtons, ucChanged)) { g_ulButtons |= BUTTON_SELECT_CLICK; } }
//***************************************************************************** // // This function handles updates due to the buttons. // // This function is called from the main loop each time the buttons need to // be checked. If it detects an update it will schedule an transfer to the // host. // // Returns Returns \b true on success or \b false if an error is detected. // //***************************************************************************** tBoolean ButtonHandler(void) { unsigned char ucButtons, ucChanged, ucRepeat; unsigned long ulRetcode; char cDeltaX, cDeltaY; tBoolean bSuccess; // // Determine the state of the pushbuttons. // ucButtons = ButtonsPoll(&ucChanged, &ucRepeat); // // Update the display to show which buttons are currently pressed. // UpdateDisplay(ucButtons); // // If we are connected to the host and the select button changed state or // we see a repeat message from any of the direction buttons, go ahead and // send a mouse state change to the host. // if((ucChanged & SELECT_BUTTON) || (ucRepeat & ~SELECT_BUTTON)) { // // Assume no change in the position until we determine otherwise. // cDeltaX = 0; cDeltaY = 0; // // Up button is held down // if(BUTTON_REPEAT(UP_BUTTON, ucRepeat)) { cDeltaY = MOUSE_MOVE_DEC; } // // Down button is held down. // if(BUTTON_REPEAT(DOWN_BUTTON, ucRepeat)) { cDeltaY = MOUSE_MOVE_INC; } // // Left button is held down. // if(BUTTON_REPEAT(LEFT_BUTTON, ucRepeat)) { cDeltaX = MOUSE_MOVE_DEC; } // // Right button is held down // if(BUTTON_REPEAT(RIGHT_BUTTON, ucRepeat)) { cDeltaX = MOUSE_MOVE_INC; } // // Tell the HID driver to send this new report for us. Note that a 0 // in ucButtons indicates that the relevant button is pressed so we // set the MOUSE_REPORT_BUTTON_1 bit if SELECT_BUTTON is clear in // ucButtons. // DEBUG_PRINT("Sending (0x%02x, 0x%02x), button %s.\n", cDeltaX, cDeltaY, ((ucButtons & SELECT_BUTTON) ? "released" : "pressed")); g_eMouseState = MOUSE_STATE_SENDING; ulRetcode = USBDHIDMouseStateChange((void *)&g_sMouseDevice, cDeltaX, cDeltaY, ((ucButtons & SELECT_BUTTON) ? 0 : MOUSE_REPORT_BUTTON_1)); // // Did we schedule the report for transmission? // if(ulRetcode == MOUSE_SUCCESS) { // // Wait for the host to acknowledge the transmission if all went // well. // bSuccess = WaitForSendIdle(MAX_SEND_DELAY); // // Did we time out waiting for the packet to be sent? // if (!bSuccess) { // // Yes - assume the host disconnected and go back to // waiting for a new connection. // DEBUG_PRINT("Send timed out!\n"); g_bConnected = 0; } } else { // // An error was reported when trying to send the report. This may // be due to host disconnection but could also be due to a clash // between our attempt to send a report and the driver sending the // last report in response to an idle timer timeout so we don't // jump to the conclusion that we were disconnected in this case. // DEBUG_PRINT("Can't send report.\n"); bSuccess = false; } } else { // // There was no change in the state of the buttons so we have nothing // to do. // bSuccess = true; } return(bSuccess); }