// update - updates led according to timed_updated. Should be called at 50Hz void Buzzer::update() { // return immediately if disabled if (!AP_Notify::flags.external_leds) { return; } // reduce 50hz call down to 10hz _counter++; if (_counter < 5) { return; } _counter = 0; // complete currently played pattern if (_pattern != NONE) { _pattern_counter++; switch (_pattern) { case SINGLE_BUZZ: // buzz for 10th of a second if (_pattern_counter == 1) { on(true); }else{ on(false); _pattern = NONE; } return; case DOUBLE_BUZZ: // buzz for 10th of a second switch (_pattern_counter) { case 1: on(true); break; case 2: on(false); break; case 3: on(true); break; case 4: default: on(false); _pattern = NONE; break; } return; case GPS_GLITCH: // play bethoven's 5th type buzz (three fast, one long) switch (_pattern_counter) { case 1: case 3: case 5: case 7: on(true); break; case 2: case 4: case 6: on(false); break; case 17: on(false); _pattern = NONE; break; default: // do nothing break; } return; case ARMING_BUZZ: // record start time if (_pattern_counter == 1) { _arming_buzz_start_ms = hal.scheduler->millis(); on(true); } else { // turn off buzzer after 3 seconds if (hal.scheduler->millis() - _arming_buzz_start_ms >= BUZZER_ARMING_BUZZ_MS) { _arming_buzz_start_ms = 0; on(false); _pattern = NONE; } } return; case BARO_GLITCH: // four fast tones switch (_pattern_counter) { case 1: case 3: case 5: case 7: case 9: on(true); break; case 2: case 4: case 6: case 8: on(false); break; case 10: on(false); _pattern = NONE; break; default: // do nothing break; } return; case EKF_BAD: // four tones getting shorter) switch (_pattern_counter) { case 1: case 5: case 8: case 10: on(true); break; case 4: case 7: case 9: on(false); break; case 11: on(false); _pattern = NONE; break; default: // do nothing break; } return; default: // do nothing break; } } // check if armed status has changed if (_flags.armed != AP_Notify::flags.armed) { _flags.armed = AP_Notify::flags.armed; if (_flags.armed) { // double buzz when armed play_pattern(ARMING_BUZZ); }else{ // single buzz when disarmed play_pattern(SINGLE_BUZZ); } return; } // check arming failed if (_flags.arming_failed != AP_Notify::flags.arming_failed) { _flags.arming_failed = AP_Notify::flags.arming_failed; if (_flags.arming_failed) { // arming failed buzz play_pattern(SINGLE_BUZZ); } return; } // check gps glitch if (_flags.gps_glitching != AP_Notify::flags.gps_glitching) { _flags.gps_glitching = AP_Notify::flags.gps_glitching; if (_flags.gps_glitching) { // gps glitch warning buzz play_pattern(GPS_GLITCH); } return; } // check gps failsafe if (_flags.failsafe_gps != AP_Notify::flags.failsafe_gps) { _flags.failsafe_gps = AP_Notify::flags.failsafe_gps; if (_flags.failsafe_gps) { // gps glitch warning buzz play_pattern(GPS_GLITCH); } return; } // check ekf bad if (_flags.ekf_bad != AP_Notify::flags.ekf_bad) { _flags.ekf_bad = AP_Notify::flags.ekf_bad; if (_flags.ekf_bad) { // ekf bad warning buzz play_pattern(EKF_BAD); } return; } // check baro glitch if (_flags.baro_glitching != AP_Notify::flags.baro_glitching) { _flags.baro_glitching = AP_Notify::flags.baro_glitching; if (_flags.baro_glitching) { // baro glitch warning buzz play_pattern(BARO_GLITCH); } return; } // if battery failsafe constantly single buzz if (AP_Notify::flags.failsafe_battery) { play_pattern(SINGLE_BUZZ); } }
/** * @brief Gets a line of raw cells from the user * @param void * @return bool - true if io_line is ready for further processing, false * otherwise */ bool get_line(void) { if (io_line_ready == false) { io_line_reset(); } if (io_user_abort) { return false; } char last_cell = get_cell(); char pattern = GET_CELL_PATTERN(last_cell); char control = GET_CELL_CONTROL(last_cell); // If last cell was empty, there's nothing to do so return false and wait if (last_cell == NO_DOTS) { return false; } // Otherwise, if cell was recorded, save it to io_line if (pattern) { io_line[io_line_cell_index] = pattern; } switch (control) { // ENTER - Advance cell, add EOT and return true case WITH_ENTER: io_line_next_cell(); io_line[io_line_cell_index] = END_OF_TEXT; io_line_ready = false; return true; break; /* RIGHT is used to switch to previous cell because Braille is entered this way */ // RIGHT - Select prev cell case WITH_RIGHT: play_mp3(lang_fileset, MP3_PREV_CELL); io_line_prev_cell(); if (!pattern) { play_pattern(io_line[io_line_cell_index]); } return false; break; /* LEFT is used to switch to next cell because Braille is entered this way */ // LEFT - Select next cell case WITH_LEFT: play_mp3(lang_fileset, MP3_NEXT_CELL); io_line_next_cell(); if (!pattern) { play_pattern(io_line[io_line_cell_index]); } return false; break; // CANCEL - Clear current cell case WITH_CANCEL: io_line_clear_cell(); return false; break; // Should not execute this code default: log_msg("[IO] Invalid control: %x\n\r", control); quit_mode(); return false; break; } }
// update - updates led according to timed_updated. Should be called at 50Hz void Buzzer::update() { // check for arming failed event if (AP_Notify::events.arming_failed) { // arming failed buzz play_pattern(SINGLE_BUZZ); } // reduce 50hz call down to 10hz _counter++; if (_counter < 5) { return; } _counter = 0; // complete currently played pattern if (_pattern != NONE) { _pattern_counter++; switch (_pattern) { case SINGLE_BUZZ: // buzz for 10th of a second if (_pattern_counter == 1) { on(true); }else{ on(false); _pattern = NONE; } return; case DOUBLE_BUZZ: // buzz for 10th of a second switch (_pattern_counter) { case 1: on(true); break; case 2: on(false); break; case 3: on(true); break; case 4: default: on(false); _pattern = NONE; break; } return; case ARMING_BUZZ: // record start time if (_pattern_counter == 1) { _arming_buzz_start_ms = AP_HAL::millis(); on(true); } else { // turn off buzzer after 3 seconds if (AP_HAL::millis() - _arming_buzz_start_ms >= BUZZER_ARMING_BUZZ_MS) { _arming_buzz_start_ms = 0; on(false); _pattern = NONE; } } return; case BARO_GLITCH: // four fast tones switch (_pattern_counter) { case 1: case 3: case 5: case 7: case 9: on(true); break; case 2: case 4: case 6: case 8: on(false); break; case 10: on(false); _pattern = NONE; break; default: // do nothing break; } return; case EKF_BAD: // four tones getting shorter) switch (_pattern_counter) { case 1: case 5: case 8: case 10: on(true); break; case 4: case 7: case 9: on(false); break; case 11: on(false); _pattern = NONE; break; default: // do nothing break; } return; default: // do nothing break; } } // check if armed status has changed if (_flags.armed != AP_Notify::flags.armed) { _flags.armed = AP_Notify::flags.armed; if (_flags.armed) { // double buzz when armed play_pattern(ARMING_BUZZ); }else{ // single buzz when disarmed play_pattern(SINGLE_BUZZ); } return; } // check ekf bad if (_flags.ekf_bad != AP_Notify::flags.ekf_bad) { _flags.ekf_bad = AP_Notify::flags.ekf_bad; if (_flags.ekf_bad) { // ekf bad warning buzz play_pattern(EKF_BAD); } return; } // if vehicle lost was enabled, starting beep if (AP_Notify::flags.vehicle_lost) { play_pattern(DOUBLE_BUZZ); } // if battery failsafe constantly single buzz if (AP_Notify::flags.failsafe_battery) { play_pattern(SINGLE_BUZZ); } }
/** * @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; } }