void spectgen_session_start(spectgen_session_t *session) { if(!session) return; if(session->busy == 0 || session->active == 0) return; SIGNAL_SET(&session->start_signal); }
/* decoder_start * * Start decoding of the file opened in decoder_open. * Note that the user needs to use decoder_data_pull to * get the decoded sample data. * * handle in decoder handle from decoder_init * * Return: 0 on success, negative error code on failure. */ int decoder_start(decoder_handle _handle) { struct decoder_handle_struct *handle = (struct decoder_handle_struct *)_handle; if(!handle && !handle->backend_handle) { return -1; } SIGNAL_SET(&handle->start_signal); return 0; }
static void *decoder_thread(void *data) { struct decoder_handle_struct *handle = (struct decoder_handle_struct *)data; while(handle->active) { SIGNAL_WAIT(&handle->start_signal); if(handle->active == 0) break; decoder_backend_decode(handle); SIGNAL_SET(&handle->finished_signal); } pthread_exit(NULL); }
static void *spectgen_session_thread(void *data) { spectgen_session_t *session = (spectgen_session_t *)data; while(session->active) { SIGNAL_WAIT(&session->start_signal); if(session->active == 0) break; /* To be safe... */ if(session->user_cb && session->user_handle) session->user_cb((void *)session->user_handle); else printf("WARING: Session improperly setup.\n"); SIGNAL_SET(&session->finished_signal); } pthread_exit(NULL); }
void decoder_exit(decoder_handle _handle) { struct decoder_handle_struct *handle = (struct decoder_handle_struct *)_handle; void *par; if(!handle) return; handle->active = 0; /* So that the active flag is tested */ SIGNAL_SET(&handle->start_signal); pthread_join(handle->thread, &par); if(handle->backend_handle) decoder_backend_close(handle); handle->backend_handle = NULL; q_destroy(handle->queue); free(handle->queue); SIGNAL_DEINIT(&handle->start_signal); SIGNAL_DEINIT(&handle->finished_signal); free(handle); }
void static inline spectgen_session_destroy(spectgen_session_t *session) { void *par; if(!session) return; session->active = 0; SIGNAL_SET(&session->start_signal); pthread_join(session->thread, &par); if(session->fft_in_pre) fftwf_free(session->fft_in_pre); if(session->fft_out_pre) fftwf_free(session->fft_out_pre); if(session->fft_in_post) fftwf_free(session->fft_in_post); if(session->fft_out_post) fftwf_free(session->fft_out_post); if(session->plan_pre) { pthread_mutex_lock(&planner_lock); fftwf_destroy_plan(session->plan_pre); pthread_mutex_unlock(&planner_lock); } if(session->plan_post) { pthread_mutex_lock(&planner_lock); fftwf_destroy_plan(session->plan_post); pthread_mutex_unlock(&planner_lock); } if(session->window) free(session->window); if(session->scale_table) free(session->scale_table); if(session->norm_table) free(session->norm_table); pthread_mutex_destroy(&session->lock); SIGNAL_DEINIT(&session->start_signal); SIGNAL_DEINIT(&session->finished_signal); decoder_exit(session->d_handle); free(session); }
t_stat realcons_pdp10_operpanel_service(realcons_console_logic_pdp10_t *_this) { unsigned single_inst; // // ----- Default ENABLE logic -------------- // controls, which are nort reclaced here, remain enbaled by default // "enable =1" // "In the upper half of the operator panel are four rows of indicators, and below them are three // rows of two-position keys and switches. Physically both are pushbuttons, but the keys are // momentary contact whereas the switches are alternate action."" _this->button_PAGING_EXEC.enabled = !_this->console_lock; _this->button_PAGING_USER.enabled = !_this->console_lock; _this->button_SINGLE_PULSER.enabled = !_this->console_lock; _this->button_STOP_PAR.enabled = !_this->console_lock; _this->button_STOP_NXM.enabled = !_this->console_lock; _this->button_REPEAT.enabled = !_this->console_lock; _this->button_FETCH_INST.enabled = !_this->console_lock; _this->button_FETCH_DATA.enabled = !_this->console_lock; _this->button_WRITE.enabled = !_this->console_lock; _this->button_ADDRESS_STOP.enabled = !_this->console_lock; _this->button_ADDRESS_BREAK.enabled = !_this->console_lock; _this->button_XCT.enabled = !_this->console_lock; // SINGLE_INST // "Whenever the processor is placed in operation, clear RUN so that it stops at the end of the first instruction. // Hence the operator can step through a program one instruction at a time, pressing START for the first one and // CONT for subsequent ones. Each time the processor stops, the lights display the same information as when STOP // is pressed. Note that read in cannot be done in single instruction mode, as the function' extends over many // instructions and there is thus no way to continue." // - SINGLE is a mode flag, not a command _this->button_SINGLE_INST.enabled = !_this->console_lock; single_inst = !!realcons_pdp10_control_get(&_this->button_SINGLE_INST); if (single_inst && _this->run_state == RUN_STATE_RUN) { // first stop the CPU, like pressing "HALT" SIGNAL_SET(cpusignal_console_halt, 1); // now START and CONT do single steps } // STOP pressed: set HALT signal _this->button_STOP.enabled = !_this->console_lock && (_this->run_state == RUN_STATE_RUN); // "Turn off RUN so the processor stops with STOP MAN on. At the stop PC points to the location of the instruction that will // be fetched if CONT is pressed (this is the instruction that would have been done next had the processor not stopped)." if (_this->button_STOP.pendingbuttons) { SIGNAL_SET(cpusignal_console_halt, 1); _this->button_STOP.pendingbuttons = 0; } // START // "Turn on RUN and EXEC MODE KERNEL, and begin normal operation by fetching the instruction at the location specified by // address switches 18-35. The memory subroutine for the instruction fetch loads the address into PC for the program // to continue. This function does not disturb the flags or the IO equipment." _this->button_START.enabled = !_this->console_lock; if (_this->button_START.pendingbuttons) { // PC value <=?=> value of addr lamps??? SIGNAL_SET(cpusignal_PC, (int32) realcons_pdp10_control_get(&_this->buttons_ADDRESS)); if (single_inst) // set PC and single step sprintf(_this->realcons->simh_cmd_buffer, "deposit pc %" PRIo64 "\nstep 1\n", realcons_pdp10_control_get(&_this->buttons_ADDRESS)); else // SimH start is like sprintf(_this->realcons->simh_cmd_buffer, "run %" PRIo64 "\n", realcons_pdp10_control_get(&_this->buttons_ADDRESS)); _this->button_START.pendingbuttons = 0; } // CONT _this->button_CONT.enabled = !_this->console_lock && (_this->run_state != RUN_STATE_RUN); if (_this->button_CONT.pendingbuttons) { if (single_inst) sprintf(_this->realcons->simh_cmd_buffer, "step 1\n"); else sprintf(_this->realcons->simh_cmd_buffer, "cont\n"); _this->button_CONT.pendingbuttons = 0; // runmode setby event "runstart" } // RESET // "Clear all IO devices, disable auto restart, high speed operation and margin programming, // clear the processor flags (lighting EXEC MODE KERNEL), turn on the triangular light // beside MEMORY DATA (turn off the light beside PROGRAM DATA), turn off RUN and stop the processor. _this->button_RESET.enabled = !_this->console_lock; if (_this->button_RESET.pendingbuttons) { if (_this->run_state == RUN_STATE_RUN) { // if machine is running: perform stop, then in stop event do reset SIGNAL_SET(cpusignal_console_halt, 1); } else { sprintf(_this->realcons->simh_cmd_buffer, "reset all\n"); _this->button_RESET.pendingbuttons = 0; } } // READ IN // "Clear all IO devices and all processor flags. Turn on RUN and EXEC MODE KERNEL // (trapping and paging will both be disabled as TRAP ENABLE at the top of the console bay will be off). // Execute DATAI D,0 where D is the device code specified by the readin device switches at the left end // of the maintenance panel (the rightmost device switch is for bit 9 of the instruction and thus // selects the least significant octal digit (which is always 0 or 4) in the device code)." _this->button_READ_IN.enabled = !_this->console_lock && (_this->run_state != RUN_STATE_RUN); if (_this->button_READ_IN.pendingbuttons) { unsigned readin_device = (unsigned) realcons_pdp10_control_get(&_this->buttons_READ_IN_DEVICE); // readin device: button labels "3..9" -> bits 6..0 readin_device <<= 2; // bits 1 and 0 are missing switch (readin_device) { case 0104: // "PTR" paper tape "PTR sprintf(_this->realcons->simh_cmd_buffer, "boot ptr\n"); break; case 0320: // "DTA": disk: rp0? sprintf(_this->realcons->simh_cmd_buffer, "boot rp0\n"); break; case 0330: // "DTB": disk: rp1? sprintf(_this->realcons->simh_cmd_buffer, "boot rp1\n"); break; case 0340: // "MTA": tape TU0 sprintf(_this->realcons->simh_cmd_buffer, "boot tu0\n"); break; case 0350: // "MTB": tape TU1 sprintf(_this->realcons->simh_cmd_buffer, "boot tu1\n"); break; default: sprintf(_this->realcons->simh_cmd_buffer, "; Unknown boot device: READ-IN DEVICE = %o\n", readin_device); } _this->button_READ_IN.pendingbuttons = 0; } /* addr/data clear/set * "At the right end of each of these switch registers is a pair of keys that clear or load all the switches in the register * together. The load button sets up the switches according to the contents of the corresponding bits of the memory * indicators (MI) in the fourth row." * So: "address load" loads from DATA LEDs. * LOAD is disabled, if data value was written by program control * Press MI PROG DIS to stop program update and enable LOAD */ _this->buttons_ADDRESS.enabled = !_this->console_lock; _this->button_ADDRESS_CLEAR.enabled = !_this->console_lock; _this->button_ADDRESS_LOAD.enabled = !_this->console_lock && !_this->memory_indicator_program; _this->buttons_DATA.enabled = !_this->console_datalock; _this->button_DATA_CLEAR.enabled = !_this->console_datalock; _this->button_DATA_LOAD.enabled = !_this->console_datalock && !_this->memory_indicator_program; if (_this->button_ADDRESS_CLEAR.pendingbuttons) { realcons_pdp10_control_set(&_this->buttons_ADDRESS, 0); _this->button_ADDRESS_CLEAR.pendingbuttons = 0; } if (_this->button_ADDRESS_LOAD.pendingbuttons) { // load addr from data leds realcons_pdp10_control_set(&_this->buttons_ADDRESS, realcons_pdp10_control_get(&_this->leds_DATA)); _this->button_ADDRESS_LOAD.pendingbuttons = 0; } if (_this->button_DATA_CLEAR.pendingbuttons) { realcons_pdp10_control_set(&_this->buttons_DATA, 0); _this->button_DATA_CLEAR.pendingbuttons = 0; } if (_this->button_DATA_LOAD.pendingbuttons) { // load data from data leds realcons_pdp10_control_set(&_this->buttons_DATA, realcons_pdp10_control_get(&_this->leds_DATA)); _this->button_DATA_LOAD.pendingbuttons = 0; } /* EXAM/DEPOSIT * light "MEMORY DATA" goes on (in feedback event "exam_deposit()" * PAGING SWITCHES: * both off: 22bit absolute physical, else virtual EXEC or USER space (Hiere: always 22 bit) */ // extra logic: exam/deposit ONLY when machine is stopped _this->button_EXAMINE_THIS.enabled = !_this->console_lock && (_this->run_state != RUN_STATE_RUN); _this->button_EXAMINE_NEXT.enabled = !_this->console_lock && (_this->run_state != RUN_STATE_RUN); _this->button_DEPOSIT_THIS.enabled = !_this->console_lock && (_this->run_state != RUN_STATE_RUN); _this->button_DEPOSIT_NEXT.enabled = !_this->console_lock && (_this->run_state != RUN_STATE_RUN); if (_this->button_EXAMINE_THIS.pendingbuttons) { sprintf(_this->realcons->simh_cmd_buffer, "examine %" PRIo64 "\n", realcons_pdp10_control_get(&_this->buttons_ADDRESS)); // addr&data result written to LEDs in "event_exam_deposit()" _this->button_EXAMINE_THIS.pendingbuttons = 0; } if (_this->button_EXAMINE_NEXT.pendingbuttons) { // inc address buttons before examine uint64_t addr = realcons_pdp10_control_get(&_this->buttons_ADDRESS); addr++; sprintf(_this->realcons->simh_cmd_buffer, "examine %" PRIo64 "\n", addr); // addr&data result written to LEDs in "event_exam_deposit()" _this->button_EXAMINE_NEXT.pendingbuttons = 0; } if (_this->button_DEPOSIT_THIS.pendingbuttons) { sprintf(_this->realcons->simh_cmd_buffer, "deposit %" PRIo64 " %" PRIo64 "\n", realcons_pdp10_control_get(&_this->buttons_ADDRESS), realcons_pdp10_control_get(&_this->buttons_DATA)); // addr&data result written to LEDs in "event_exam_deposit()" _this->button_DEPOSIT_THIS.pendingbuttons = 0; } if (_this->button_DEPOSIT_NEXT.pendingbuttons) { uint64_t addr = realcons_pdp10_control_get(&_this->buttons_ADDRESS); addr++; sprintf(_this->realcons->simh_cmd_buffer, "deposit %" PRIo64 " %" PRIo64 "\n", addr, realcons_pdp10_control_get(&_this->buttons_DATA)); // addr&data result written to LEDs in "event_exam_deposit()" _this->button_DEPOSIT_NEXT.pendingbuttons = 0; } // set the MEMORY INDICATOR triangle LEDs above row 4 if (_this->memory_indicator_program == 1) { _this->led_MEMORY_DATA.lamps->value = 0; _this->led_PROGRAM_DATA.lamps->value = 1; } else { _this->led_MEMORY_DATA.lamps->value = 1; _this->led_PROGRAM_DATA.lamps->value = 0; } // DATA Switches set the "console data switch register" // (so a Simh "deposit cds ...." is always overwritten with this SIGNAL_SET(cpusignal_console_data_switches, realcons_pdp10_control_get(&_this->buttons_DATA)); // RUN/STOP LEDS switch (_this->run_state) { case RUN_STATE_HALT_MAN: // halt bei user _this->leds_STOP.lamps->value = 0x4; // STOP.MAN _this->led_RUN.lamps->value = 0; break; case RUN_STATE_HALT_PROG: _this->leds_STOP.lamps->value = 0x2; // STOP.PROG _this->led_RUN.lamps->value = 0; break; case RUN_STATE_RUN: _this->leds_STOP.lamps->value = 0; // no STOP _this->led_RUN.lamps->value = 1; break; } // PI LEDs // "The four sets of seven lights at the left display the state of the priority interrupt channels. // The PI ACTIVE lights indicate which channels are on. The IOB PI REQUEST lights indicate which // channels are receiving request signals over the in-out bus; the PI REQUEST lights indicate // channels on which the processor has accepted requests. Except in the case of a program-initiated // interrupt, a REQUEST light can go on only if the corresponding ACTIVE light is on. The PI IN // PROGRESS lights indicate channels on which interrupts are currently being held; the channel that // is actually being serviced is the lowest-numbered one whose light is on. When an IN PROGRESS // light goes on, the corresponding REQUEST goes off and cannot go on again until IN PROGRESS goes // off when the interrupt is dismissed. PI ON indicates the priority interrupt system is active, so // interrupts can be started (this corresponds to CONI PI, bit 28). PI OK 8 indicates that there is // no interrupt being held and no channel waiting for an interrupt; this signal is used by the real // time clock to discount interrupt time while timing user programs." // Different signals names? // Simh KI10 console // pi_act "active" pi in progress "chanels where interrupts are beeing held" // pi_enb "enabled pi levels" pi active "channels which are ON" // realcons_pdp10_control_set(&_this->led_PI_ON, !!SIGNAL_GET(cpusignal_pi_on)); realcons_pdp10_control_set(&_this->leds_PI_ACTIVE, SIGNAL_GET(cpusignal_pi_enb)); realcons_pdp10_control_set(&_this->leds_PI_IN_PROGRESS, SIGNAL_GET(cpusignal_pi_act)); realcons_pdp10_control_set(&_this->leds_IOB_PI_REQUEST, SIGNAL_GET(cpusignal_pi_ioq)); realcons_pdp10_control_set(&_this->leds_PI_REQUEST, SIGNAL_GET(cpusignal_pi_prq)); // some eye candy if (_this->run_state == RUN_STATE_RUN) { _this->leds_MODE.lamps->value = 0x01; // kernel exec } return 0; // OK }