// return true is a command was read, false if a reset was requested uint8_t receive_cmd(char *cmd) { uint8_t num = 0, ch; dprintf(">"); *cmd = 0; for(; !check_reset();) { for(;!check_reset() && !serial_rx_nb(&ch);) idle(); if (check_reset()) return 0; serial_tx(ch); if (ch == '\r') { serial_tx('\n'); cmd[num] = 0; return 1; } cmd[num] = ch; num++; } return 0; }
void comm_test(void) { uint8_t ch; // disable all interrupts and just echo every character received. cli(); set_led_rgb(0, 255, 255); for(; !check_reset();) if (serial_rx_nb(&ch)) for(; !serial_tx_nb(ch) && !check_reset();) ; sei(); }
void id_conflict(void) { // we failed to get an address. stop and wait for a reset set_led_rgb(255, 0, 0); for(; !check_reset();) ; }
uint8_t address_exchange(void) { uint8_t ch; uint8_t id; set_led_rgb(0, 0, 255); id = eeprom_read_byte((uint8_t *)ee_pump_id_offset); if (id == 0 || id == 255) { // we failed to get a unique number for the pump. just stop. set_led_rgb(255, 0, 0); for(;;); } for(;;) { for(;;) { if (serial_rx_nb(&ch)) break; if (check_reset()) return 0xFF; } if (ch == 0xFF) break; if (ch == '?') serial_tx(id); } set_led_rgb(0, 255, 0); return id; }
/* Process any pending interrupt(s) after a group of parallel insns. */ void frv_process_interrupts (SIM_CPU *current_cpu) { SI NE_flags[2]; /* Need to save the pc here because writeback may change it (due to a branch). */ IADDR pc = CPU_PC_GET (current_cpu); /* Check for a reset before anything else. */ if (check_reset (current_cpu, pc)) return; /* First queue the writes for any accumulated NE flags. */ if (frv_interrupt_state.f_ne_flags[0] != 0 || frv_interrupt_state.f_ne_flags[1] != 0) { GET_NE_FLAGS (NE_flags, H_SPR_FNER0); NE_flags[0] |= frv_interrupt_state.f_ne_flags[0]; NE_flags[1] |= frv_interrupt_state.f_ne_flags[1]; SET_NE_FLAGS (H_SPR_FNER0, NE_flags); } /* If there is no interrupt pending, then perform parallel writeback. This may cause an interrupt. */ if (frv_interrupt_state.queue_index <= 0) frvbf_perform_writeback (current_cpu); /* If there is an interrupt pending, then process it. */ if (frv_interrupt_state.queue_index > 0) handle_interrupt (current_cpu, pc); }
void run_motor_timed(uint32_t duration) { uint32_t t; if (duration == 0) return; set_motor_speed(255, 1); for(t = 0; t < duration && !check_reset(); t++) _delay_ms(1); stop_motor(); }
/* * * Process the SCSI command * * Called with: * cdev -> Char dev file handle, * cdb -> SCSI Command buffer pointer, * struct vtl_ds -> general purpose data structure... Need better name * * Return: * SAM status returned in struct vtl_ds.sam_stat */ static void processCommand(int cdev, uint8_t *cdb, struct vtl_ds *dbuf_p, useconds_t pollInterval) { int err = 0; struct scsi_cmd _cmd; struct scsi_cmd *cmd; cmd = &_cmd; cmd->scb = cdb; cmd->scb_len = 16; /* fixme */ cmd->dbuf_p = dbuf_p; cmd->lu = &lunit; cmd->pollInterval = pollInterval; cmd->cdev = cdev; MHVTL_DBG_PRT_CDB(1, cmd); switch (cdb[0]) { case REPORT_LUNS: case REQUEST_SENSE: case MODE_SELECT: case INQUIRY: dbuf_p->sam_stat = SAM_STAT_GOOD; break; default: if (cmd->lu->online == 0) { sam_not_ready(E_OFFLINE, &dbuf_p->sam_stat); return; } if (check_reset(&dbuf_p->sam_stat)) return; } /* Skip main op code processing if pre-cmd returns non-zero */ if (cmd->lu->scsi_ops->ops[cdb[0]].pre_cmd_perform) err = cmd->lu->scsi_ops->ops[cdb[0]].pre_cmd_perform(cmd, NULL); if (!err) dbuf_p->sam_stat = cmd->lu->scsi_ops->ops[cdb[0]].cmd_perform(cmd); /* Post op code processing regardless */ if (cmd->lu->scsi_ops->ops[cdb[0]].post_cmd_perform) cmd->lu->scsi_ops->ops[cdb[0]].post_cmd_perform(cmd, NULL); return; }
/* * * Process the SCSI command * * Called with: * cdev -> Char dev file handle, * cdb -> SCSI Command buffer pointer, * struct vtl_ds -> general purpose data structure... Need better name * * Return: * SAM status returned in struct vtl_ds.sam_stat */ static void processCommand(int cdev, uint8_t *cdb, struct vtl_ds *dbuf_p, useconds_t pollInterval) { struct scsi_cmd _cmd; struct scsi_cmd *cmd; cmd = &_cmd; cmd->scb = cdb; cmd->scb_len = 16; /* fixme */ cmd->dbuf_p = dbuf_p; cmd->lu = &lunit; cmd->pollInterval = pollInterval; MHVTL_DBG_PRT_CDB(1, cmd); switch (cdb[0]) { case REPORT_LUNS: case REQUEST_SENSE: case MODE_SELECT: case INQUIRY: dbuf_p->sam_stat = SAM_STAT_GOOD; break; default: if (cmd->lu->online == 0) { mkSenseBuf(NOT_READY, E_OFFLINE, &dbuf_p->sam_stat); return; } if (check_reset(&dbuf_p->sam_stat)) return; } if (cmd->lu->scsi_ops->ops[cdb[0]].pre_cmd_perform) cmd->lu->scsi_ops->ops[cdb[0]].pre_cmd_perform(cmd, NULL); dbuf_p->sam_stat = cmd->lu->scsi_ops->ops[cdb[0]].cmd_perform(cmd); return; }
int main(void) { uint8_t id, rec, i, cs; color_t c; packet_t p; setup(); stop_motor(); sei(); for(i = 0; i < 5; i++) { set_led_rgb(255, 0, 255); _delay_ms(50); set_led_rgb(255, 255, 0); _delay_ms(50); } // get the current liquid level update_liquid_level(); for(;;) { cli(); g_reset = 0; g_current_sense_detected = 0; g_current_sense_num_cycles = 0; setup(); serial_init(); stop_motor(); set_led_rgb(0, 0, 255); sei(); id = address_exchange(); for(; !check_reset();) { rec = receive_packet(&p); if (rec == COMM_CRC_FAIL) continue; if (rec == COMM_RESET) break; if (rec == COMM_OK && (p.dest == DEST_BROADCAST || p.dest == id)) { // If we've detected a over current sitatuion, ignore all comamnds until reset cli(); cs = g_current_sense_detected; sei(); switch(p.type) { case PACKET_PING: break; case PACKET_SET_MOTOR_SPEED: if (!cs) set_motor_speed(p.p.uint8[0], p.p.uint8[1]); if (p.p.uint8[0] == 0) flush_saved_tick_count(0); break; case PACKET_TICK_DISPENSE: if (!cs) { dispense_ticks((uint16_t)p.p.uint32, 255); flush_saved_tick_count(0); } break; case PACKET_TIME_DISPENSE: if (!cs) { run_motor_timed(p.p.uint32); flush_saved_tick_count(0); } break; case PACKET_IS_DISPENSING: is_dispensing(); break; case PACKET_LIQUID_LEVEL: get_liquid_level(); break; case PACKET_UPDATE_LIQUID_LEVEL: update_liquid_level(); break; case PACKET_LED_OFF: set_led_pattern(LED_PATTERN_OFF); break; case PACKET_LED_IDLE: if (!cs) set_led_pattern(LED_PATTERN_IDLE); break; case PACKET_LED_DISPENSE: if (!cs) set_led_pattern(LED_PATTERN_DISPENSE); break; case PACKET_LED_DRINK_DONE: if (!cs) set_led_pattern(LED_PATTERN_DRINK_DONE); break; case PACKET_LED_CLEAN: if (!cs) set_led_pattern(LED_PATTERN_CLEAN); break; case PACKET_COMM_TEST: comm_test(); break; case PACKET_ID_CONFLICT: id_conflict(); break; case PACKET_SET_CS_THRESHOLD: g_current_sense_threshold = p.p.uint16[0]; break; case PACKET_SAVED_TICK_COUNT: get_saved_tick_count(); break; case PACKET_RESET_SAVED_TICK_COUNT: reset_saved_tick_count(); break; case PACKET_FLUSH_SAVED_TICK_COUNT: flush_saved_tick_count(1); break; case PACKET_GET_LIQUID_THRESHOLDS: get_liquid_thresholds(); break; case PACKET_SET_LIQUID_THRESHOLDS: set_liquid_thresholds(p.p.uint16[0], p.p.uint16[1]); break; case PACKET_TICK_SPEED_DISPENSE: if (!cs) { dispense_ticks(p.p.uint16[0], (uint8_t)p.p.uint16[1]); flush_saved_tick_count(0); } break; case PACKET_PATTERN_DEFINE: pattern_define(p.p.uint8[0]); break; case PACKET_PATTERN_ADD_SEGMENT: c.red = p.p.uint8[0]; c.green = p.p.uint8[1]; c.blue = p.p.uint8[2]; pattern_add_segment(&c, p.p.uint8[3]); break; case PACKET_PATTERN_FINISH: pattern_finish(); break; } } } } return 0; }
int mark(int argc, char *argv[], int retc, char *retv[] ) { int firstarg, cmd_is_ds, mark_ret_val, num_num_args, reset_flag, trace_flag; double mark_args[ 4 ]; /************************************************************************/ /* Check for `reset' as a keyword. Need to verify syntax. Three */ /* situations: "reset" used improperly; "reset" used correctly; */ /* no "reset" keyword. */ /************************************************************************/ reset_flag = check_reset( argc, argv ); if (reset_flag < 0) ABORT; else if (reset_flag > 0) { if (do_mark_reset() == 0) RETURN; else ABORT; } /************************************************************************/ /* Check for `trace' as a keyword. Situation is similar to `reset', */ /* except there is no file name and the returned value distinguishes */ /* `trace' as first from `trace' as last argument (the only 2 choices) */ /************************************************************************/ firstarg = 1; /* Skip command name */ trace_flag = check_trace( argc, argv ); if (trace_flag < 0) ABORT; if (trace_flag != 0) { if (retc > 2) { Werrprintf( "%s: cannot return more than 2 values when using `trace' keyword", argv[ 0 ] ); ABORT; } if (trace_flag == 1) /* Skip over 1st argument */ firstarg = 2; /* if it was `trace' */ else /* Otherwise it was the last */ argc--; /* argument, so reduce total */ } /* number of arguments by 1 */ /************************************************************************/ /* Extract numeric values, number of numeric values. The `mark' */ /* command accepts 0, 1, 2 or 4 such arguments. If `num_vals_args' */ /* returns -1, the subroutine has already posted an error message. */ /************************************************************************/ num_num_args = num_vals_args( firstarg, argc, argv, &mark_args[ 0 ], 4 ); if (num_num_args < 0) ABORT; else if (num_num_args == 3 || num_num_args > 4) { Werrprintf( "%s: incorrect number of numeric arguments", argv[ 0 ] ); ABORT; } /************************************************************************/ /* Get the current graphics command to establish if DS was the last */ /* such command executed. In that case, we perform a 1D operation */ /* unless MARK was called with 4 numeric arguments. */ /* */ /* Abort if current graphics command is not DS or DCONI. Add checks */ /* for other display commands (DCON, DPCON, etc.) here if required. */ /************************************************************************/ cmd_is_ds = WgraphicsdisplayValid( "ds" ); if ( !cmd_is_ds && !WgraphicsdisplayValid( "dconi" ) && num_num_args == 0 ) { Werrprintf( "%s: requires arguments when no data displayed", argv[ 0 ] ); ABORT; } /************************************************************************/ /* `init2d' subroutine defines `d2flag' and many other important */ /* variables. First argument instructs `init2d' to set "reverse" */ /* flag if trace = "f1". Second argument instructs `init2d' to */ /* prepare chart variables for displaying data. */ /************************************************************************/ if (init2d( 1, 1 )) ABORT; /************************************************************************/ /* Now that `d2flag' is defined, check on 4 more error conditions: */ /* A. 2D data is present, last command not `ds', 1 numeric argument */ /* and no `trace' keyword. */ /* B. No 2D data present and 4 numeric arguments entered. */ /* C. No 2D data present and the `trace' keyword was used. */ /* D. No 2D data present and command returns more than 2 values. */ /************************************************************************/ if (d2flag) { if (trace_flag == 0 && cmd_is_ds == 0 && num_num_args == 1) { Werrprintf( "%s: 'trace' keyword required with 2D data and 1 numeric argument", argv[ 0 ] ); ABORT; } } else { /* No 2D data */ if (num_num_args == 4) { Werrprintf( "%s: Cannot have 4 numeric arguments with 1D data", argv[ 0 ] ); ABORT; } if (trace_flag) { Werrprintf( "%s: Cannot use 'trace' keyword with 1D data", argv[ 0 ] ); ABORT; } if (retc > 2) { Werrprintf( "%s: Cannot return more than 2 values with 1D data", argv[ 0 ] ); ABORT; } } /* 2D operations. If 2D data is present and the `trace' keyword was NOT selected, then there were either 2 or 4 numeric arguments. */ if (num_num_args == 4 || (d2flag && trace_flag == 0 && cmd_is_ds == 0)) { mark_ret_val = do_2d_mark( retc, retv, num_num_args, &mark_args[ 0 ] ); } /* 1D operations. Come here if A. num_num_args != 4 AND B. d2flag is clear OR trace_flag is set OR cmd_is_ds is set. */ else { mark_ret_val = do_1d_mark( cmd_is_ds, retc, retv, num_num_args, &mark_args[ 0 ] ); } if (mark_ret_val == 0) RETURN; else ABORT; }