/** * List all programs stored on the terminal host over the serial line. * DIR */ void cmd_dir(char *) { unsigned char first = 1; acia_puts("*DIR\n"); for(;;) { acia_puts("*NEXT\n"); acia_gets(readline_buffer, 255); if (strncmp("*EOF", readline_buffer, 4) == 0) { break; } else { if (first) { first = 0; } else { do { if (is_interrupted()) { acia_puts("*BREAK\n"); print_interrupted(); return; } keys_update(); } while (keys_get_code() == KEY_NONE); } lcd_puts(readline_buffer); lcd_put_newline(); } } print_ready(); }
/** * List the program. * LiST [<from>] */ void cmd_list(char *args) { unsigned char range = 0; unsigned int from_number; unsigned int to_number; program_line *line; unsigned char first = 1; if (isdigit(args[0])) { sscanf(args, "%u", &from_number); to_number = from_number; range = 1; } line = program; while (line) { if (range == 0 || (line->number >= from_number && line->number <= to_number)) { if (first) { first = 0; } else { do { if (is_interrupted()) { print_interrupted(); return; } keys_update(); } while (keys_get_code() == KEY_NONE); } sprintf(print_buffer, "%u %s %s\n", line->number, keywords[line->command], line->args); lcd_puts(print_buffer); } line = line->next; } print_ready(); }
/** * Load a program by reading it from the terminal program over the serial line. * LOAD "<filename>" */ void cmd_load(char *args) { char *filename; if (parse_string_expression(args, &filename)) { cmd_new(0); lcd_puts("Loading..."); acia_puts("*LOAD \""); acia_puts(filename); acia_puts("\"\n"); for(;;) { acia_puts("*NEXT\n"); acia_gets(readline_buffer, 255); if (strncmp("*EOF", readline_buffer, 4) == 0) { break; } else if (strncmp("!NOTFOUND", readline_buffer, 9) == 0) { lcd_put_newline(); syntax_error_msg("File not found"); break; } else { lcd_putc('.'); interpret(readline_buffer); } } if (! error) { lcd_put_newline(); print_ready(); } } else { syntax_error_invalid_argument(); } }
/** * Run the program. * RUN */ void cmd_run(char *) { unsigned char command; error = 0; running = 1; current_line = program; current_line_changed = 0; while (current_line) { if (is_interrupted()) { print_interrupted(); lcd_cursor_blink(); break; } command = current_line->command; command_functions[command](current_line->args); if (error) { break; } if (current_line_changed) { current_line_changed = 0; if (! current_line) { break; } } else { current_line = current_line->next; } } print_ready(); }
/** * Terminate the program. * END */ void cmd_end(char *) { if (! current_line) { print_ready(); } current_line = 0; current_line_changed = 1; }
/** * Assign a value to a variable or delete the variable if no assignment is given. * List all variables if no arguments are given. */ void cmd_let(char *args) { unsigned char token; unsigned int var_name; unsigned char var_type; skip_whitespace(args); if (*args == '\0') { print_all_variables(); print_ready(); return; } if (args = parse_variable(args, &var_name, &var_type)) { if (next_token(args) == TOKEN_ASSIGN) { token = next_token(args); args = consume_token(args, token); switch (var_type) { case VAR_TYPE_INTEGER: { int value; if (parse_number_expression(args, &value)) { create_variable(var_name, var_type, &value); } break; } case VAR_TYPE_STRING: { char *value; if (parse_string_expression(args, &value)) { create_variable(var_name, var_type, value); } break; } } } else { if (*args == '\0') { delete_variable(var_name, var_type); } } } else { syntax_error(); } }
/** * Save a program by sending it to the terminal program over the serial line. * SAVE "<filename>" */ void cmd_save(char *args) { char *filename; if (parse_string_expression(args, &filename)) { program_line *line = program; lcd_puts("Saving..."); acia_puts("*SAVE \""); acia_puts(filename); acia_puts("\"\n"); while (line) { sprintf(print_buffer, "%u %s %s\n", line->number, keywords[line->command], line->args); acia_puts(print_buffer); line = line->next; lcd_putc('.'); } acia_puts("*EOF\n"); lcd_put_newline(); print_ready(); } else { syntax_error_invalid_argument(); } }
/** * Delete all variables. */ void cmd_clear(char *) { clear_variables(); print_ready(); }
/** * @brief: c UART0 IRQ Handler */ void uart_iprocess(void) { uint8_t IIR_IntId; // Interrupt ID from IIR LPC_UART_TypeDef *pUart = (LPC_UART_TypeDef *)LPC_UART0; __disable_irq(); #ifdef DEBUG_0 //uart1_put_string("Entering c_UART0_IRQHandler\n\r"); #endif // DEBUG_0 /* Reading IIR automatically acknowledges the interrupt */ IIR_IntId = (pUart->IIR) >> 1 ; // skip pending bit in IIR if (IIR_IntId & IIR_RDA) { // Receive Data Avaialbe /* read UART. Read RBR will clear the interrupt */ // Perform a 'context switch' PCB *old_proc = gp_current_process; gp_current_process = k_get_process(PID_UART_IPROC); g_char_in = pUart->RBR; #ifdef DEBUG_0 uart1_put_string("Reading a char = "); uart1_put_char(g_char_in); uart1_put_string("\n\r"); #endif // DEBUG_0 // process the character. If it is a hotkey, call the corresponding function // If we are reading, fall through to default and add to the command buffer switch (g_char_in) { case '\r': case '\n': if (g_is_reading) { // We've finished reading a command, send it to the KCD process MSG_BUF *message; g_is_reading = 0; strcpy("\n\r", (char *)(g_in_buffer + g_in_index)); if (is_memory_available()) { message = k_request_memory_block(); message->mtype = DEFAULT; strcpy((char *)g_in_buffer, message->mtext); k_send_message(PID_KCD, message); } g_in_index = 0; } break; case '%': if (!g_is_reading) { // Start reading a command g_is_reading = 1; g_in_index = 1; g_in_buffer[0] = '%'; break; } #if defined(DEBUG_0) && defined(_DEBUG_HOTKEYS) case READY_Q_COMMAND: if (!g_is_reading) { print_ready(); break; } case MEMORY_Q_COMMAND: if (!g_is_reading) { print_mem_blocked(); break; } case RECEIVE_Q_COMMAND: if (!g_is_reading) { print_receive_blocked(); break; } case MESSAGE_COMMAND: if (!g_is_reading) { print_messages(); break; } #endif /* DEBUG HOTKEYS */ default: if (g_is_reading) { // TODO: check bounds g_in_buffer[g_in_index++] = g_char_in; } } gp_current_process = old_proc; } else if (IIR_IntId & IIR_THRE) { /* THRE Interrupt, transmit holding register becomes empty */ // Check for messages and load the buffer // Perform a 'context switch' to the i-process MSG_BUF *message; PCB *old_proc = gp_current_process; gp_current_process = k_get_process(PID_UART_IPROC); // Don't block waiting for a message while (is_message(PID_UART_IPROC)) { int sender = PID_CRT; char *c; // Receive message and copy it to the buffer message = k_receive_message(&sender); c = message->mtext; //dprintf("Copying message to buffer: %s\n\r", message->mtext); if (*c != '\0') { do { g_out_buffer[g_out_end] = *c; g_out_end = (g_out_end + 1) % OUTPUT_BUFF_SIZE; c++; } while (g_out_end != g_out_start && *c != '\0'); } k_release_memory_block(message); } // Check if there is something in the circular buffer if (g_out_start != g_out_end) { g_char_out = g_out_buffer[g_out_start]; pUart->THR = g_char_out; g_out_start = (g_out_start + 1) % OUTPUT_BUFF_SIZE; } else { // nothing to print, disable the THRE interrupt pUart->IER ^= IER_THRE; // toggle (disable) the IER_THRE bit } gp_current_process = old_proc; } else { /* not implemented yet */ #ifdef DEBUG_0 //uart1_put_string("Should not get here!\n\r"); #endif // DEBUG_0 __enable_irq(); return; } __enable_irq(); }
static void update_state(void){ static utime_t fault_song = 0; static utime_t diag_last = 0; static int8_t diag_counter = 0; int sw = get_switch(); int bn = get_button(); blinky_override = 0; switch( inv_state ){ case INV_STATE_OFF: set_led_green(0); if( sw ){ // switch was turned on ondelay_until = get_time() + ONDELAY; inv_state = INV_STATE_ONDELAY; blinky_override = 1; set_led_white(255); play(ivolume, "c+3"); // debounce delay printbig("STARTING...\n"); syslog("switch on"); } break; case INV_STATE_ONDELAY: if( !sw ){ // switch was turned off inv_state = INV_STATE_OFF; play(ivolume, "a-3"); diag_counter ++; diag_last = get_time(); printbig("OFF\n"); usleep(500000); print_ready(); syslog("canceled"); }else if( get_time() >= ondelay_until ){ // countdown finished set_led_green( 255 ); inv_state = INV_STATE_ONDELAY2; diag_counter = 0; play(ivolume, "b"); printbig("ACTIVE\n"); syslog("ac active"); }else{ // flash + chirp; 2Hz blinky_override = 1; set_led_green(127); set_led_white(0); play(ivolume, "b+5>>"); set_led_green(0); set_led_white(64); usleep(437500); // reset the clock if Vi drops below 300 (per the spec) if( s_vi._curr < MIN_VI_SOFT ){ ondelay_until = get_time() + ONDELAY; } } break; case INV_STATE_ONDELAY2: // will move to running at next zero-xing break; case INV_STATE_RUNNING: set_led_green( 127 ); if( !sw ){ // switch was turned off // quickly bring VH down, and stop at zero-xing shutdown_until = get_time() + OFFDELAY; inv_state = INV_STATE_SHUTTINGDOWN; play(ivolume, "a-3"); // debounce syslog("switch off"); } break; case INV_STATE_SHUTTINGDOWN: set_led_green(255); if( get_time() >= shutdown_until ){ if( sw ){ // wild switch flipping inv_state = INV_STATE_FAULTEDOFF; fault_song = 0; fault_reason = "SWITCH ERR"; syslog("switch fault"); }else{ // done ramping down inv_state = INV_STATE_OFF; play(ivolume, "f-3"); printbig("AC OFF\n"); syslog("ac disabled"); usleep(500000); print_ready(); } } break; case INV_STATE_FAULTED: set_led_green(255); set_led_red(255); // we ramp down same as a shutdown, but end in faultedoff shutdown_until = get_time() + OFFDELAY; inv_state = INV_STATE_FAULTINGDOWN; printadj(fault_reason); break; case INV_STATE_FAULTINGDOWN: set_led_green(255); set_led_red(255); if( get_time() >= shutdown_until ){ inv_state = INV_STATE_FAULTEDOFF; fault_song = 0; syslog("ac disabled (fault)"); } break; case INV_STATE_FAULTEDOFF: set_led_green(0); set_led_red(255); if( !sw ){ // switch turned off, resume normal operation inv_state = INV_STATE_OFF; play(ivolume, "f-3"); set_led_red(0); print_ready(); }else if( get_time() >= fault_song ){ // periodically, sing printadj(fault_reason); play(128, "t150[4 d+3d-3]"); fault_song = get_time() + FAULTSONGT; } break; case INV_STATE_DIAG: menu(&guitop); inv_state = INV_STATE_OFF; print_ready(); break; case INV_STATE_TEST: break; } if( diag_last && diag_last + 5000000 < get_time() ){ diag_counter = 0; diag_last = 0; } // toggle switch rapidly, or toggle switch once + press button if( (diag_mode != 2) && ((diag_counter >= 5) || (bn && diag_counter)) ){ inv_state = INV_STATE_DIAG; diag_counter = 0; printbig("DIAG MODE\n"); syslog("diag mode"); play(ivolume, "g4e4f4f-3"); // ... } }