├── StateMachine.png ├── README.md ├── Input └── src │ ├── header.h │ └── input.c ├── Display └── src │ ├── header.h │ └── display.c └── Controller └── src ├── header.h └── controller.c /StateMachine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NFestoso/QNX_State_Machine/HEAD/StateMachine.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QNX Real-Time State Machine 2 | State machine build in QNX real-time operating system. This state machine demonstrates multi-threading, namespaces, timers, and IPC using a pulse. 3 | 4 | ![State Machine](StateMachine.png) 5 | 6 | ## Build Environment 7 | - QNX Software Development Platform version 7.0 8 | - QNX SDP 7.0 x86-64 virtual machine 9 | - VMware Workstation Player 12.0 10 | 11 | ## Date Created 12 | November, 2018 13 | 14 | ## Author 15 | Nathan Festoso 16 | -------------------------------------------------------------------------------- /Input/src/header.h: -------------------------------------------------------------------------------- 1 | /* 2 | * header.h 3 | * 4 | * Created on: Nov 21, 2018 5 | * Author: Nathan Festoso 6 | */ 7 | 8 | #ifndef ASS2_HEADER_H_ 9 | #define ASS2_HEADER_H_ 10 | 11 | #define NUM_STATES 12 12 | typedef enum { 13 | READY = 0, 14 | LEFT_DOWN = 1, 15 | LEFT_UP = 2, 16 | RIGHT_DOWN = 3, 17 | RIGHT_UP = 4, 18 | ARMED = 5, 19 | PUNCH = 6, 20 | EXIT = 7, 21 | START = 8, 22 | STOP = 9, 23 | PAUSE = 10, 24 | EMERGENCY = 11 25 | } State; 26 | 27 | const char *inMessage[NUM_STATES] = { 28 | "", 29 | "ld", 30 | "lu", 31 | "rd", 32 | "ru", 33 | "", 34 | "", 35 | "s", 36 | "", 37 | "", 38 | "p", 39 | "es" 40 | }; 41 | 42 | const char *outMessage[NUM_STATES] = { 43 | "Ready...", 44 | "Left button down - press right button to arm press", 45 | "", 46 | "Right button down - press left button to arm press", 47 | "", 48 | "DANGER - Press is Armed! - Hold buttons for 2 seconds...", 49 | "Press Cutting Now", 50 | "Powering down...", 51 | "", 52 | "", 53 | "", 54 | "Emergency Stop!" 55 | }; 56 | 57 | #endif /* ASS2_HEADER_H_ */ 58 | -------------------------------------------------------------------------------- /Display/src/header.h: -------------------------------------------------------------------------------- 1 | /* 2 | * header.h 3 | * 4 | * Created on: Nov 21, 2018 5 | * Author: Nathan Festoso 6 | */ 7 | 8 | #ifndef ASS2_HEADER_H_ 9 | #define ASS2_HEADER_H_ 10 | 11 | #define NUM_STATES 12 12 | typedef enum { 13 | READY = 0, 14 | LEFT_DOWN = 1, 15 | LEFT_UP = 2, 16 | RIGHT_DOWN = 3, 17 | RIGHT_UP = 4, 18 | ARMED = 5, 19 | PUNCH = 6, 20 | EXIT = 7, 21 | START = 8, 22 | STOP = 9, 23 | PAUSE = 10, 24 | EMERGENCY = 11 25 | } State; 26 | 27 | const char *inMessage[NUM_STATES] = { 28 | "", 29 | "ld", 30 | "lu", 31 | "rd", 32 | "ru", 33 | "", 34 | "", 35 | "s", 36 | "", 37 | "", 38 | "p", 39 | "es" 40 | }; 41 | 42 | const char *outMessage[NUM_STATES] = { 43 | "Ready...", 44 | "Left button down - press right button to arm press", 45 | "", 46 | "Right button down - press left button to arm press", 47 | "", 48 | "DANGER - Press is Armed! - Hold buttons for 2 seconds...", 49 | "Press Cutting Now", 50 | "Powering down...", 51 | "", 52 | "", 53 | "", 54 | "Emergency Stop!" 55 | }; 56 | 57 | struct Machine{ 58 | State currentState; 59 | } typedef Machine_t; 60 | 61 | 62 | #endif /* ASS2_HEADER_H_ */ 63 | -------------------------------------------------------------------------------- /Controller/src/header.h: -------------------------------------------------------------------------------- 1 | /* 2 | * header.h 3 | * 4 | * Created on: Nov 21, 2018 5 | * Author: Nathan Festoso 6 | */ 7 | 8 | #ifndef ASS2_HEADER_H_ 9 | #define ASS2_HEADER_H_ 10 | 11 | #define NUM_STATES 12 12 | typedef enum { 13 | READY = 0, 14 | LEFT_DOWN = 1, 15 | LEFT_UP = 2, 16 | RIGHT_DOWN = 3, 17 | RIGHT_UP = 4, 18 | ARMED = 5, 19 | PUNCH = 6, 20 | EXIT = 7, 21 | START = 8, 22 | STOP = 9, 23 | PAUSE = 10, 24 | EMERGENCY = 11 25 | } State; 26 | 27 | const char *inMessage[NUM_STATES] = { 28 | "", 29 | "ld", 30 | "lu", 31 | "rd", 32 | "ru", 33 | "", 34 | "", 35 | "s", 36 | "", 37 | "", 38 | "p", 39 | "es" 40 | }; 41 | 42 | const char *outMessage[NUM_STATES] = { 43 | "Ready...", 44 | "Left button down - press right button to arm press", 45 | "", 46 | "Right button down - press left button to arm press", 47 | "", 48 | "DANGER - Press is Armed! - Hold buttons for 2 seconds...", 49 | "Press Cutting Now", 50 | "Powering down...", 51 | "", 52 | "", 53 | "", 54 | "Emergency Stop!" 55 | }; 56 | 57 | struct Machine{ 58 | State currentState; 59 | } typedef Machine_t; 60 | 61 | 62 | #endif /* ASS2_HEADER_H_ */ 63 | -------------------------------------------------------------------------------- /Display/src/display.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "header.h" 13 | 14 | /* 15 | * Main method: 16 | * 17 | * This function handles output messages to user when it receives a state change from the controller. 18 | */ 19 | int main(void) { 20 | // Create channel 21 | name_attach_t *display; 22 | display = name_attach(NULL, "display", 0); 23 | if (display == NULL){ 24 | perror("Error: name_attach failed."); 25 | exit (EXIT_FAILURE); 26 | } 27 | 28 | State currentState = READY; 29 | int rcvid; 30 | while(1){ 31 | // Receive state change 32 | if((rcvid = MsgReceive(display->chid, ¤tState, sizeof(currentState), NULL)) == -1){ 33 | printf("Error: MsgReveice failed"); 34 | name_detach(display, NAME_FLAG_DETACH_SAVEDPP); 35 | exit(EXIT_FAILURE); 36 | } 37 | 38 | // Print message 39 | printf("%s\n", outMessage[currentState]); 40 | 41 | // respond to controller 42 | MsgReply (rcvid, EOK, ¤tState, sizeof(currentState)); 43 | if(currentState == EXIT || currentState == EMERGENCY) break; 44 | } 45 | 46 | // Terminate 47 | printf("Exiting Display...\n"); 48 | name_detach(display, NAME_FLAG_DETACH_SAVEDPP); 49 | return EXIT_SUCCESS; 50 | } 51 | -------------------------------------------------------------------------------- /Input/src/input.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "header.h" 13 | 14 | /* 15 | * Main method: 16 | * 17 | * This function runs a command prompt for user to step through the state machine. 18 | * Upon error, 's', or 'es' command, this process will terminate. 19 | */ 20 | int main(void) { 21 | // Connect to named end point 22 | int server_coid = name_open("controller", 0); 23 | if(server_coid == -1) { 24 | printf("Error: Cannot name_open"); 25 | return EXIT_FAILURE; 26 | } 27 | 28 | State currentState = READY; 29 | // Initialize controllers 30 | if(MsgSend(server_coid, ¤tState, sizeof(currentState), NULL, 0) == -1){ 31 | printf("Error: MsgSend failed.\n"); 32 | name_close(server_coid); 33 | exit(EXIT_FAILURE); 34 | } 35 | 36 | // Run machine 37 | char command[3]; 38 | while(1){ 39 | // Prompt for next event 40 | printf("\nEnter the input (ld, lu, rd, ru, p, s, es):\n"); 41 | scanf("%s", &command, &pause); 42 | 43 | // assign new state 44 | int found = 0; 45 | for(int i=0; i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "header.h" 14 | 15 | #define MY_PULSE_CODE _PULSE_CODE_MINAVAIL 16 | 17 | typedef union { 18 | struct _pulse pulse; 19 | } my_message_t; 20 | 21 | int emergencyStop = -1; 22 | int server_coid; 23 | int released = -1; 24 | 25 | void * doTimer(void *c) { 26 | struct sigevent event; 27 | struct itimerspec itime; 28 | timer_t timer_id; 29 | int chid; 30 | int rcvid; 31 | my_message_t msg; 32 | 33 | chid = ChannelCreate(0); 34 | 35 | event.sigev_notify = SIGEV_PULSE; 36 | event.sigev_coid = ConnectAttach(ND_LOCAL_NODE, 0, 37 | chid, 38 | _NTO_SIDE_CHANNEL, 0); 39 | event.sigev_priority = SchedGet( 0, 0, NULL ); 40 | event.sigev_code = MY_PULSE_CODE; 41 | timer_create(CLOCK_REALTIME, &event, &timer_id); 42 | 43 | State state = (int) c; 44 | 45 | long seconds = ((state == PUNCH) ? 2 : 1); 46 | 47 | printf("Waiting for %d seconds..\n", seconds); 48 | 49 | itime.it_value.tv_sec = seconds; 50 | /* 500 million nsecs = .5 secs */ 51 | itime.it_value.tv_nsec = 500000000; 52 | itime.it_interval.tv_sec = 1; 53 | /* 500 million nsecs = .5 secs */ 54 | itime.it_interval.tv_nsec = 500000000; 55 | timer_settime(timer_id, 0, &itime, NULL); 56 | 57 | for (;;) { 58 | rcvid = MsgReceive(chid, &msg, sizeof(msg), NULL); 59 | if (rcvid == 0) { /* we got a pulse */ 60 | if (msg.pulse.code == MY_PULSE_CODE) { 61 | timer_delete(timer_id); 62 | break; 63 | } 64 | } 65 | } 66 | 67 | if (released > 0) { 68 | printf("One of the buttons were released!\n"); 69 | return NULL; 70 | } 71 | 72 | if (emergencyStop > 0) { 73 | return NULL; 74 | } 75 | 76 | if (MsgSend(server_coid, &state, sizeof (state) + 1, NULL, 0) == -1) { 77 | fprintf(stderr, "Error during MsgSend\n"); 78 | perror(NULL); 79 | } 80 | return NULL; 81 | } 82 | 83 | void startTimer(State nextState) { 84 | pthread_create (NULL, NULL, doTimer, (void *)nextState); 85 | } 86 | 87 | int main(void) { 88 | // Attach to device 89 | name_attach_t * controllerDevice = name_attach(NULL, "controller", 0); 90 | if (controllerDevice == NULL) { 91 | printf("Error: Cannot name_attach\n"); 92 | return EXIT_FAILURE; 93 | } 94 | 95 | if ((server_coid = name_open("display", 0)) == -1) { 96 | printf("Error: name open failed\n"); 97 | return EXIT_FAILURE; 98 | } 99 | 100 | State rmsg; 101 | State reply = START; 102 | State response; 103 | State statenum = START; // Beginning state 104 | 105 | int rcvid; 106 | 107 | while (1) 108 | { 109 | if ((rcvid = MsgReceive(controllerDevice -> chid, &rmsg, sizeof(rmsg), NULL)) < 0) { 110 | if (emergencyStop < 0) printf("Error: Receiving pulse\n"); 111 | return EXIT_FAILURE; 112 | } 113 | 114 | switch (rmsg) 115 | { 116 | case LEFT_DOWN: 117 | printf("Left down\n"); 118 | if (statenum == RIGHT_DOWN) statenum = ARMED; 119 | else statenum = LEFT_DOWN; 120 | released = -1; // button is pressed 121 | break; 122 | case RIGHT_DOWN: 123 | printf("Right down\n"); 124 | if (statenum == LEFT_DOWN) statenum = ARMED; 125 | else statenum = RIGHT_DOWN; 126 | released = -1; // button is pressed 127 | break; 128 | case LEFT_UP: 129 | printf("Left up\n"); 130 | statenum = LEFT_UP; 131 | released = 1; // button is released 132 | break; 133 | case RIGHT_UP: 134 | printf("Right up\n"); 135 | statenum = RIGHT_UP; 136 | released = 1; // button is released 137 | break; 138 | case READY: 139 | printf("Ready\n"); 140 | statenum = READY; 141 | sleep(3); 142 | break; 143 | case EMERGENCY: 144 | printf("Emergency Stop\n"); 145 | emergencyStop = 1; 146 | statenum = EXIT; 147 | break; 148 | case EXIT: 149 | printf("Exit\n"); 150 | statenum = rmsg; 151 | break; 152 | default: 153 | statenum = -1; 154 | } 155 | // assign a new state to the reply 156 | reply = statenum; 157 | // reply to the input micro-service 158 | MsgReply (rcvid, EOK, &reply, sizeof (reply)); 159 | // send a state to the display 160 | if ((statenum > 0) && (statenum != LEFT_UP) && (statenum != RIGHT_UP)) { 161 | // send a message to the display 162 | rmsg = statenum; 163 | if (MsgSend(server_coid, &rmsg, sizeof (rmsg) + 1, &response, sizeof (response)) == -1) { 164 | fprintf(stderr, "Error during MsgSend\n"); 165 | perror(NULL); 166 | } 167 | } 168 | // exit the process and send a kill packet to the display service 169 | if (statenum == EXIT) sleep(5); 170 | else if (statenum == ARMED) { 171 | rmsg = PUNCH; 172 | startTimer(rmsg); 173 | statenum = READY; // go back to start 174 | } 175 | if (statenum == EXIT) break; 176 | } 177 | 178 | name_close(server_coid); 179 | name_detach(controllerDevice, NAME_FLAG_DETACH_SAVEDPP); 180 | printf("Controller exited.\n"); 181 | return EXIT_SUCCESS; 182 | } 183 | --------------------------------------------------------------------------------