/** * @brief Timer handler procedure * * This is not a realistic workload and it is a demonstration code only. * * It runs couple thousand of iterations and each iteration is randomizing * memory locations to run a number of arithmetic operations on them. * * @param sig UNUSED * @param si UNUSED * @param uc UNUSED */ static void timer_handler(int sig, siginfo_t *si, void *uc) { const int num_iterations = 5000; int *p = (int *) timer_data_ptr; const size_t sz = timer_data_size / sizeof(int); int m; (void) (sig); (void) (si); (void) (uc); tsc_start(&timer_prof); /* START - "latency sensitive" code */ for (m = 0; m < num_iterations; m++) { const size_t stride = 5; const int idx0 = timer_rand() % (sz - stride); const int idx1 = timer_rand() % (sz - stride); size_t n; for (n = 0; n < stride; n++) p[idx0 + n] = 2 * p[idx1 + n] + p[idx0 + n]; } /* END - "latency sensitive" code */ tsc_end(&timer_prof, 1); }
/** * @brief Set up the timer * * The timer expiration is delivered as a signal, * the signal handler is timer_handler() above. * * @param freq_nanosecs timer frequency in nanoseconds * * @return Operation status * @retval 0 OK * @retval <0 error */ static int init_timer(const long long freq_nanosecs) { sigset_t mask; struct sigaction sa; struct sigevent sev; struct itimerspec its; /* this will initialize the table with random numbers */ (void) timer_rand(); /* Block timer signal temporarily */ sigemptyset(&mask); sigaddset(&mask, SIGRTMIN); if (sigprocmask(SIG_SETMASK, &mask, NULL) == -1) { printf("Error masking signal!\n"); return -1; } /* set signal handler */ sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = timer_handler; sigemptyset(&sa.sa_mask); if (sigaction(SIGRTMIN, &sa, NULL) == -1) { printf("Error setting signal handler!\n"); return -1; } /* Create the timer */ sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = SIGRTMIN; sev.sigev_value.sival_ptr = &timerid; if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1) { printf("Error creating the timer!\n"); return -1; } /* Start the timer */ its.it_value.tv_sec = freq_nanosecs / 1000000000; its.it_value.tv_nsec = freq_nanosecs % 1000000000; its.it_interval.tv_sec = freq_nanosecs / 1000000000; its.it_interval.tv_nsec = freq_nanosecs % 1000000000; if (timer_settime(timerid, 0, &its, NULL) == -1) { printf("Error starting the timer!\n"); return -1; } /* Unlock the timer signal */ if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1) { printf("Error unmasking signal!\n"); return -1; } return 0; }
/** * @brief Step through the main stages in the code. * @return Void */ void md14_main() { switch(md14_next_state) { case MD14_STATE_INTRO: lang_fileset = LANG_FILESET; mode_fileset = MODE_FILESET; play_mp3(MODE_FILESET, "WELC"); md14_next_state = MD14_STATE_LVLSEL; srand(timer_rand()); break; case MD14_STATE_LVLSEL: md14_last_dot = create_dialog("LVL3", (DOT_1 | DOT_2 | DOT_3)); if (md14_last_dot == NO_DOTS) break; switch (md14_last_dot) { case '1': play_mp3(LANGUAGE, "EASY"); strings_to_wordlist(easy, ARRAYLEN(easy), &md14_dict); break; case '2': play_mp3(LANGUAGE, "MED"); strings_to_wordlist(medium, ARRAYLEN(medium), &md14_dict); break; case '3': play_mp3(LANGUAGE, "HARD"); strings_to_wordlist(hard, ARRAYLEN(hard), &md14_dict); break; } print_words_in_list(&md14_dict); play_mp3(MODE_FILESET, "INST"); md14_next_state = MD14_STATE_GENQUES; break; case MD14_STATE_GENQUES: md14_reset(); get_next_word_in_wordlist(&md14_dict, &md14_chosen_word); log_msg("[MD14] Next word: %s\n\r", md14_chosen_word->name); md14_next_state = MD14_STATE_PROMPT; break; case MD14_STATE_PROMPT: play_mp3(LANGUAGE, "SPEL"); speak_word(md14_chosen_word); md14_next_state = MD14_STATE_INPUT; break; case MD14_STATE_INPUT: md14_cell = get_cell(); if (md14_cell == NO_DOTS) { break; } md14_cell_pattern = GET_CELL_PATTERN(md14_cell); md14_cell_control = GET_CELL_CONTROL(md14_cell); switch (md14_cell_control) { case WITH_ENTER: md14_user_cell.pattern = md14_cell_pattern; md14_next_state = MD14_STATE_CHECK; log_msg("[MD14] Checking answer\n\r"); break; case WITH_LEFT: md14_next_state = MD14_STATE_REPROMPT; break; case WITH_RIGHT: md14_next_state = MD14_STATE_GENQUES; break; case WITH_CANCEL: break; } break; case MD14_STATE_CHECK: md14_speak_inputted_cell(); get_next_cell_in_word(md14_chosen_word, &md14_curr_cell); log_msg("Target cell: %x, inputted cell: %x.\n\r", md14_curr_cell.pattern, md14_user_cell.pattern); if (cell_equals(&md14_curr_cell, &md14_user_cell)) { if (md14_chosen_word->curr_letter == md14_chosen_word->num_letters - 1) { // done md14_correct_answer(); md14_next_state = MD14_STATE_GENQUES; } else {// correct but not done play_mp3(LANGUAGE, "GOOD"); play_mp3(LANGUAGE, "NLET"); md14_curr_mistakes = 0; md14_next_state = MD14_STATE_INPUT; } } else { md14_incorrect_answer(); md14_next_state = MD14_STATE_REPROMPT; } break; case MD14_STATE_REPROMPT: if (md14_curr_mistakes >= MAX_INCORRECT_GUESS) { play_mp3(LANGUAGE, "PRSS"); char* letter_name = get_eng_letter_name_by_cell(&md14_curr_cell); play_mp3(LANGUAGE, letter_name); if (md14_curr_mistakes >= MAX_INCORRECT_GUESS + 1) play_pattern(md14_curr_cell.pattern); } else { play_mp3(LANGUAGE, "SPEL"); speak_word(md14_chosen_word); if (md14_chosen_word->curr_glyph > -1) {// not at beginning of word play_mp3(MODE_FILESET, "SPLS"); speak_letters_so_far(md14_chosen_word); play_mp3(LANGUAGE, "NLET"); } } md14_next_state = MD14_STATE_INPUT; break; default: break; } }
/** * @brief Step through the main stages in the code. * @return Void */ void md14_main() { switch(md14_next_state) { case MD14_STATE_INTRO: PRINTF("In intro state\n\r"); play_mp3(MODE_FILESET, "WELC"); lang_fileset = "ENG_"; mode_fileset = "MD14"; md14_next_state = MD14_STATE_LVLSEL; srand(timer_rand()); break; case MD14_STATE_LVLSEL: md14_last_dot = create_dialog("LVLS", (DOT_1 | DOT_2)); switch (md14_last_dot) { case NO_DOTS: break; case '1': play_mp3(LANGUAGE, "EASY"); strings_to_wordlist(easy, ARRAYLEN(easy), &md14_dict); print_words_in_list(&md14_dict); play_mp3(MODE_FILESET, "INST"); md14_next_state = MD14_STATE_GENQUES; break; case '2': play_mp3(LANGUAGE, "HARD"); strings_to_wordlist(medium, ARRAYLEN(medium), &md14_dict); print_words_in_list(&md14_dict); play_mp3(MODE_FILESET, "INST"); md14_next_state = MD14_STATE_GENQUES; break; // todo: add case 3; figure out too-long words default: play_mp3(LANGUAGE, "INVP"); PRINTF("Invalid entry."); break; } break; case MD14_STATE_GENQUES: PRINTF("In genques state\n\r"); md14_curr_mistakes = 0; get_next_word_in_wordlist(&md14_dict, &md14_chosen_word); sprintf(dbgstr, "[MD14] Next word: %s\n\r", md14_chosen_word->name); PRINTF(dbgstr); md14_next_state = MD14_STATE_PROMPT; break; case MD14_STATE_PROMPT: PRINTF("In prompt state\n\r"); play_mp3(LANGUAGE, "SPEL"); speak_word(md14_chosen_word); md14_next_state = MD14_STATE_INPUT; break; case MD14_STATE_INPUT: md14_cell = get_cell(); if (md14_cell == NO_DOTS) { break; } md14_cell_pattern = GET_CELL_PATTERN(md14_cell); md14_cell_control = GET_CELL_CONTROL(md14_cell); switch (md14_cell_control) { case WITH_ENTER: md14_user_cell.pattern = md14_cell_pattern; md14_next_state = MD14_STATE_CHECK; PRINTF("[MD14] Checking answer\n\r"); break; case WITH_LEFT: md14_next_state = MD14_STATE_REPROMPT; break; case WITH_RIGHT: stats(); md14_next_state = MD14_STATE_GENQUES; break; case WITH_CANCEL: break; } break; case MD14_STATE_CHECK: get_next_cell_in_word(md14_chosen_word, &md14_curr_cell); sprintf(dbgstr, "In check state. Current cell: %x, user cell: %x.\n\r", md14_curr_cell.pattern, md14_user_cell.pattern); PRINTF(dbgstr); if (cell_equals(&md14_curr_cell, &md14_user_cell)) { md14_curr_mistakes = 0; if (md14_chosen_word->curr_letter == md14_chosen_word->num_letters - 1) { // done correct_answer(); md14_next_state = MD14_STATE_GENQUES; } else {// correct but not done play_mp3(LANGUAGE, "GOOD"); play_mp3(LANGUAGE, "NLET"); md14_next_state = MD14_STATE_INPUT; } } else {// incorrect letter incorrect_answer(); // @todo mark invalid letters invalid md14_next_state = MD14_STATE_REPROMPT; } break; case MD14_STATE_REPROMPT: PRINTF("In reprompt state\n\r"); if (md14_curr_mistakes >= MAX_INCORRECT_GUESS) { play_mp3(LANGUAGE, "PRSS"); play_pattern(md14_curr_cell.pattern); } else { play_mp3(LANGUAGE, "SPEL"); speak_word(md14_chosen_word); if (md14_chosen_word->curr_glyph > -1) {// not at beginning of word play_mp3(MODE_FILESET, "SPLS"); speak_letters_so_far(md14_chosen_word); } } md14_next_state = MD14_STATE_INPUT; break; default: break; } }