// Returns the keykode of the pressed key, or NO_KEY if no key is pressed char KeypadSimple::getKey(){ char key = NO_KEY; // Assume that no key is pressed, this is the default return for getKey() for (byte k=0; k<size.keys; k++){ // Scan all the rows for a key press. // The user pressed a button for more then debounceTime microseconds. if (currentKey == keymap[k]){ // Button hold if (((millis()-lastUpdate) >= holdTime) && digitalRead(Pins[k]) == LOW){ transitionTo(HOLD); } // Button release if (((millis()-lastUpdate) >= debounceTime) && digitalRead(Pins[k]) == HIGH){ transitionTo(RELEASED); currentKey = NO_KEY; } } // Button pressed event. The user pressed a button. else if (((millis()-lastUpdate) >= debounceTime) && digitalRead(Pins[k]) == LOW){ key = keymap[k]; lastUpdate = millis(); goto EVALUATE_KEY; // Save resources and do not attempt to parse two keys at a time } } EVALUATE_KEY: if (key != NO_KEY && key != currentKey){ currentKey = key; transitionTo(PRESSED); return currentKey; } else{ return NO_KEY; } }
void StateMachine::update(){ // TODO while more events uint8_t ev; while(ev){ // Does the current state have a trigger for this state? Transition * t = state->findTransition(ev); // nope if(t == NULL) continue; transitionTo(t->to); } // Does the current state have an any-state? Transition * t = state->findTransition(E_ANY); // yes if(t != NULL){ transitionTo(t->to); } };
// Private // I rewrote the state machine and renamed it. The old getKey() method failed // to return the IDLE state and was too tightly integrated with the key scan // to make simple changes without breaking it completely. But more importantly // only one key can ever be evaluated at one point in time. KeyState Keypad::getKeyState() { static unsigned long startTime; static unsigned long Timer; static boolean buttons; stateChanged = false; // Scan keypad once every 10 mS. This makes the loop() count go from about // 4,000 loops per second to about 40,000 loops per second. A 10 fold increase // in program speed. It is also responsible for the major portion of time used // for debouncing the keys. Most humans can't press a key any faster than 20 mS // so the end user won't notice any lag at 10 mS. if ( (millis()-startTime)>10 ) startTime = millis(); else return state; // Find out whether or not a key was pressed and if so which one it was. buttons = scanKeys(); switch (state) { case IDLE: // The only thing to do while idling is to look for a debounced keypress. if( buttons==CLOSED && (millis()-Timer)>debounceTime ) { transitionTo(PRESSED); Timer = millis(); } break; case PRESSED: // Waiting for a key hold... if ( (millis()-Timer)>holdTime ) { transitionTo(HOLD); // Move to next state. Timer = millis(); // Reset debounce timer. } // Or for the key to be release. else if ( buttons==OPEN && (millis()-Timer)>debounceTime ) { transitionTo(RELEASED); Timer = millis(); } break; case HOLD: // Waiting for the key to be released. if ( (buttons==OPEN) && (millis()-Timer)>debounceTime ) { transitionTo(RELEASED); Timer = millis(); } break; case RELEASED: transitionTo(IDLE); break; } return state; // Let the world know which state we're in. }
void LtsManager::unselectNonsimilated() { if (m_simulation->isStarted() == (transitionTo(selectedState()) == 0)) { //unselect(); } }
// Returns the keykode of the pressed key, or NO_KEY if no key is pressed char KeyPadGetKey(){ char key = NO_KEY; // Assume that no key is pressed, this is the default return for getKey() uint8_t c; for ( c=0; c<size.columns; c++) { digitalWrite(columnPins[c],LOW); // Activate the current column. uint8_t r; for ( r=0; r<size.rows; r++) { // Scan all the rows for a key press. // The user pressed a button for more then debounceTime microseconds. if (currentKey == keymap[c+(r*size.columns)]) { // Button hold if (((millis()-lastUpdate) >= holdTime) && digitalRead(rowPins[r]) == LOW) { transitionTo(HOLD); } // Button release if (((millis()-lastUpdate) >= debounceTime) && digitalRead(rowPins[r]) == HIGH){ transitionTo(RELEASED); currentKey = NO_KEY; } } // Button pressed event. The user pressed a button. else if (((millis()-lastUpdate) >= debounceTime) && digitalRead(rowPins[r]) == LOW){ digitalWrite(columnPins[c],HIGH); // De-activate the current column. key = keymap[c+(r*size.columns)]; lastUpdate = millis(); currentRow = r; currentCol = c; goto EVALUATE_KEY; // Save resources and do not attempt to parse to keys at a time } } digitalWrite(columnPins[c],HIGH); // De-activate the current column. } EVALUATE_KEY: if (key != NO_KEY && key != currentKey){ currentKey = key; transitionTo(PRESSED); return currentKey; } else{ return NO_KEY; } }
void LtsManager::simulateState(State *state) { if (m_simulation) { Transition *transition = transitionTo(state); if (transition) { m_simulation->followTransition(transition); } } }
// Private // This function is a state machine but is also used for debouncing the keys. void Keypad::nextKeyState(byte idx, boolean button) { key[idx].stateChanged = false; switch (key[idx].kstate) { case IDLE: if (button==CLOSED) { transitionTo (idx, PRESSED); holdTimer = millis(); } // Get ready for next HOLD state. break; case PRESSED: if ((millis()-holdTimer)>holdTime) // Waiting for a key HOLD... transitionTo (idx, HOLD); else if (button==OPEN) // or for a key to be RELEASED. transitionTo (idx, RELEASED); break; case HOLD: if (button==OPEN) transitionTo (idx, RELEASED); break; case RELEASED: transitionTo (idx, IDLE); break; } }
// <<constructor>> Allows custom keymap, pin configuration, and keypad sizes. Keypad::Keypad(char *userKeymap, byte *row, byte *col, byte numRows, byte numCols) { rowPins = row; columnPins = col; size.rows = numRows; size.columns = numCols; begin(userKeymap); setDebounceTime(2); setHoldTime(500); keypadEventListener = 0; transitionTo(IDLE); stateChanged = false; initializePins(); }
void LtsManager::selectState(State *state) { if (m_lts) { m_selectedState = state; if (m_simulation->isStarted()) { Transition *transition = transitionTo(state); if (transition) { m_simulation->selectTransition(transition); } } else { m_simulation->setInitialState(state); } emit selectionChanged(); } }
void HeadProvider::setCommand(const SetHeadCommand::ptr command) { transitionTo(SET); yawDest = command->getYaw(); pitchDest = command->getPitch(); yawMaxSpeed = command->getMaxSpeedYaw(); pitchMaxSpeed = command->getMaxSpeedPitch(); /* ** *///debugging speed clipping (should probably stay in some form) yawMaxSpeed = NBMath::clip(yawMaxSpeed, 0, Kinematics::jointsMaxVelNominal [Kinematics::HEAD_YAW]*.1f); pitchMaxSpeed = NBMath::clip(pitchMaxSpeed, 0, Kinematics::jointsMaxVelNominal [Kinematics::HEAD_PITCH]*.1f); setActive(); currHeadCommand = command; }
void Pixel::transitionTo(uint8_t steps, Color color) { //transitionTo(steps, color.red, color.green, color.blue); transitionTo(steps, random(20), random(20), random(20)); }
/* || @description || | Returns the keycode of the pressed key, or NO_KEY if no key is pressed || | The keycode is retrieved from the keymap array || # */ char Keypad::getKey() { char key = NO_KEY; // Assume that no key is pressed, this is the default return for getKey() for (byte c = 0; c < size.columns; c++) { digitalWrite(columnPins[c], LOW); // Activate the current column. for (byte r = 0; r < size.rows; r++) // Scan all the rows for a key press. { // The user pressed a button for more then debounceTime microseconds. if (currentKey == keymap[c + (r * size.columns)]) { // Button hold if (((millis() - lastUpdate) >= holdTime) && digitalRead(rowPins[r]) == LOW) { transitionTo(HOLD); } // Button release if (((millis() - lastUpdate) >= debounceTime) && digitalRead(rowPins[r]) == HIGH) { transitionTo(RELEASED); lastKey = currentKey; currentKey = NO_KEY; break; } else if (state == HOLD) { break; } } // Button pressed event. The user pressed a button. else if (((millis() - lastUpdate) >= debounceTime) && digitalRead(rowPins[r]) == LOW) { digitalWrite(columnPins[c], HIGH); // De-activate the current column. key = keymap[c + (r * size.columns)]; lastPress = lastUpdate; lastUpdate = millis(); break; } } if (key != NO_KEY) { break; } digitalWrite(columnPins[c], HIGH); // De-activate the current column. } if (key != NO_KEY) { if (key == lastKey && ((millis() - lastPress) <= multiPressTime)) { pressCount++; // increase press count to return the correct key (if multiple keys are available) currentKey = key; transitionTo(PRESSED); } else if (key != currentKey) { pressCount = 1; // key was pressed the first time currentKey = key; transitionTo(PRESSED); } else { return NO_KEY; } return currentKey; } else { return NO_KEY; } }
void HeadProvider::setCommand(const HeadJointCommand::ptr command) { transitionTo(SCRIPTED); headCommandQueue.push(command); setActive(); }