void set_speed(struct wave * const wave, midi_value_t speed) { // Scale range from [0..127] to [15..300] bpm fixed_t freq = fixed_from_int(speed); freq /= 127; freq *= 285; freq += fixed_from_int(15); freq /= 60; set_frequency(wave, freq); }
void tap_tempo_task(void) { static uint8_t taps = 0; static uint8_t buffer_index = 0; // Increment counter static uint16_t counter = 0; ++counter; if (!tap_arrived) { if (counter < 400) { return; } // Reset after timeout set_led(LED_RED, false); counter = 0; taps = 0; buffer_index = 0; return; } tap_arrived = false; // Increment tap counter to buffer size if (taps < TAP_TEMPO_BUFFER_SIZE) { ++taps; } if (taps == 1) { set_led(LED_RED, true); } else { // Register tap interval with cyclic buffer static fixed_t tap_tempo_buffer[TAP_TEMPO_BUFFER_SIZE] = {0, }; fixed_t tap_frequency = fixed_from_int(TAP_TEMPO_TASK_FREQUENCY) / counter; tap_tempo_buffer[buffer_index] = tap_frequency; ++buffer_index; buffer_index %= TAP_TEMPO_BUFFER_SIZE; // Compute average fixed_t average = 0; for (int i=0; i<taps; i++) { average += tap_tempo_buffer[i]; } average /= taps; // Set wave frequency set_frequency(tap_tempo_wave, average); } // Reset counter counter = 0; }
void Scan_Samples(void){ fixed ybox[7]; // array box car derivative s16 bin; // index into peak height array fixed dt, tau, *yp0, *yp1, y, y_i; fixed threshold; // trigger level for leading edge fixed deriv; fixed alpha, beta, gamma, peak; s16 i; configurations *cp = &configuration; ADC_Stop(); tail = head = Get_Scan_Pos(); // get current absolute position in adc buffer /* if(cp->sig_filter){ // Set up Butterworth low pass filter dt = FIXED_HALF; // sample time 0.5 uS tau = fixed_from_int(cp->sig_filter); // filter time in uS alpha = fixed_div(dt, tau + dt); } */ ADC_Start(); while(TRUE){ if(tail == head){ head = Get_Scan_Pos(); // recalculate filter elements in case changed /* if(cp->sig_filter){ // Set up Butterworth low pass filter in case of changes dt = FIXED_HALF; // sample time 0.5 uS tau = fixed_from_int(cp->sig_filter); // filter time in uS alpha = fixed_div(dt, tau + dt); } */ } if(tail == head) continue; // track live time if(samp_cntr++ >= SAMP_PER_MS){ live_time++; samp_cntr = 0; } // get new value, adjust for zero and inversion at same time y = fixed_from_int(zero - scan_buffer[tail++]); if(tail >= SCAN_BUFFER_SZ){ tail = 0; } // filter signal if needed /* if(cp->sig_filter){ // Butterworth low pass filter y = *yp0 + fixed_mul(alpha, (y - *yp0)); } */ // shift the boxcar window and find derivative yp0 =&ybox[0]; yp1 = &ybox[1]; for(i = 6; i > 0; i--){ // last box slot gets new y value *yp0++ = *yp1++; } *yp0 = y; // place latest sample in end of boxcar // compute the derivative deriv = 0; yp0 =&ybox[0]; deriv -= *yp0++; deriv -= *yp0++; alpha = *yp0; deriv -= *yp0++; beta = *yp0++; gamma = *yp0; deriv += *yp0++; deriv += *yp0++; deriv += *yp0++; // process depending on state switch(scan_state){ case RESTART: scan_state = LEADING; //cp->scope_valid = FALSE; break; case LEADING: if(cp->sig_type == PULSE_POS && deriv > cp->sig_dvdt_lim){ scan_state = PEAK; break; } if(cp->sig_type == PULSE_NEG && deriv < cp->sig_dvdt_lim){ scan_state = PEAK; break; } // if no pulse then check the zero avg_zero = (avg_zero * 20 + y)/21; break; case PEAK: // reverse derivative indicates peak if(cp->sig_type == PULSE_POS && deriv < 0){ scan_state = TAIL; } if(cp->sig_type == PULSE_NEG && deriv > 0){ scan_state = TAIL; } if(scan_state == TAIL){ // handle gaussian approximation if enabled if(cp->sig_gaussian){ // p = ((a - g)/(a -2b + g))/2 = position of peak peak = (fixed_div((alpha - gamma),(alpha - (2 * beta) + gamma))) / 2; // y(p) = b - ((a - g) * p)/4 = peak value peak = beta - (fixed_mul((alpha - gamma), peak) / 4); } else { peak = (alpha + beta + gamma) / 3; } if(cp->sig_type == PULSE_NEG){ peak = -peak; } // peak now always positive if( peak > cp->sig_lo_lim && peak < cp->sig_hi_lim){ bin = fixed_to_int(peak); pulse_height[bin]++; // increment count in spectrum array cur_cnt++; // handle rate meter beeping if(cp->rate_beep && !alarm_on){ Beep(BEEP_500Hz, 10); } } } break; case TAIL: // find where curve turns back to baseline if(cp->sig_type == PULSE_POS && deriv >= 0){ scan_state = LEADING; } if(cp->sig_type == PULSE_NEG && deriv <= 0){ scan_state = LEADING; } break; } // switch(scan_state) } // while ring buffer not empty }
void set_frequency(struct wave * const wave, fixed_t frequency) { wave->settings.frequency = frequency; const fixed_t max_frequency = fixed_from_int(F_TASK_FAST/(2*WAVE_STEPS)); wave->state.speed_prescaler = fixed_to_int(fixed_div(max_frequency, wave->settings.frequency)); }