예제 #1
0
파일: wave.c 프로젝트: theFork/uMIDI
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);
}
예제 #2
0
파일: wave.c 프로젝트: theFork/uMIDI
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;
}
예제 #3
0
파일: Sig_Acq.c 프로젝트: thinrope/Nano_MCA
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
}
예제 #4
0
파일: wave.c 프로젝트: theFork/uMIDI
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));
}