int main(int ac, char** av) { #if 1 { fixed_t fu = float_to_fixed(1.2); fixed_t bar = float_to_fixed(2.4); fixed_t baz = fixed_add(fu, bar); printf("%f + ", fixed_to_float(fu)); printf("%f = ", fixed_to_float(bar)); printf("%f\n", fixed_to_float(baz)); } { fixed_t fu = float_to_fixed(1.5); fixed_t bar = int_to_fixed(2); fixed_t baz = fixed_mul(fu, bar); printf("%f * ", fixed_to_float(fu)); printf("%f = ", fixed_to_float(bar)); printf("%f\n", fixed_to_float(baz)); } { fixed_t fu = int_to_fixed(1); fixed_t bar = int_to_fixed(2); fixed_t baz = fixed_div(fu, bar); printf("%f / ", fixed_to_float(fu)); printf("%f = ", fixed_to_float(bar)); printf("%f\n", fixed_to_float(baz)); } { fixed_t fu = int_to_fixed(-1); fixed_t bar = int_to_fixed(2); fixed_t baz = fixed_div(fu, bar); printf("%f / ", fixed_to_float(fu)); printf("%f = ", fixed_to_float(bar)); printf("%f\n", fixed_to_float(baz)); } #endif #if 0 { fixed_t alpha = float_to_fixed(0.0); fixed_t step = float_to_fixed(0.01); for (; alpha < FIXED_TWO_PI; alpha = fixed_add(alpha, step)) { printf("%f ", fixed_to_float(alpha)); printf("%f\n", fabsf(sinf(fixed_to_float(alpha)) - fixed_to_float(fixed_sin(alpha)))); } } #endif return 0; }
void test_fixed_divide(void) { /* Negative */ a = fixed_make(-2023.621F); b = fixed_make(10.0F); result = fixed_div(a, b); TEST_ASSERT_EQUAL_FLOAT(fixed_make(-202.3621F), result); /* Positive */ a = fixed_make(2023.621F); b = fixed_make(10.0F); result = fixed_div(a, b); TEST_ASSERT_EQUAL_FLOAT(fixed_make(202.3621F), result); }
void temp_handler(void) { temp_samples[sample++] = make_fixed(raw_temp); if (sample == N_SAMPLES) { fixed_t t = make_fixed(0); for (uint8_t i = 0; i < N_SAMPLES; i++) { t = fixed_add(t, temp_samples[i]); } temp = fixed_round(fixed_div(fixed_div(t, N_SAMPLES), 4)); set_number(0, temp, relay_on); sample = 0; } }
void mat44_perspective(mat44 *m, fixed fov, fixed aspect, fixed near_z, fixed far_z) { fixed _fov = fixed_div(fixed_mul(FIXED_PI, fov), int_to_fixed(180)); fixed _f = fixed_div(FIXED_ONE, fixed_tan(fixed_mul(_fov, double_to_fixed(0.5)))); fixed nf = fixed_div((far_z + near_z), (near_z - far_z)); fixed nfr = fixed_div(fixed_mul(fixed_mul(int_to_fixed(2), far_z), near_z), (near_z - far_z)); mat44_set(m, fixed_div(_f, aspect), 0 , 0 , 0 , 0 , _f, 0 , 0 , 0 , 0 , nf , nfr, 0 , 0 , FIXED_NEGONE, 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 image_downsize_gd_fixed_point(image *im) { int x, y; fixed_t sy1, sy2, sx1, sx2; int dstX = 0, dstY = 0, srcX = 0, srcY = 0; fixed_t width_scale, height_scale; int dstW = im->target_width; int dstH = im->target_height; int srcW = im->width; int srcH = im->height; if (im->height_padding) { dstY = im->height_padding; dstH = im->height_inner; } if (im->width_padding) { dstX = im->width_padding; dstW = im->width_inner; } width_scale = fixed_div(int_to_fixed(srcW), int_to_fixed(dstW)); height_scale = fixed_div(int_to_fixed(srcH), int_to_fixed(dstH)); for (y = dstY; (y < dstY + dstH); y++) { sy1 = fixed_mul(int_to_fixed(y - dstY), height_scale); sy2 = fixed_mul(int_to_fixed((y + 1) - dstY), height_scale); for (x = dstX; (x < dstX + dstW); x++) { fixed_t sx, sy; fixed_t spixels = 0; fixed_t red = 0, green = 0, blue = 0, alpha = 0; if (!im->has_alpha) alpha = FIXED_255; sx1 = fixed_mul(int_to_fixed(x - dstX), width_scale); sx2 = fixed_mul(int_to_fixed((x + 1) - dstX), width_scale); sy = sy1; /* DEBUG_TRACE("sx1 %f, sx2 %f, sy1 %f, sy2 %f\n", fixed_to_float(sx1), fixed_to_float(sx2), fixed_to_float(sy1), fixed_to_float(sy2)); */ do { fixed_t yportion; //DEBUG_TRACE(" yportion(sy %f, sy1 %f, sy2 %f) = ", fixed_to_float(sy), fixed_to_float(sy1), fixed_to_float(sy2)); if (fixed_floor(sy) == fixed_floor(sy1)) { yportion = FIXED_1 - (sy - fixed_floor(sy)); if (yportion > sy2 - sy1) { yportion = sy2 - sy1; } sy = fixed_floor(sy); } else if (sy == fixed_floor(sy2)) { yportion = sy2 - fixed_floor(sy2); } else { yportion = FIXED_1; } //DEBUG_TRACE("%f\n", fixed_to_float(yportion)); sx = sx1; do { fixed_t xportion; fixed_t pcontribution; pix p; //DEBUG_TRACE(" xportion(sx %f, sx1 %f, sx2 %f) = ", fixed_to_float(sx), fixed_to_float(sx1), fixed_to_float(sx2)); if (fixed_floor(sx) == fixed_floor(sx1)) { xportion = FIXED_1 - (sx - fixed_floor(sx)); if (xportion > sx2 - sx1) { xportion = sx2 - sx1; } sx = fixed_floor(sx); } else if (sx == fixed_floor(sx2)) { xportion = sx2 - fixed_floor(sx2); } else { xportion = FIXED_1; } //DEBUG_TRACE("%f\n", fixed_to_float(xportion)); pcontribution = fixed_mul(xportion, yportion); p = get_pix(im, fixed_to_int(sx + srcX), fixed_to_int(sy + srcY)); /* DEBUG_TRACE(" merging with pix %d, %d: src %x (%d %d %d %d), pcontribution %f\n", fixed_to_int(sx + srcX), fixed_to_int(sy + srcY), p, COL_RED(p), COL_GREEN(p), COL_BLUE(p), COL_ALPHA(p), fixed_to_float(pcontribution)); */ red += fixed_mul(int_to_fixed(COL_RED(p)), pcontribution); green += fixed_mul(int_to_fixed(COL_GREEN(p)), pcontribution); blue += fixed_mul(int_to_fixed(COL_BLUE(p)), pcontribution); if (im->has_alpha) alpha += fixed_mul(int_to_fixed(COL_ALPHA(p)), pcontribution); spixels += pcontribution; sx += FIXED_1; } while (sx < sx2); sy += FIXED_1; } while (sy < sy2); // If rgba get too large for the fixed-point representation, fallback to the floating point routine // This should only happen with very large images if (red < 0 || green < 0 || blue < 0 || alpha < 0) { warn("fixed-point overflow: %d %d %d %d\n", red, green, blue, alpha); return image_downsize_gd(im); } if (spixels != 0) { /* DEBUG_TRACE(" rgba (%f %f %f %f) spixels %f\n", fixed_to_float(red), fixed_to_float(green), fixed_to_float(blue), fixed_to_float(alpha), fixed_to_float(spixels)); */ spixels = fixed_div(FIXED_1, spixels); red = fixed_mul(red, spixels); green = fixed_mul(green, spixels); blue = fixed_mul(blue, spixels); if (im->has_alpha) alpha = fixed_mul(alpha, spixels); } /* Clamping to allow for rounding errors above */ if (red > FIXED_255) red = FIXED_255; if (green > FIXED_255) green = FIXED_255; if (blue > FIXED_255) blue = FIXED_255; if (im->has_alpha && alpha > FIXED_255) alpha = FIXED_255; /* DEBUG_TRACE(" -> %d, %d %x (%d %d %d %d)\n", x, y, COL_FULL(fixed_to_int(red), fixed_to_int(green), fixed_to_int(blue), fixed_to_int(alpha)), fixed_to_int(red), fixed_to_int(green), fixed_to_int(blue), fixed_to_int(alpha)); */ if (im->orientation != ORIENTATION_NORMAL) { int ox, oy; // new destination pixel coordinates after rotating image_get_rotated_coords(im, x, y, &ox, &oy); if (im->orientation >= 5) { // 90 and 270 rotations, width/height are swapped so we have to use alternate put_pix method put_pix_rotated( im, ox, oy, im->target_height, COL_FULL(fixed_to_int(red), fixed_to_int(green), fixed_to_int(blue), fixed_to_int(alpha)) ); } else { put_pix( im, ox, oy, COL_FULL(fixed_to_int(red), fixed_to_int(green), fixed_to_int(blue), fixed_to_int(alpha)) ); } } else { put_pix( im, x, y, COL_FULL(fixed_to_int(red), fixed_to_int(green), fixed_to_int(blue), fixed_to_int(alpha)) ); } } } }
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)); }
void decode_output_samples(sample_t *buffer, u32_t nsamples, int sample_rate) { size_t bytes_out; /* Some decoders can pass no samples at the start of the track. Stop * early, otherwise we may send the track start event at the wrong * time. */ if (nsamples == 0) { return; } // XXXX full port from ip3k decode_audio_lock(); if (decode_first_buffer) { LOG_DEBUG(log_audio_decode, "first buffer sample_rate=%d", sample_rate); upload_open(); crossfade_started = FALSE; decode_audio->track_start_point = decode_audio->fifo.wptr; if (decode_transition_type & TRANSITION_CROSSFADE) { size_t crossfadeBytes; fft_fixed interval; if (decode_transition_type & TRANSITION_IMMEDIATE) { size_t wanted = SAMPLES_TO_BYTES(decode_transition_period * decode_audio->track_sample_rate); size_t used = fifo_bytes_used(&decode_audio->fifo); if (used > wanted) { size_t skip = used - wanted; if (skip > decode_audio->fifo.wptr) decode_audio->fifo.wptr += decode_audio->fifo.size; decode_audio->fifo.wptr -= skip; } } /* We are being asked to do a crossfade. Find out * if it is possible. */ interval = determine_transition_interval(sample_rate, decode_transition_period, &crossfadeBytes); if (interval) { LOG_DEBUG(log_audio_decode, "Starting CROSSFADE over %d seconds, requiring %d bytes", fixed_to_s32(interval), (unsigned int)crossfadeBytes); /* Buffer position to stop crossfade */ crossfade_ptr = decode_audio->fifo.wptr; /* Buffer position to start crossfade */ if (crossfadeBytes > decode_audio->fifo.wptr) decode_audio->fifo.wptr += decode_audio->fifo.size; decode_audio->fifo.wptr -= crossfadeBytes; /* Gain steps */ transition_gain_step = fixed_div(FIXED_ONE, fixed_mul(interval, s32_to_fixed(TRANSITION_STEPS_PER_SECOND))); transition_gain = 0; transition_sample_step = sample_rate / TRANSITION_STEPS_PER_SECOND; transition_samples_in_step = 0; crossfade_started = TRUE; decode_audio->track_start_point = decode_audio->fifo.wptr; } /* * else there aren't enough leftover samples from the * previous track, so abort the transition. */ } else if (decode_transition_type & TRANSITION_FADE_IN) { /* The transition is a fade in. */ LOG_DEBUG(log_audio_decode, "Starting FADE_IN over %d seconds", decode_transition_period); /* Gain steps */ transition_gain_step = fixed_div(FIXED_ONE, s32_to_fixed(decode_transition_period * TRANSITION_STEPS_PER_SECOND)); transition_gain = 0; transition_sample_step = sample_rate / TRANSITION_STEPS_PER_SECOND; transition_samples_in_step = 0; } decode_audio->track_copyright = streambuf_is_copyright(); decode_audio->track_sample_rate = sample_rate; decode_audio->check_start_point = TRUE; decode_first_buffer = FALSE; } if (upload_samples(buffer, nsamples)) { decode_audio_unlock(); return; } /* If output_channels is set, copy left samples to right, or vice versa */ if (output_channels) { unsigned int i; if (output_channels & OUTPUT_CHANNEL_LEFT) { for (i = 0; i < nsamples * 2; i += 2) { buffer[i+1] = buffer[i]; } } else { for (i = 0; i < nsamples * 2; i += 2) { buffer[i] = buffer[i+1]; } } } decode_apply_track_gain(buffer, nsamples); bytes_out = SAMPLES_TO_BYTES(nsamples); while (bytes_out) { size_t wrap, bytes_write, bytes_remaining; /* The size of the output write is limied by the * space untill our fifo wraps. */ wrap = fifo_bytes_until_wptr_wrap(&decode_audio->fifo); /* When crossfading limit the output write to the * end of the transition. */ if (crossfade_started) { bytes_remaining = decode_transition_bytes_remaining(crossfade_ptr); if (bytes_remaining < wrap) { wrap = bytes_remaining; } } bytes_write = bytes_out; if (bytes_write > wrap) { bytes_write = wrap; } if (transition_gain_step) { decode_transition_copy_bytes(buffer, bytes_write); if ((crossfade_started && decode_audio->fifo.wptr == crossfade_ptr) || transition_gain >= FIXED_ONE) { LOG_DEBUG(log_audio_decode, "Completed transition"); transition_gain_step = 0; crossfade_started = FALSE; } } else { memcpy(decode_fifo_buf + decode_audio->fifo.wptr, buffer, bytes_write); fifo_wptr_incby(&decode_audio->fifo, bytes_write); } buffer += (bytes_write / sizeof(sample_t)); bytes_out -= bytes_write; } decode_audio_unlock(); }