йцукен (26.06.2017 14:40, просмотров: 1) ответил йцукен на У CM0 нет длинного умножения - куда крестьянину податься? Переношу тут некоторый код с CM3 на CM0, и такой затык: не успевает FIR фильтр, который фильтрует отсчёты 24-битного АЦП. Фильтр, ясное дело, целочисленный, и на CM3 никакой проблемы не
Раз никто не ответил, отвечу сам. Так я и не придумал, как православно резать коэффициенты на старшую и младшую часть, и решил вместо этого резать отсчёты АЦП. Ниже приведено 3 варианта фильтра: исходный, оптимизированный и хитрожопый. При частоте 48 МГц и максимальной оптимизации на скорость F042 исполняет их за 42, 23 и 9 мкс соответственно.
#define COEFF_SCALE 18
int32_t fir( int32_t *px, int32_t *pc, int len ) // brute force
{
int64_t acc = 0;
for ( int j = 0; j < len; j++ )
acc += int64_t(*pc++) * int64_t(*px++);
return int32_t( acc >> COEFF_SCALE );
}
int32_t fir2( int32_t *px1, int32_t *pc, int len ) // for even-length symmetric fir
{
int32_t *px2 = px1 + (len-1); // last tap
int64_t acc = 0;
for ( int j = 0; j < len/2; j++ )
acc += int64_t(*pc++) * int64_t( *px1++ + *px2-- );
return int32_t( acc >> COEFF_SCALE );
}
int32_t fir2_32( int32_t *px1, int32_t *pc, int len ) // avoids 64-bit arithmetic
{
int32_t *px2 = px1 + (len-1); // last tap
int32_t acc_lo = 0;
int32_t acc_hi = 0;
for ( int j = 0; j < len/2; j++ )
{
int32_t c = *pc++;
int32_t v = *px1++ + *px2--;
acc_lo += c * int32_t( v & 0xFFF ); // lower 12 bits
acc_hi += c * ( v >> 12 ); // upper 13 bits
}
return ( acc_hi + (acc_lo>>12) ) >> (18-12);
}