diff --git a/.project b/.project new file mode 100644 index 0000000..ed8dc0b --- /dev/null +++ b/.project @@ -0,0 +1,11 @@ + + + electronic-leadscrew + + + + + + + + diff --git a/els-f280049c/ControlPanel.cpp b/els-f280049c/ControlPanel.cpp index 5a6a5ba..969a3e9 100644 --- a/els-f280049c/ControlPanel.cpp +++ b/els-f280049c/ControlPanel.cpp @@ -230,6 +230,9 @@ KEY_REG ControlPanel :: readKeys(void) CS_RELEASE; DELAY_US(CS_RISE_TIME_US); // give CS line time to register high + // keyMask = (MSb) POWER, SET, FWD/REV, FEED/THREAD, IN/MM, DOWN, x, UP (LSb) + // 0 = up + // 1 = down return keyMask; } @@ -240,39 +243,102 @@ KEY_REG ControlPanel :: getKeys() configureSpiBus(); + // newKeys.all = (MSb) POWER, SET, FWD/REV, FEED/THREAD, IN/MM, DOWN, x, UP (LSb) + // 0 = up + // 1 = down newKeys = readKeys(); - if( isValidKeyState(newKeys) && isStable(newKeys) && newKeys.all != this->keys.all ) { + + // Original: if( isValidKeyState(newKeys) && isStable(newKeys) && newKeys.all != this->keys.all ) + // Apply three filters to eliminate spurious key presses due to noise. + // With the exception of the UP/DOWN keys: + // 1) Reject multiple keys down. + // 2) Reject any data that isn't the same for several (now 3) consecutive reads. + // 3) Accept a key press only if the previous stable value showed no keys pressed. + if( isValidKeyState(newKeys) && isStable(newKeys) ) + { KEY_REG previousKeys = this->keys; // remember the previous stable value this->keys = newKeys; - if( previousKeys.all == 0 ) { // only act if the previous stable value was no keys pressed + if( (previousKeys.all & 0xF8) == 0 ) + { // only act if the previous stable value was no keys pressed return newKeys; } } return noKeys; } -bool ControlPanel :: isValidKeyState(KEY_REG testKeys) { +bool ControlPanel :: isValidKeyState(KEY_REG testKeys) +{ // filter out any states with multiple keys pressed (bad communication filter) - switch(testKeys.all) { - case 0: - case 1 << 0: - case 1 << 2: - case 1 << 3: - case 1 << 4: - case 1 << 5: - case 1 << 6: - case 1 << 7: + // testKeys = (MSb) POWER, SET, FWD/REV, FEED/THREAD, IN/MM, DOWN, x, UP (LSb) + // 0 = up + // 1 = down + switch(testKeys.all & 0xF8) // ignore UP/DOWN keys + { + case 0: // no keys pressed + case 1 << 0: // only UP pressed + case 1 << 2: // only DOWN pressed + case 1 << 3: // only IN/MM pressed + case 1 << 4: // only FEED/THREAD pressed + case 1 << 5: // only FWD/REV pressed + case 1 << 6: // only SET pressed + case 1 << 7: // only POWER pressed return true; } - return false; + return false; // two or more keys are pressed } - -bool ControlPanel :: isStable(KEY_REG testKeys) { +bool ControlPanel :: isStable(KEY_REG testKeys) +{ // don't trust any read key state until we've seen it multiple times consecutively (noise filter) - if( testKeys.all != stableKeys.all ) + // ignore UP/DOWN keys + // How does this work? + // Initial conditions: + // stableKeys.all == 0 + // stableCount == 0 + // First loop: + // We can assume all keys are up, so + // The comparison is false and stableCount 0 is less than MIN_CONSECUTIVE_READS (assumed to be 3), so + // stableCount = 1. + // stableCount is not >= 3, so the function returns false + // Second loop: + // All keys are still up, so + // The comparison is false and stableCount 1 is less than 3, so + // stableCount = 2. + // stableCount is not >= 3, so the function again returns false + // Third loop: + // All keys are still up, so + // The comparison is false and stableCount 2 is less than 3, so + // stableCount = 3. + // stableCount is now >= 3, so the function again returns true + // Fourth and subsequent loops: + // All keys are still up, so + // The comparison is false but stableCount 3 is not less than 3, so + // stableCount = 3. + // stableCount is now >= 3, so the function again returns true + // + // Now suppose the PWR key is pressed: + // testKeys.all == 0x80 and stableKeys == 0, so the first predicate is true. + // stableKeys == testKeys + // stableCount == 1 + // stableCount is not >= 3, so the function returns false + // At the third loop: + // testKeys.all == stableKeys, so the first predicate is false. + // stableCount == 3, which is not < 3, so the second predicate is false + // stableCount == 3, which is >= 3, so the function returns true + // As long as PWR is pressed, + // testKeys.all == stableKeys, so the first predicate is false. + // stableCount == 3, which is not < 3, so the second predicate is false + // stableCount == 3, which is >= 3, so the function returns true + // When PWR is released, + // testKeys.all != stableKeys, so the first predicate is true. + // stableKeys == testKeys + // stableCount == 1 + // stableCount is < 3, so the second predicate is true, so + // stableCount == 2 + // stableCount is not >= 3, so the function returns false + if( (testKeys.all & 0xF8) != (stableKeys.all & 0xF8) ) // was if( testKeys.all != stableKeys.all ) { this->stableKeys = testKeys; this->stableCount = 1; @@ -293,13 +359,44 @@ void ControlPanel :: setMessage( const Uint16 *message ) this->message = message; } +void ControlPanel :: increaseBrightness() +{ + ++brightness; + + if (brightness == 5) brightness = 8; + + setBrightness(brightness); +} + +void ControlPanel :: decreaseBrightness() +{ + --brightness; + + if(brightness == 7) brightness = 4; + + setBrightness(brightness); +} + void ControlPanel :: setBrightness( Uint16 brightness ) +// Because of the screwy way the TM1638 controls brightness in steps of 1/16, +// 2/16, 4/16, 10/16, 11/16, 12/16, 13/16, and 14/16, +// there are really only five distinct levels. +// Limit brightness value sent to control panel to 1, 2, 3, 4, or 8. +// 0 = off. +// 5, 6, and 7 are indistinguishable from 4. { + if (brightness == 0) brightness = 1; + if( brightness > 8 ) brightness = 8; this->brightness = brightness; } +Uint16 ControlPanel :: getBrightness(void) +{ + return this->brightness; +} + void ControlPanel :: refresh() { configureSpiBus(); @@ -310,7 +407,282 @@ void ControlPanel :: refresh() sendData(); } +Uint16 ControlPanel :: buttonStateMachine(bool incrementButtonPressed, bool decrementButtonPressed) +{ +static Uint16 loopCount = 0; +static Uint16 state = BSM_STATE_IDLE; +char buttonConfiguration; + +Uint16 returnValue = BSM_NO_ACTION; + + ++loopCount; + + // get button configuration for input to state machine + if (decrementButtonPressed && incrementButtonPressed) + { + buttonConfiguration = BSM_INPUT_BOTH_BUTTONS_PRESSED; + } + else if (decrementButtonPressed) + { + buttonConfiguration = BSM_INPUT_DECREMENT_BUTTON_PRESSED; + } + else if (incrementButtonPressed) + { + buttonConfiguration = BSM_INPUT_INCREMENT_BUTTON_PRESSED; + } + else + { + buttonConfiguration = BSM_INPUT_NEITHER_BUTTON_PRESSED; + } + + // set default returned action + returnValue = BSM_NO_ACTION; + + switch (state) + { + case BSM_STATE_IDLE: + + switch (buttonConfiguration) + { + case BSM_INPUT_NEITHER_BUTTON_PRESSED: + state = BSM_STATE_IDLE; + break; + + case BSM_INPUT_INCREMENT_BUTTON_PRESSED: + loopCount = 0; + state = BSM_STATE_WAIT_FOR_AUTO_SLOW_INCREMENT; + returnValue = BSM_INCREMENT; + break; + + case BSM_INPUT_DECREMENT_BUTTON_PRESSED: + loopCount = 0; + state = BSM_STATE_WAIT_FOR_AUTO_SLOW_DECREMENT; + returnValue = BSM_DECREMENT; + break; + + case BSM_INPUT_BOTH_BUTTONS_PRESSED: + // It would be difficult to press both buttons simultaneously + // enough that one would not be read first. + state = BSM_STATE_IDLE; + break; + } + + break; + + case BSM_STATE_WAIT_FOR_AUTO_SLOW_INCREMENT: + + switch (buttonConfiguration) + { + case BSM_INPUT_NEITHER_BUTTON_PRESSED: + state = BSM_STATE_IDLE; + break; + + case BSM_INPUT_INCREMENT_BUTTON_PRESSED: + if (loopCount >= BSM_INITIAL_DELAY) + { + loopCount = 0; + state = BSM_STATE_AUTO_SLOW_INCREMENT; + returnValue = BSM_INCREMENT; + } + else + { + state = BSM_STATE_WAIT_FOR_AUTO_SLOW_INCREMENT; + } + break; + + case BSM_INPUT_DECREMENT_BUTTON_PRESSED: + loopCount = 0; + state = BSM_STATE_WAIT_FOR_AUTO_SLOW_DECREMENT; + returnValue = BSM_DECREMENT; + break; + + case BSM_INPUT_BOTH_BUTTONS_PRESSED: + loopCount = 0; + state = BSM_STATE_AUTO_FAST_INCREMENT; + returnValue = BSM_INCREMENT; + break; + } + + break; + + case BSM_STATE_WAIT_FOR_AUTO_SLOW_DECREMENT: + + switch (buttonConfiguration) + { + case BSM_INPUT_NEITHER_BUTTON_PRESSED: + state = BSM_STATE_IDLE; + break; + + case BSM_INPUT_INCREMENT_BUTTON_PRESSED: + loopCount = 0; + state = BSM_STATE_WAIT_FOR_AUTO_SLOW_INCREMENT; + returnValue = BSM_INCREMENT; + break; + + case BSM_INPUT_DECREMENT_BUTTON_PRESSED: + if (loopCount >= BSM_INITIAL_DELAY) + { + loopCount = 0; + state = BSM_STATE_AUTO_SLOW_DECREMENT; + returnValue = BSM_DECREMENT; + } + else + { + state = BSM_STATE_WAIT_FOR_AUTO_SLOW_DECREMENT; + } + break; + + case BSM_INPUT_BOTH_BUTTONS_PRESSED: + loopCount = 0; + state = BSM_STATE_AUTO_FAST_DECREMENT; + returnValue = BSM_DECREMENT; + break; + } + + break; + + case BSM_STATE_AUTO_SLOW_INCREMENT: + + switch (buttonConfiguration) + { + case BSM_INPUT_NEITHER_BUTTON_PRESSED: + state = BSM_STATE_IDLE; + break; + + case BSM_INPUT_INCREMENT_BUTTON_PRESSED: + if (loopCount >= BSM_SLOW_DELAY) + { + loopCount = 0; + returnValue = BSM_INCREMENT; + } + state = BSM_STATE_AUTO_SLOW_INCREMENT; + break; + + case BSM_INPUT_DECREMENT_BUTTON_PRESSED: + loopCount = 0; + state = BSM_STATE_WAIT_FOR_AUTO_SLOW_DECREMENT; + returnValue = BSM_DECREMENT; + break; + + case BSM_INPUT_BOTH_BUTTONS_PRESSED: + loopCount = 0; + state = BSM_STATE_AUTO_FAST_INCREMENT; + returnValue = BSM_INCREMENT; + break; + } + + break; + + case BSM_STATE_AUTO_SLOW_DECREMENT: + switch (buttonConfiguration) + { + case BSM_INPUT_NEITHER_BUTTON_PRESSED: + state = BSM_STATE_IDLE; + break; + + case BSM_INPUT_INCREMENT_BUTTON_PRESSED: + loopCount = 0; + state = BSM_STATE_WAIT_FOR_AUTO_SLOW_INCREMENT; + returnValue = BSM_INCREMENT; + break; + + case BSM_INPUT_DECREMENT_BUTTON_PRESSED: + if (loopCount >= BSM_SLOW_DELAY) + { + loopCount = 0; + returnValue = BSM_DECREMENT; + } + state = BSM_STATE_AUTO_SLOW_DECREMENT; + break; + + case BSM_INPUT_BOTH_BUTTONS_PRESSED: + loopCount = 0; + state = BSM_STATE_AUTO_FAST_DECREMENT; + returnValue = BSM_DECREMENT; + break; + } + + break; + + case BSM_STATE_AUTO_FAST_INCREMENT: + + switch (buttonConfiguration) + { + case BSM_INPUT_NEITHER_BUTTON_PRESSED: + state = BSM_STATE_IDLE; + break; + + case BSM_INPUT_INCREMENT_BUTTON_PRESSED: + // the decrement button has just been released + // stop the auto fast increment and return to auto slow increment + loopCount= 0; + state = BSM_STATE_AUTO_SLOW_INCREMENT; + break; + + case BSM_INPUT_DECREMENT_BUTTON_PRESSED: + // the increment button has just been released + // stop auto fast decrement and go to auto slow decrement + loopCount = 0; + state = BSM_STATE_WAIT_FOR_AUTO_SLOW_DECREMENT; + break; + + case BSM_INPUT_BOTH_BUTTONS_PRESSED: + // continue auto fast increment + if (loopCount >= BSM_FAST_DELAY) + { + loopCount = 0; + returnValue = BSM_INCREMENT; + } + state = BSM_STATE_AUTO_FAST_INCREMENT; + break; + } + + break; + + case BSM_STATE_AUTO_FAST_DECREMENT: + + switch (buttonConfiguration) + { + case BSM_INPUT_NEITHER_BUTTON_PRESSED: + state = BSM_STATE_IDLE; + break; + + case BSM_INPUT_INCREMENT_BUTTON_PRESSED: + // the decrement button has just been released + // return to auto slow increment + loopCount = 0; + state = BSM_STATE_WAIT_FOR_AUTO_SLOW_INCREMENT; + break; + + case BSM_INPUT_DECREMENT_BUTTON_PRESSED: + // the increment button has just been released + // return to auto slow decrement + loopCount = 0; + state = BSM_STATE_AUTO_SLOW_DECREMENT; + break; + + case BSM_INPUT_BOTH_BUTTONS_PRESSED: + // continue auto fast decrement + if (loopCount >= BSM_FAST_DELAY) + { + loopCount = 0; + returnValue = BSM_DECREMENT; + } + state = BSM_STATE_AUTO_FAST_DECREMENT; + break; + } + + break; + + default: + state = BSM_STATE_IDLE; + break; + + } + + return returnValue; +} diff --git a/els-f280049c/ControlPanel.h b/els-f280049c/ControlPanel.h index f118f1a..d266d4e 100644 --- a/els-f280049c/ControlPanel.h +++ b/els-f280049c/ControlPanel.h @@ -30,6 +30,16 @@ #include "F28x_Project.h" #include "SPIBus.h" +// Seven segment display segment mapping: +// +// MSb 7 6 5 4 3 2 1 0 x x x x x x x x LSb +// +// 7 +// 2 6 +// 1 +// 3 5 +// 4 +// 0 #define ZERO 0b1111110000000000 // 0 #define ONE 0b0110000000000000 // 1 @@ -44,35 +54,85 @@ #define POINT 0b0000000100000000 // . #define BLANK 0b0000000000000000 +// Some lowercase letters have to be the same as the +// uppercase letter. #define LETTER_A 0b1110111000000000 +#define LETTER_a 0b1111101000000000 #define LETTER_B 0b0011111000000000 +#define LETTER_b 0b0011111000000000 #define LETTER_C 0b1001110000000000 +#define LETTER_c 0b0011001000000000 #define LETTER_D 0b0111101000000000 +#define LETTER_d 0b0111101000000000 #define LETTER_E 0b1001111000000000 +#define LETTER_e 0b1001111000000000 #define LETTER_F 0b1000111000000000 +#define LETTER_f 0b1000111000000000 #define LETTER_G 0b1011110000000000 +#define LETTER_g 0b1011110000000000 #define LETTER_H 0b0110111000000000 +#define LETTER_h 0b0010111000000000 #define LETTER_I 0b0000110000000000 +#define LETTER_i 0b0010000000000000 #define LETTER_J 0b0111100000000000 +#define LETTER_j 0b0111100000000000 #define LETTER_K 0b1010111000000000 +#define LETTER_k 0b1010111000000000 #define LETTER_L 0b0001110000000000 +#define LETTER_l 0b0001110000000000 #define LETTER_M 0b1010100000000000 +#define LETTER_m 0b1010100000000000 #define LETTER_N 0b1110110000000000 +#define LETTER_n 0b0010101000000000 #define LETTER_O 0b1111110000000000 +#define LETTER_o 0b0011101000000000 #define LETTER_P 0b1100111000000000 +#define LETTER_p 0b1100111000000000 #define LETTER_Q 0b1110011000000000 +#define LETTER_q 0b1110011000000000 #define LETTER_R 0b1100110000000000 +#define LETTER_r 0b0000101000000000 #define LETTER_S 0b1011011000000000 +#define LETTER_s 0b1011011000000000 #define LETTER_T 0b0001111000000000 +#define LETTER_t 0b0001111000000000 #define LETTER_U 0b0111110000000000 +#define LETTER_u 0b0011100000000000 #define LETTER_V 0b0111010000000000 +#define LETTER_v 0b0111010000000000 #define LETTER_W 0b0101010000000000 +#define LETTER_w 0b0101010000000000 #define LETTER_X 0b0110110000000000 +#define LETTER_x 0b0110110000000000 #define LETTER_Y 0b0111011000000000 +#define LETTER_y 0b0111011000000000 #define LETTER_Z 0b1101001000000000 +#define LETTER_z 0b1101001000000000 #define DASH 0b0000001000000000 +// button state machine constants +#define BSM_NO_ACTION 0 +#define BSM_INCREMENT 1 +#define BSM_DECREMENT 2 + +#define BSM_INITIAL_DELAY 30 // delay before auto slow increment/decrement begins +#define BSM_SLOW_DELAY 15 // delay between changes in auto slow increment/decrement +#define BSM_FAST_DELAY 5 // delay between changes in auto fast increment/decrement + +#define BSM_INPUT_NEITHER_BUTTON_PRESSED 0 +#define BSM_INPUT_INCREMENT_BUTTON_PRESSED 1 +#define BSM_INPUT_DECREMENT_BUTTON_PRESSED 2 +#define BSM_INPUT_BOTH_BUTTONS_PRESSED 3 + +#define BSM_STATE_IDLE 0 +#define BSM_STATE_WAIT_FOR_AUTO_SLOW_INCREMENT 1 +#define BSM_STATE_WAIT_FOR_AUTO_SLOW_DECREMENT 2 +#define BSM_STATE_AUTO_SLOW_INCREMENT 3 +#define BSM_STATE_AUTO_SLOW_DECREMENT 4 +#define BSM_STATE_AUTO_FAST_INCREMENT 5 +#define BSM_STATE_AUTO_FAST_DECREMENT 6 + #define LED_TPI 1 #define LED_INCH (1<<1) #define LED_MM (1<<2) @@ -102,6 +162,7 @@ typedef union LED_REG struct KEY_BITS { + // MSb POWER, SET, FWD/REV, FEED/THREAD, IN/MM, DOWN, x, UP LSb Uint16 UP:1; Uint16 reserved1:1; Uint16 DOWN:1; @@ -165,6 +226,7 @@ class ControlPanel void configureSpiBus(void); bool isValidKeyState(KEY_REG); bool isStable(KEY_REG); + void setBrightness(Uint16 x); public: ControlPanel(SPIBus *spiBus); @@ -187,11 +249,16 @@ class ControlPanel // set a message that overrides the display, 8 characters required void setMessage(const Uint16 *message); - // set a brightness value, 0 (off) to 8 (max) - void setBrightness(Uint16 brightness); + Uint16 getBrightness(void); + + void increaseBrightness(void); + + void decreaseBrightness(void); // refresh the hardware display void refresh(void); + + Uint16 buttonStateMachine(bool x, bool y); }; diff --git a/els-f280049c/Debug.cpp b/els-f280049c/Debug.cpp index 3da41e7..0da10c9 100644 --- a/els-f280049c/Debug.cpp +++ b/els-f280049c/Debug.cpp @@ -35,13 +35,25 @@ Debug :: Debug( void ) void Debug :: initHardware( void ) { + // Initialize GPIO + // Doesn't work if put after EALLOW + InitGpio(); + // set up GPIO pins as output for debugging EALLOW; + GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 0; GpioCtrlRegs.GPADIR.bit.GPIO2 = 1; GpioDataRegs.GPACLEAR.bit.GPIO2 = 1; + GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 0; GpioCtrlRegs.GPADIR.bit.GPIO3 = 1; GpioDataRegs.GPACLEAR.bit.GPIO3 = 1; + + // LED4 on LAUNCHXL (red) + GpioCtrlRegs.GPAMUX2.bit.GPIO23 = 0; + GpioCtrlRegs.GPADIR.bit.GPIO23 = 1; + GpioDataRegs.GPACLEAR.bit.GPIO23 = 1; + EDIS; } diff --git a/els-f280049c/Debug.h b/els-f280049c/Debug.h index 993e032..2782843 100644 --- a/els-f280049c/Debug.h +++ b/els-f280049c/Debug.h @@ -31,6 +31,9 @@ class Debug { +private: + Uint16 heartbeatCount; + public: Debug(void); void initHardware(void); @@ -42,6 +45,8 @@ class Debug // analyzer pin 2 void begin2( void ); void end2( void ); + + void heartbeat( void ); }; @@ -65,5 +70,28 @@ inline void Debug :: end2( void ) GpioDataRegs.GPACLEAR.bit.GPIO3 = 1; } +inline void Debug :: heartbeat( void ) +{ + ++heartbeatCount; + + if (heartbeatCount > 50) + { + heartbeatCount = 1; + } + + if (heartbeatCount == 15) + { + // Turn off red LED and turn on green LED + GpioDataRegs.GPASET.bit.GPIO23 = 1; + GpioDataRegs.GPBCLEAR.bit.GPIO34 = 1; + } + + if (heartbeatCount == 1) + { + // Turn on red LED and turn off green LED + GpioDataRegs.GPACLEAR.bit.GPIO23 = 1; + GpioDataRegs.GPBSET.bit.GPIO34 = 1; + } +} #endif // __DEBUG_H diff --git a/els-f280049c/UserInterface.cpp b/els-f280049c/UserInterface.cpp index 0bf1200..173d75f 100644 --- a/els-f280049c/UserInterface.cpp +++ b/els-f280049c/UserInterface.cpp @@ -25,6 +25,7 @@ #include "UserInterface.h" +#include "ControlPanel.h" const MESSAGE STARTUP_MESSAGE_2 = { @@ -39,23 +40,18 @@ const MESSAGE STARTUP_MESSAGE_1 = .next = &STARTUP_MESSAGE_2 }; -const MESSAGE SETTINGS_MESSAGE_2 = +MESSAGE USER_INTERFACE_STATE = { - .message = { LETTER_S, LETTER_E, LETTER_T, LETTER_T, LETTER_I, LETTER_N, LETTER_G, LETTER_S }, - .displayTime = UI_REFRESH_RATE_HZ * .5 -}; - -const MESSAGE SETTINGS_MESSAGE_1 = -{ - .message = { BLANK, BLANK, BLANK, LETTER_N, LETTER_O, BLANK, BLANK, BLANK }, - .displayTime = UI_REFRESH_RATE_HZ * .5, - .next = &SETTINGS_MESSAGE_2 + .message = { LETTER_S, LETTER_T, LETTER_A, LETTER_T, LETTER_E, BLANK, BLANK, BLANK }, + .displayTime = UI_REFRESH_RATE_HZ * 2 }; const Uint16 VALUE_BLANK[4] = { BLANK, BLANK, BLANK, BLANK }; UserInterface :: UserInterface(ControlPanel *controlPanel, Core *core, FeedTableFactory *feedTableFactory) { + userInterfaceState = UI_STATE_NORMAL; + this->controlPanel = controlPanel; this->core = core; this->feedTableFactory = feedTableFactory; @@ -110,24 +106,77 @@ void UserInterface :: setMessage(const MESSAGE *message) void UserInterface :: overrideMessage( void ) { + // see if an override message is pending if( this->message != NULL ) { - if( this->messageTime > 0 ) { + // message pending + // see if message display has timed out + if( this->messageTime > 0 ) + { + // not timed out + // adjust display time this->messageTime--; + + // queue the message to be displayed controlPanel->setMessage(this->message->message); } - else { + else + { + // timed out + // reset user interface state to normal + userInterfaceState = UI_STATE_NORMAL; + + // see if there's another message this->message = this->message->next; if( this->message == NULL ) + { + // no more messages controlPanel->setMessage(NULL); + } else + { + // more messages + // set to display next message this->messageTime = this->message->displayTime; + } } + } // message pending +} + +Uint16 UserInterface :: digitToSevenSegmentPattern(Uint16 digit) +{ + switch (digit) + { + case 0: + return ZERO; + case 1: + return ONE; + case 2: + return TWO; + case 3: + return THREE; + case 4: + return FOUR; + case 5: + return FIVE; + case 6: + return SIX; + case 7: + return SEVEN; + case 8: + return EIGHT; + case 9: + return NINE; + default: + return DASH; } } void UserInterface :: loop( void ) { + Uint16 number; + Uint16 action; + // read the RPM up front so we can use it to make decisions Uint16 currentRpm = core->getRPM(); @@ -141,12 +190,16 @@ void UserInterface :: loop( void ) if( currentRpm == 0 ) { // these keys should only be sensitive when the machine is stopped - if( keys.bit.POWER ) { + if( keys.bit.POWER ) + { this->core->setPowerOn(!this->core->isPowerOn()); + + userInterfaceState = UI_STATE_NORMAL; } // these should only work when the power is on - if( this->core->isPowerOn() ) { + if( this->core->isPowerOn() ) + { if( keys.bit.IN_MM ) { this->metric = ! this->metric; @@ -164,10 +217,98 @@ void UserInterface :: loop( void ) } if( keys.bit.SET ) { - setMessage(&SETTINGS_MESSAGE_1); - } - } - } + switch (userInterfaceState) + { + case UI_STATE_NORMAL: + userInterfaceState = UI_STATE_ADJ_BRT; + + USER_INTERFACE_STATE.message[0] = LETTER_B; + USER_INTERFACE_STATE.message[1] = LETTER_r; + USER_INTERFACE_STATE.message[2] = LETTER_t; + USER_INTERFACE_STATE.message[3] = BLANK; + USER_INTERFACE_STATE.message[4] = BLANK; + USER_INTERFACE_STATE.message[5] = BLANK; + USER_INTERFACE_STATE.message[6] = BLANK; + USER_INTERFACE_STATE.message[7] = digitToSevenSegmentPattern(controlPanel->getBrightness()); + + setMessage(&USER_INTERFACE_STATE); + break; + + case UI_STATE_ADJ_BRT: + userInterfaceState = UI_STATE_uSTPS; + + USER_INTERFACE_STATE.message[0] = LETTER_L; + USER_INTERFACE_STATE.message[1] = LETTER_E; + USER_INTERFACE_STATE.message[2] = LETTER_A; + USER_INTERFACE_STATE.message[3] = LETTER_D; + USER_INTERFACE_STATE.message[4] = BLANK; + USER_INTERFACE_STATE.message[5] = BLANK; + USER_INTERFACE_STATE.message[6] = digitToSevenSegmentPattern(LEADSCREW_TPI / 10); + USER_INTERFACE_STATE.message[7] = digitToSevenSegmentPattern(LEADSCREW_TPI % 10); + + setMessage(&USER_INTERFACE_STATE); + break; + + case UI_STATE_uSTPS: + userInterfaceState = UI_STATE_STEPPER_RES; + + USER_INTERFACE_STATE.message[0] = LETTER_u; + USER_INTERFACE_STATE.message[1] = LETTER_S; + USER_INTERFACE_STATE.message[2] = LETTER_T; + USER_INTERFACE_STATE.message[3] = LETTER_P; + USER_INTERFACE_STATE.message[4] = LETTER_S; + USER_INTERFACE_STATE.message[5] = BLANK; + USER_INTERFACE_STATE.message[6] = BLANK; + USER_INTERFACE_STATE.message[7] = digitToSevenSegmentPattern(STEPPER_MICROSTEPS); + + setMessage(&USER_INTERFACE_STATE); + break; + + case UI_STATE_STEPPER_RES: + userInterfaceState = UI_STATE_ENCODER_RES; + + USER_INTERFACE_STATE.message[0] = LETTER_S | POINT; + USER_INTERFACE_STATE.message[1] = LETTER_r; + USER_INTERFACE_STATE.message[2] = LETTER_E; + USER_INTERFACE_STATE.message[3] = LETTER_S; + number = STEPPER_RESOLUTION; + // note the next four are in reverse order + USER_INTERFACE_STATE.message[7] = digitToSevenSegmentPattern( number % 10 ); + USER_INTERFACE_STATE.message[6] = digitToSevenSegmentPattern( (number = number / 10) % 10 ); + USER_INTERFACE_STATE.message[5] = digitToSevenSegmentPattern( (number = number / 10) % 10 ); + USER_INTERFACE_STATE.message[4] = digitToSevenSegmentPattern( (number = number / 10) % 10 ); + + setMessage(&USER_INTERFACE_STATE); + break; + + case UI_STATE_ENCODER_RES: + userInterfaceState = UI_STATE_CANCEL; + + USER_INTERFACE_STATE.message[0] = LETTER_E | POINT; + USER_INTERFACE_STATE.message[1] = LETTER_r; + USER_INTERFACE_STATE.message[2] = LETTER_E; + USER_INTERFACE_STATE.message[3] = LETTER_S; + number = ENCODER_RESOLUTION; + // note the next four are in reverse order + USER_INTERFACE_STATE.message[7] = digitToSevenSegmentPattern( number % 10 ); + USER_INTERFACE_STATE.message[6] = digitToSevenSegmentPattern( (number = number / 10) % 10 ); + USER_INTERFACE_STATE.message[5] = digitToSevenSegmentPattern( (number = number / 10) % 10 ); + USER_INTERFACE_STATE.message[4] = digitToSevenSegmentPattern( (number = number / 10) % 10 ); + + setMessage(&USER_INTERFACE_STATE); + break; + + case UI_STATE_CANCEL: + userInterfaceState = UI_STATE_NORMAL; + + this->messageTime = 0; + + default: + userInterfaceState = UI_STATE_NORMAL; + } // switch + } // SET + } // power on + } // rpm is zero #ifdef IGNORE_ALL_KEYS_WHEN_RUNNING if( currentRpm == 0 ) @@ -175,17 +316,68 @@ void UserInterface :: loop( void ) #endif // IGNORE_ALL_KEYS_WHEN_RUNNING // these should only work when the power is on - if( this->core->isPowerOn() ) { + if( this->core->isPowerOn() ) + { // these keys can be operated when the machine is running - if( keys.bit.UP ) + switch (userInterfaceState) { - core->setFeed(feedTable->next()); - } - if( keys.bit.DOWN ) - { - core->setFeed(feedTable->previous()); - } - } + case UI_STATE_NORMAL: + +// if( keys.bit.UP ) +// { +// core->setFeed(feedTable->next()); +// } +// if( keys.bit.DOWN ) +// { +// core->setFeed(feedTable->previous()); +// } + + action = controlPanel->buttonStateMachine(keys.bit.UP, keys.bit.DOWN); + + if( action == BSM_INCREMENT ) + { + core->setFeed(feedTable->next()); + } + if( action == BSM_DECREMENT ) + { + core->setFeed(feedTable->previous()); + } + break; + + case UI_STATE_ADJ_BRT: + + action = controlPanel->buttonStateMachine(keys.bit.UP, keys.bit.DOWN); + + if( action == BSM_INCREMENT ) + { + controlPanel->increaseBrightness(); + USER_INTERFACE_STATE.message[7] = digitToSevenSegmentPattern(controlPanel->getBrightness()); + setMessage(&USER_INTERFACE_STATE); + } + if( action == BSM_DECREMENT ) + { + controlPanel->decreaseBrightness(); + USER_INTERFACE_STATE.message[7] = digitToSevenSegmentPattern(controlPanel->getBrightness()); + setMessage(&USER_INTERFACE_STATE); + } + +// if( keys.bit.UP ) +// { +// controlPanel->increaseBrightness(); +// USER_INTERFACE_STATE.message[7] = digitToSevenSegmentPattern(controlPanel->getBrightness()); +// setMessage(&USER_INTERFACE_STATE); +// } +// +// if( keys.bit.DOWN ) +// { +// controlPanel->decreaseBrightness(); +// USER_INTERFACE_STATE.message[7] = digitToSevenSegmentPattern(controlPanel->getBrightness()); +// setMessage(&USER_INTERFACE_STATE); +// } + + break; + } // switch + } // power is on #ifdef IGNORE_ALL_KEYS_WHEN_RUNNING } diff --git a/els-f280049c/UserInterface.h b/els-f280049c/UserInterface.h index d193914..7878ce1 100644 --- a/els-f280049c/UserInterface.h +++ b/els-f280049c/UserInterface.h @@ -31,6 +31,14 @@ #include "Core.h" #include "Tables.h" +#define UI_STATE_NORMAL 0 +#define UI_STATE_ADJ_BRT 1 +#define UI_STATE_LEADSCREW 2 +#define UI_STATE_uSTPS 3 +#define UI_STATE_STEPPER_RES 4 +#define UI_STATE_ENCODER_RES 5 +#define UI_STATE_CANCEL 6 + typedef struct MESSAGE { Uint16 message[8]; @@ -61,10 +69,14 @@ class UserInterface void setMessage(const MESSAGE *message); void overrideMessage( void ); + Uint16 userInterfaceState; + public: UserInterface(ControlPanel *controlPanel, Core *core, FeedTableFactory *feedTableFactory); void loop( void ); + + Uint16 static digitToSevenSegmentPattern(Uint16 x); }; #endif // __USERINTERFACE_H diff --git a/els-f280049c/main.cpp b/els-f280049c/main.cpp index 24c4872..fe28342 100644 --- a/els-f280049c/main.cpp +++ b/els-f280049c/main.cpp @@ -139,6 +139,9 @@ void main(void) // mark beginning of loop for debugging debug.begin2(); + // service heartbeat + debug.heartbeat(); + // service the user interface userInterface.loop();