u8 XN297_ReadPayload(u8* msg, int len) { // TODO: if xn297_crc==1, check CRC before filling *msg u8 res = NRF24L01_ReadPayload(msg, len); for(u8 i=0; i<len; i++) msg[i] = bit_reverse(msg[i])^bit_reverse(xn297_scramble[i+xn297_addr_len]); return res; }
uint8_t XN297_ReadPayload(uint8_t* msg, int len) { uint8_t res = NRF24L01_ReadPayload(msg, len); uint8_t i; for(i = 0; i<len; i++) msg[i] = bit_reverse(msg[i]) ^ bit_reverse(xn297_scramble[i+xn297_addr_len]); return res; }
void process_fddi(register u_char *u, register const struct pcap_pkthdr *h, register const u_char *p) { register struct fddi_header *fh; register struct ether_arp *ea; register u_char *sea, *sha; register time_t t; u_int32_t sia; fh = (struct fddi_header *)p; ea = (struct ether_arp *)(fh + 1); if (!swapped) { bit_reverse(fh->src, 6); bit_reverse(fh->dst, 6); } if (!sanity_fddi(fh, ea, h->caplen)) return; /* Source MAC hardware ethernet address */ sea = (u_char *)fh->src; /* Source ARP ethernet address */ sha = (u_char *)SHA(ea); /* Source ARP ip address */ BCOPY(SPA(ea), &sia, 4); /* Watch for bogons */ if (isbogon(sia)) { dosyslog(LOG_INFO, "bogon", sia, sea, sha); return; } /* Watch for ethernet broadcast */ if (MEMCMP(sea, zero, 6) == 0 || MEMCMP(sea, allones, 6) == 0 || MEMCMP(sha, zero, 6) == 0 || MEMCMP(sha, allones, 6) == 0) { dosyslog(LOG_INFO, "ethernet broadcast", sia, sea, sha); return; } /* Double check ethernet addresses */ if (MEMCMP(sea, sha, 6) != 0) { dosyslog(LOG_INFO, "ethernet mismatch", sia, sea, sha); return; } /* Got a live one */ t = h->ts.tv_sec; can_checkpoint = 0; if (!ent_add(sia, sea, t, NULL)) syslog(LOG_ERR, "ent_add(%s, %s, %ld) failed", intoa(sia), e2str(sea), t); can_checkpoint = 1; }
int bit_reverse(unsigned int n, unsigned int k) { if(k==1)return n; unsigned int k1,k2,a,b; k1 = k/2; k2 = k-k1; a = n>>k2; b = n - (a<<k2); a = bit_reverse(a,k1); b = bit_reverse(b,k2); return (b<<k1)+a; }
bool display_drawLine(int x, int y, uint8_t line) { bool unset = false; if (!display_inited) return unset; if (y < 0 || y >= DISPLAY_MAX_Y) return unset; line = bit_reverse(line); while (line) { if (x < 0 || x >= DISPLAY_MAX_X) break; if (line & 1) { if (display_get(x, y)) unset = true; display_toggle(x, y); } x++; line >>= 1; } return unset; }
void fft_tobb(fft_direction dir, cpx **in, cpx **out, const int n_threads, const int n) { const int n2 = (n / 2); int bit, dist, dist2; unsigned int steps; cpx *W; bit = log2_32(n); const int lead = 32 - bit; W = (cpx *)malloc(sizeof(cpx) * n); twiddle_factors(W, dir, n); steps = 0; dist2 = n; dist = n2; --bit; _fft_tbbody(*in, *out, W, bit, steps, dist, dist2, n2); while (bit-- > 0) { dist2 = dist; dist = dist >> 1; _fft_tbbody(*out, *out, W, bit, ++steps, dist, dist2, n2); } bit_reverse(*out, dir, lead, n); free(W); }
static int create_stairstep_page(TIFF *tiff_file) { uint8_t image_buffer[8192]; int row; int start_pixel; int i; /* TSB-85 STAIRSTEP page. */ start_pixel = 0; for (row = 0; row < 1728; row++) { clear_row(image_buffer, 1728); set_pixel_range(image_buffer, 1, start_pixel, start_pixel + 63); if (photo_metric != PHOTOMETRIC_MINISWHITE) { for (i = 0; i < 1728/8; i++) image_buffer[i] = ~image_buffer[i]; } #if 0 if (fill_order != FILLORDER_LSB2MSB) bit_reverse(image_buffer, image_buffer, 1728/8); #endif if (TIFFWriteScanline(tiff_file, image_buffer, row, 0) < 0) { printf("Write error at row %d.\n", row); exit(2); } start_pixel += 64; if (start_pixel >= 1728) start_pixel = 0; } return 1728; }
void fft(DTYPE X_R[SIZE], DTYPE X_I[SIZE]) { DTYPE temp_R; /*temporary storage complex variable*/ DTYPE temp_I; /*temporary storage complex variable*/ int i,j,k; /* loop indexes */ int i_lower; /* Index of lower point in butterfly */ int step; int stage; int DFTpts; int numBF; /*Butterfly Width*/ int N2 = SIZE2; /* N2=N>>1 */ bit_reverse(X_R, X_I); /*=======================BEGIN: FFT=========================*/ // Do M stages of butterflies step=N2; DTYPE a, e, c, s; for(stage=1; stage<= M; stage++) { DFTpts = 1 << stage; // DFT = 2^stage = points in sub DFT numBF = DFTpts/2; // Butterfly WIDTHS in sub-DFT k=0; e = -6.283185307178/DFTpts; a = 0.0; // Perform butterflies for j-th stage butterfly:for(j=0; j<numBF; j++) { c = cos(a); s = sin(a); a = a + e; // Compute butterflies that use same W**k DFTpts:for(i=j; i<SIZE; i += DFTpts) { i_lower = i + numBF; //index of lower point in butterfly temp_R = X_R[i_lower]*c- X_I[i_lower]*s; temp_I = X_I[i_lower]*c+ X_R[i_lower]*s; X_R[i_lower] = X_R[i] - temp_R; X_I[i_lower] = X_I[i] - temp_I; X_R[i] = X_R[i] + temp_R; X_I[i] = X_I[i] + temp_I; } k+=step; } step=step/2; } }
void mlcd_set_lines_with_func(uint8_t (*f)(uint8_t, uint8_t), uint8_t first_line, uint8_t line_number) { NRF_SPI_Type *spi_base = (NRF_SPI_Type *)MLCD_SPI; uint8_t command = MLCD_WR; uint8_t dummy = 0; uint8_t line_buffer[MLCD_LINE_BYTES+2]; uint8_t max_line = first_line + line_number; /* enable slave (slave select active HIGH) */ nrf_gpio_pin_set(MLCD_SPI_SS); spi_master_tx_data_no_cs(spi_base, &command, 1); line_buffer[MLCD_LINE_BYTES+1] = 0; for(uint8_t line = first_line; line < max_line; line++) { line_buffer[0] = bit_reverse(line+1); for(uint8_t i=0; i < MLCD_LINE_BYTES; i++) { uint8_t val = 0; for(uint8_t bit=0; bit<8; bit++){ val |= (*f)(i*8+bit, line) << (7-bit); } line_buffer[i+1] = val; } spi_master_tx_data_no_cs(spi_base, line_buffer, MLCD_LINE_BYTES+2); } spi_master_tx_data_no_cs(spi_base, &dummy, 1); /* disable slave (slave select active HIGH) */ nrf_gpio_pin_clear(MLCD_SPI_SS); }
int __main(void) { int store [20]; volatile unsigned char r; char text [] = "1234"; char test [] = "hello"; volatile int result = asciiToBCD(0x30); result = asciiToBCD(0x3239); result = BCDToAscii(0x1234); result = BCDToAscii(0x0); r = cipher('A'); r = cipher('Z'); r = ccipher('A', 5); result = bit_reverse(0xAAAA0000); fib(20, store); char_reverse(text, 4); word_reverse(text, 4); word_reverse(test, 5); word_reverse_compiled(text, 4); word_reverse_compiled(test, 5); return 0; }
unsigned long llz_fft_init(int size) { int i; double ang; llz_fft_ctx_t *f = NULL; f = (llz_fft_ctx_t *)malloc(sizeof(llz_fft_ctx_t)); memset(f, 0, sizeof(llz_fft_ctx_t)); f->length = size; f->base = (int)(log(size)/log(2)); if ((1<<f->base) < size) f->base += 1; f->bit_rvs = (int *)malloc(sizeof(int)*size); f->fft_work = (double *)malloc(sizeof(double)*size*2); f->cos_ang = (double *)malloc(sizeof(double)*size); f->sin_ang = (double *)malloc(sizeof(double)*size); bit_reverse(f->bit_rvs,size); for (i = 0 ; i < size ; i++){ ang = (double)(2*M_PI*i)/size; f->cos_ang[i] = (double)cos(ang); f->sin_ang[i] = (double)sin(ang); } return (unsigned long)f; }
uintptr_t fa_fft_init(int size) { int i; float ang; fa_fft_ctx_t *f = NULL; f = (fa_fft_ctx_t *)malloc(sizeof(fa_fft_ctx_t)); f->length = size; f->base = (int)(log(size)/log(2)); if ((1<<f->base) < size) f->base += 1; f->bit_rvs = (int *)malloc(sizeof(int)*size); f->fft_work = (float *)malloc(sizeof(float)*size*2); f->cos_ang = (float *)malloc(sizeof(float)*size); f->sin_ang = (float *)malloc(sizeof(float)*size); bit_reverse(f->bit_rvs,size); for (i = 0 ; i < size ; i++){ ang = (float)(2*M_PI*i)/size; f->cos_ang[i] = (float)cos(ang); f->sin_ang[i] = (float)sin(ang); } return (uintptr_t)f; }
void fft(double* re,double* im,int32_t bitsize) { int32_t i; int32_t stage; int32_t datasize = 1 << bitsize; bit_reverse(datasize,re); bit_reverse(datasize,im); for (stage = 1; stage <= bitsize; stage++) { int32_t type; double wRe, wIm; double uRe, uIm; double tempwRe,tempwIm; double tempRe, tempIm; int32_t butterflydist = 1 << stage; int32_t numType = butterflydist >> 1; int32_t butterflysize = butterflydist >> 1; wRe = 1.0; wIm = 0.0; uRe = cos(PI / butterflysize); uIm = -sin(PI / butterflysize); for (type = 0; type < numType; type++) { for (i = type; i < datasize; i += butterflydist) { int32_t ip; ip = i + butterflysize; tempRe = re[ip] * wRe - im[ip] * wIm; tempIm = re[ip] * wIm + im[ip] * wRe; re[ip] = re[i] - tempRe; im[ip] = im[i] - tempIm; re[i] += tempRe; im[i] += tempIm; } tempwRe = wRe * uRe - wIm * uIm; tempwIm = wRe * uIm + wIm * uRe; wRe = tempwRe; wIm = tempwIm; } } }
complex fft(int n, int log2n, double *data) { if ( n < 0 || n >= (1 << (log2n) ) ) { fprintf(stderr, "_fft() : index no. [%d] is invalid.", n); exit(1); } n = bit_reverse(n, log2n); return _fft(n, 0, log2n, data); }
void FFT::transform( std::vector< std::complex<double> > &data ) { N = data.size(); f = &data; bit_reverse(); for (int n = 1; n < N; n *= 2) Danielson_Lanczos(n); for (int i = 0; i < N; ++i) (*f)[i] /= std::sqrt(double(N)); }
void fft_fixed(fft_direction dir, cpx **in, cpx **out, const int n_threads, const int n) { #ifdef GENERATED_FIXED_SIZE if (fixed_size_fft(dir, *in, *out, GEN_BIT_REVERSE_ORDER, n)) { return; } #endif cpx *W = (cpx *)malloc(sizeof(cpx) * n); twiddle_factors(W, dir, n); fft_xn(dir, *in, *out, W, n); free(W); bit_reverse(*out, dir, 32 - log2_32(n), n); }
static void send_hdlc(void *user_data, const uint8_t *msg, int len) { t38_terminal_state_t *s; s = (t38_terminal_state_t *) user_data; if (len <= 0) { s->tx_len = -1; } else { bit_reverse(s->tx_buf, msg, len); s->tx_len = len; s->tx_ptr = 0; } }
//----------------------------------------------------------------------------- // name: cfft() // desc: complex value fft // // these routines from CARL software, spect.c // check out the CARL CMusic distribution for more software // // cfft replaces float array x containing NC complex values (2*NC float // values alternating real, imagininary, etc.) by its Fourier transform // if forward is true, or by its inverse Fourier transform ifforward is // false, using a recursive Fast Fourier transform method due to // Danielson and Lanczos. // // NC MUST be a power of 2. // //----------------------------------------------------------------------------- void cfft( float * x, long NC, unsigned int forward ) { float wr, wi, wpr, wpi, theta, scale ; long mmax, ND, m, i, j, delta ; ND = NC<<1 ; bit_reverse( x, ND ) ; for( mmax = 2 ; mmax < ND ; mmax = delta ) { delta = mmax<<1 ; theta = TWOPI/( forward? mmax : -mmax ) ; wpr = (float) (-2.*pow( sin( 0.5*theta ), 2. )) ; wpi = (float) sin( theta ) ; wr = 1. ; wi = 0. ; for( m = 0 ; m < mmax ; m += 2 ) { register float rtemp, itemp ; for( i = m ; i < ND ; i += delta ) { j = i + mmax ; rtemp = wr*x[j] - wi*x[j+1] ; itemp = wr*x[j+1] + wi*x[j] ; x[j] = x[i] - rtemp ; x[j+1] = x[i+1] - itemp ; x[i] += rtemp ; x[i+1] += itemp ; } wr = (rtemp = wr)*wpr - wi*wpi + wr ; wi = wi*wpr + rtemp*wpi + wi ; } } // scale output scale = (float)(forward ? 1./ND : 2.) ; { register float *xi=x, *xe=x+ND ; while( xi < xe ) *xi++ *= scale ; } }
static huft_code huft_get_code( huft_bits *b, /* code lengths in bits (all assumed <= B_MAX) */ int n, /* number of codes (assumed <= N_MAX) */ int k /* index */ ) { huft_code code = 0; huft_bits bits = b[k]; int i; if (bits == 0) return 0; for (i = 0; i < n; i++) { if (b[i] < bits && b[i] > 0) code += 1 << (b[k] - b[i]); else if ((i < k) && (b[i] == bits)) code += 1; } return bit_reverse(code, bits); }
__inline void _fft_tobb(fft_direction dir, cpx *seq, cpx *W, const int n) { const int n2 = (n / 2); int bit, dist, dist2; unsigned int steps; bit = log2_32(n); const int lead = 32 - bit; steps = 0; dist2 = n; dist = n2; --bit; _fft_tbbody(seq, seq, W, bit, steps, dist, dist2, n2); while (bit-- > 0) { dist2 = dist; dist = dist >> 1; _fft_tbbody(seq, seq, W, bit, ++steps, dist, dist2, n2); } bit_reverse(seq, dir, lead, n); }
inline void ntt(bool is_inv,VT &in,VT &out,int N){ int bitlen=std::__lg(N); for(int i=0;i<N;++i)out[bit_reverse(i,bitlen)]=in[i]; for(int step=2,id=1;step<=N;step<<=1,++id){ T wn=pow_mod(G,(P-1)>>id,P),wi=1,u,t; const int mh=step>>1; for(int i=0;i<mh;++i){ for(int j=i;j<N;j+=step){ u=out[j],t=wi*out[j+mh]%P; out[j]=u+t; out[j+mh]=u-t; if(out[j]>=P)out[j]-=P; if(out[j+mh]<0)out[j+mh]+=P; } wi=wi*wn%P; } } if(is_inv){ for(int i=1;i<N/2;++i)std::swap(out[i],out[N-i]); T invn=pow_mod(N,P-2,P); for(int i=0;i<N;++i)out[i]=out[i]*invn%P; } }
u8 XN297_WritePayload(u8* msg, int len) { u8 packet[32]; u8 res; if (is_xn297) { res = NRF24L01_WritePayload(msg, len); } else { int last = 0; if (xn297_addr_len < 4) { // If address length (which is defined by receive address length) // is less than 4 the TX address can't fit the preamble, so the last // byte goes here packet[last++] = 0x55; } for (int i = 0; i < xn297_addr_len; ++i) { packet[last++] = xn297_tx_addr[xn297_addr_len-i-1] ^ xn297_scramble[i]; } for (int i = 0; i < len; ++i) { // bit-reverse bytes in packet u8 b_out = bit_reverse(msg[i]); packet[last++] = b_out ^ xn297_scramble[xn297_addr_len+i]; } if (xn297_crc) { int offset = xn297_addr_len < 4 ? 1 : 0; u16 crc = initial; for (int i = offset; i < last; ++i) { crc = crc16_update(crc, packet[i]); } crc ^= xn297_crc_xorout[xn297_addr_len - 3 + len]; packet[last++] = crc >> 8; packet[last++] = crc & 0xff; } res = NRF24L01_WritePayload(packet, last); } return res; }
uint8_t XN297_WritePayload(uint8_t* msg, int len) { uint8_t buf[32]; uint8_t res; int last = 0; if (xn297_addr_len < 4) { // If address length (which is defined by receive address length) // is less than 4 the TX address can't fit the preamble, so the last // byte goes here buf[last++] = 0x55; } int i; for (i = 0; i < xn297_addr_len; ++i) { buf[last++] = xn297_tx_addr[xn297_addr_len-i-1] ^ xn297_scramble[i]; } for (i = 0; i < len; ++i) { // bit-reverse bytes in packet uint8_t b_out = bit_reverse(msg[i]); buf[last++] = b_out ^ xn297_scramble[xn297_addr_len+i]; } if (xn297_crc) { int offset = xn297_addr_len < 4 ? 1 : 0; uint16_t crc = initial; int i; for (i = offset; i < last; ++i) { crc = crc16_update(crc, buf[i]); } crc ^= xn297_crc_xorout[xn297_addr_len - 3 + len]; buf[last++] = crc >> 8; buf[last++] = crc & 0xff; } res = NRF24L01_WritePayload(buf, last); return res; }
int main(int argc, char *argv[]) { int i; uint32_t x; uint8_t ax; uint8_t bx; uint16_t ax16; uint16_t bx16; uint32_t ax32; uint32_t bx32; for (i = 0, x = 0; i < 100000; i++) { ax = top_bit_dumb(x); bx = top_bit(x); if (ax != bx) { printf("Test failed: top bit mismatch 0x%" PRIx32 " -> %u %u\n", x, ax, bx); exit(2); } ax = bottom_bit_dumb(x); bx = bottom_bit(x); if (ax != bx) { printf("Test failed: bottom bit mismatch 0x%" PRIx32 " -> %u %u\n", x, ax, bx); exit(2); } x = rand(); } for (i = 0; i < 256; i++) { ax = bit_reverse8_dumb(i); bx = bit_reverse8(i); if (ax != bx) { printf("Test failed: bit reverse 8 - %02x %02x %02x\n", i, ax, bx); exit(2); } } for (i = 0; i < 1000000; i++) from[i] = rand(); bit_reverse(to, from, 1000000); for (i = 0; i < 1000000; i++) { if (bit_reverse8_dumb(from[i]) != to[i]) { printf("Test failed: bit reverse - at %d, %02x %02x %02x\n", i, from[i], bit_reverse8(from[i]), to[i]); exit(2); } } for (i = 0; i < 256; i++) { x = i | (((i + 1) & 0xFF) << 8) | (((i + 2) & 0xFF) << 16) | (((i + 3) & 0xFF) << 24); ax32 = bit_reverse_4bytes_dumb(x); bx32 = bit_reverse_4bytes(x); if (ax32 != bx32) { printf("Test failed: bit reverse 4 bytes - %" PRIx32 " %" PRIx32 " %" PRIx32 "\n", x, ax32, bx32); exit(2); } } for (i = 0; i < 65536; i++) { ax16 = bit_reverse16_dumb(i); bx16 = bit_reverse16(i); if (ax16 != bx16) { printf("Test failed: bit reverse 16 - %x %x %x\n", i, ax16, bx16); exit(2); } } for (i = 0; i < 0x7FFFFF00; i += 127) { ax32 = bit_reverse32_dumb(i); bx32 = bit_reverse32(i); if (ax32 != bx32) { printf("Test failed: bit reverse 32 - %d %" PRIx32 " %" PRIx32 "\n", i, ax32, bx32); exit(2); } } for (i = 0; i < 256; i++) { ax = parity8(i); bx = parity8_dumb(i); if (ax != bx) { printf("Test failed: parity 8 - %x %x %x\n", i, ax, bx); exit(2); } } for (i = -1; i < 32; i++) { ax32 = most_significant_one32(1 << i); if (ax32 != (1 << i)) { printf("Test failed: most significant one 32 - %x %" PRIx32 " %x\n", i, ax32, (1 << i)); exit(2); } ax32 = least_significant_one32(1 << i); if (ax32 != (1 << i)) { printf("Test failed: least significant one 32 - %x %" PRIx32 " %x\n", i, ax32, (1 << i)); exit(2); } } for (i = 0x80000000; i < 0x800FFFFF; i++) { ax = one_bits32_dumb(i); bx = one_bits32(i); if (ax != bx) { printf("Test failed: one bits - %d, %x %x\n", i, ax, bx); exit(2); } } printf("Tests passed.\n"); return 0; }
static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type, int field_type, const uint8_t *buf, int len) { t38_terminal_state_t *s; uint8_t buf2[len]; s = (t38_terminal_state_t *) user_data; #if 0 /* In termination mode we don't care very much what the data type is. */ switch (data_type) { case T38_DATA_V21: case T38_DATA_V27TER_2400: case T38_DATA_V27TER_4800: case T38_DATA_V29_7200: case T38_DATA_V29_9600: case T38_DATA_V17_7200: case T38_DATA_V17_9600: case T38_DATA_V17_12000: case T38_DATA_V17_14400: case T38_DATA_V8: case T38_DATA_V34_PRI_RATE: case T38_DATA_V34_CC_1200: case T38_DATA_V34_PRI_CH: case T38_DATA_V33_12000: case T38_DATA_V33_14400: default: break; } #endif switch (field_type) { case T38_FIELD_HDLC_DATA: if (s->rx_len + len <= T38_MAX_HDLC_LEN) { bit_reverse(s->rx_buf + s->rx_len, buf, len); s->rx_len += len; } s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT); break; case T38_FIELD_HDLC_FCS_OK: if (len > 0) { span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK!\n"); /* The sender has incorrectly included data in this message. It is unclear what we should do with it, to maximise tolerance of buggy implementations. */ } /* Don't deal with repeats of the same field type. Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK packets, when they have sent no data for the body of the frame. */ if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) { span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC OK (%s)\n", (s->rx_len >= 3) ? t30_frametype(s->rx_buf[2]) : "???", (s->missing_data) ? "missing octets" : "clean"); t30_hdlc_accept(&(s->t30_state), !s->missing_data, s->rx_buf, s->rx_len); } s->rx_len = 0; s->missing_data = FALSE; s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT); break; case T38_FIELD_HDLC_FCS_BAD: if (len > 0) { span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD!\n"); /* The sender has incorrectly included data in this message. We can safely ignore it, as the bad FCS means we will throw away the whole message, anyway. */ } /* Don't deal with repeats of the same field type. Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_BAD packets, when they have sent no data for the body of the frame. */ if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) { span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC bad (%s)\n", (s->rx_len >= 3) ? t30_frametype(s->rx_buf[2]) : "???", (s->missing_data) ? "missing octets" : "clean"); t30_hdlc_accept(&(s->t30_state), FALSE, s->rx_buf, s->rx_len); } s->rx_len = 0; s->missing_data = FALSE; s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT); break; case T38_FIELD_HDLC_FCS_OK_SIG_END: if (len > 0) { span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK_SIG_END!\n"); /* The sender has incorrectly included data in this message. It is unclear what we should do with it, to maximise tolerance of buggy implementations. */ } /* Don't deal with repeats of the same field type. Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK_SIG_END packets, when they have sent no data for the body of the frame. */ if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) { span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC OK, sig end (%s)\n", (s->rx_len >= 3) ? t30_frametype(s->rx_buf[2]) : "???", (s->missing_data) ? "missing octets" : "clean"); t30_hdlc_accept(&(s->t30_state), !s->missing_data, s->rx_buf, s->rx_len); t30_hdlc_accept(&(s->t30_state), TRUE, NULL, PUTBIT_CARRIER_DOWN); } s->rx_len = 0; s->missing_data = FALSE; s->timeout_rx_samples = 0; break; case T38_FIELD_HDLC_FCS_BAD_SIG_END: if (len > 0) { span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD_SIG_END!\n"); /* The sender has incorrectly included data in this message. We can safely ignore it, as the bad FCS means we will throw away the whole message, anyway. */ } /* Don't deal with repeats of the same field type. Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_BAD_SIG_END packets, when they have sent no data for the body of the frame. */ if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) { span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC bad, sig end (%s)\n", (s->rx_len >= 3) ? t30_frametype(s->rx_buf[2]) : "???", (s->missing_data) ? "missing octets" : "clean"); t30_hdlc_accept(&(s->t30_state), FALSE, s->rx_buf, s->rx_len); t30_hdlc_accept(&(s->t30_state), TRUE, NULL, PUTBIT_CARRIER_DOWN); } s->rx_len = 0; s->missing_data = FALSE; s->timeout_rx_samples = 0; break; case T38_FIELD_HDLC_SIG_END: if (len > 0) { span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_SIG_END!\n"); /* The sender has incorrectly included data in this message, but there seems nothing meaningful it could be. There could not be an FCS good/bad report beyond this. */ } /* This message is expected under 2 circumstances. One is as an alternative to T38_FIELD_HDLC_FCS_OK_SIG_END - i.e. they send T38_FIELD_HDLC_FCS_OK, and then T38_FIELD_HDLC_SIG_END when the carrier actually drops. The other is because the HDLC signal drops unexpectedly - i.e. not just after a final frame. */ if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) { /* WORKAROUND: At least some Mediatrix boxes have a bug, where they can send this message at the end of non-ECM data. We need to tolerate this. We use the generic receive complete indication, rather than the specific HDLC carrier down. */ s->rx_len = 0; s->missing_data = FALSE; s->timeout_rx_samples = 0; t30_receive_complete(&(s->t30_state)); } break; case T38_FIELD_T4_NON_ECM_DATA: if (!s->rx_signal_present) { t30_non_ecm_put_bit(&(s->t30_state), PUTBIT_TRAINING_SUCCEEDED); s->rx_signal_present = TRUE; } bit_reverse(buf2, buf, len); t30_non_ecm_put_chunk(&(s->t30_state), buf2, len); s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT); break; case T38_FIELD_T4_NON_ECM_SIG_END: if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) { if (len > 0) { if (!s->rx_signal_present) { t30_non_ecm_put_bit(&(s->t30_state), PUTBIT_TRAINING_SUCCEEDED); s->rx_signal_present = TRUE; } bit_reverse(buf2, buf, len); t30_non_ecm_put_chunk(&(s->t30_state), buf2, len); } /* WORKAROUND: At least some Mediatrix boxes have a bug, where they can send HDLC signal end where they should send non-ECM signal end. It is possible they also do the opposite. We need to tolerate this, so we use the generic receive complete indication, rather than the specific non-ECM carrier down. */ t30_receive_complete(&(s->t30_state)); } s->rx_signal_present = FALSE; s->timeout_rx_samples = 0; break; case T38_FIELD_CM_MESSAGE: case T38_FIELD_JM_MESSAGE: case T38_FIELD_CI_MESSAGE: case T38_FIELD_V34RATE: default: break; } return 0; }
static void bit_reverse_buffer(uint8_t *p, uint8_t *end) { for (; p < end; ++p) *p = bit_reverse(*p); }
int t38_terminal_send_timeout(t38_terminal_state_t *s, int samples) { int len; int i; int previous; uint8_t buf[MAX_OCTETS_PER_UNPACED_CHUNK + 50]; /* Training times for all the modem options, with and without TEP */ static const int training_time[] = { 0, 0, /* T38_IND_NO_SIGNAL */ 0, 0, /* T38_IND_CNG */ 0, 0, /* T38_IND_CED */ 1000, 1000, /* T38_IND_V21_PREAMBLE */ /* TODO: 850 should be OK for this, but it causes trouble with some ATAs. Why? */ 943, 1158, /* T38_IND_V27TER_2400_TRAINING */ 708, 923, /* T38_IND_V27TER_4800_TRAINING */ 234, 454, /* T38_IND_V29_7200_TRAINING */ 234, 454, /* T38_IND_V29_9600_TRAINING */ 142, 367, /* T38_IND_V17_7200_SHORT_TRAINING */ 1393, 1618, /* T38_IND_V17_7200_LONG_TRAINING */ 142, 367, /* T38_IND_V17_9600_SHORT_TRAINING */ 1393, 1618, /* T38_IND_V17_9600_LONG_TRAINING */ 142, 367, /* T38_IND_V17_12000_SHORT_TRAINING */ 1393, 1618, /* T38_IND_V17_12000_LONG_TRAINING */ 142, 367, /* T38_IND_V17_14400_SHORT_TRAINING */ 1393, 1618, /* T38_IND_V17_14400_LONG_TRAINING */ 0, 0, /* T38_IND_V8_ANSAM */ 0, 0, /* T38_IND_V8_SIGNAL */ 0, 0, /* T38_IND_V34_CNTL_CHANNEL_1200 */ 0, 0, /* T38_IND_V34_PRI_CHANNEL */ 0, 0, /* T38_IND_V34_CC_RETRAIN */ 0, 0, /* T38_IND_V33_12000_TRAINING */ 0, 0 /* T38_IND_V33_14400_TRAINING */ }; if (s->current_rx_type == T30_MODEM_DONE || s->current_tx_type == T30_MODEM_DONE) return TRUE; s->samples += samples; t30_timer_update(&s->t30_state, samples); if (s->timeout_rx_samples && s->samples > s->timeout_rx_samples) { span_log(&s->logging, SPAN_LOG_FLOW, "Timeout mid-receive\n"); s->timeout_rx_samples = 0; t30_receive_complete(&(s->t30_state)); } if (s->timed_step == T38_TIMED_STEP_NONE) return FALSE; if (s->samples < s->next_tx_samples) return FALSE; /* Its time to send something */ switch (s->timed_step) { case T38_TIMED_STEP_NON_ECM_MODEM: /* Create a 75ms silence */ if (s->t38.current_tx_indicator != T38_IND_NO_SIGNAL) t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count); s->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_2; s->next_tx_samples += ms_to_samples(75); break; case T38_TIMED_STEP_NON_ECM_MODEM_2: /* Switch on a fast modem, and give the training time to complete */ t38_core_send_indicator(&s->t38, s->next_tx_indicator, s->indicator_tx_count); s->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_3; s->next_tx_samples += ms_to_samples(training_time[s->next_tx_indicator << 1]); break; case T38_TIMED_STEP_NON_ECM_MODEM_3: /* Send a chunk of non-ECM image data */ /* T.38 says it is OK to send the last of the non-ECM data in the signal end message. However, I think the early versions of T.38 said the signal end message should not contain data. Hopefully, following the current spec will not cause compatibility issues. */ len = t30_non_ecm_get_chunk(&s->t30_state, buf, s->octets_per_data_packet); bit_reverse(buf, buf, len); if (len >= s->octets_per_data_packet) { s->next_tx_samples += ms_to_samples(s->ms_per_tx_chunk); t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_T4_NON_ECM_DATA, buf, len, DATA_TX_COUNT); } else { t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_T4_NON_ECM_SIG_END, buf, len, s->data_end_tx_count); /* This should not be needed, since the message above indicates the end of the signal, but it seems like it can improve compatibility with quirky implementations. */ t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count); s->timed_step = T38_TIMED_STEP_NONE; t30_send_complete(&(s->t30_state)); } break; case T38_TIMED_STEP_HDLC_MODEM: /* Send HDLC preambling */ t38_core_send_indicator(&s->t38, s->next_tx_indicator, s->indicator_tx_count); s->next_tx_samples += ms_to_samples(training_time[s->next_tx_indicator << 1]); s->timed_step = T38_TIMED_STEP_HDLC_MODEM_2; break; case T38_TIMED_STEP_HDLC_MODEM_2: /* Send a chunk of HDLC data */ i = s->octets_per_data_packet; if (i >= (s->tx_len - s->tx_ptr)) { i = s->tx_len - s->tx_ptr; s->timed_step = T38_TIMED_STEP_HDLC_MODEM_3; } t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_HDLC_DATA, &s->tx_buf[s->tx_ptr], i, DATA_TX_COUNT); s->tx_ptr += i; s->next_tx_samples += ms_to_samples(s->ms_per_tx_chunk); break; case T38_TIMED_STEP_HDLC_MODEM_3: /* End of HDLC frame */ previous = s->current_tx_data_type; s->tx_ptr = 0; s->tx_len = 0; t30_send_complete(&s->t30_state); if (s->tx_len < 0) { t38_core_send_data(&s->t38, previous, T38_FIELD_HDLC_FCS_OK_SIG_END, NULL, 0, s->data_end_tx_count); /* We have already sent T38_FIELD_HDLC_FCS_OK_SIG_END. It seems some boxes may not like us sending a T38_FIELD_HDLC_SIG_END at this point. Just say there is no signal. */ t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count); s->tx_len = 0; t30_send_complete(&s->t30_state); if (s->tx_len) s->timed_step = T38_TIMED_STEP_HDLC_MODEM; } else { t38_core_send_data(&s->t38, previous, T38_FIELD_HDLC_FCS_OK, NULL, 0, DATA_TX_COUNT); if (s->tx_len) s->timed_step = T38_TIMED_STEP_HDLC_MODEM_2; } s->next_tx_samples += ms_to_samples(s->ms_per_tx_chunk); break; case T38_TIMED_STEP_CED: /* It seems common practice to start with a no signal indicator, though this is not a specified requirement. Since we should be sending 200ms of silence, starting the delay with a no signal indication makes sense. We do need a 200ms delay, as that is a specification requirement. */ s->timed_step = T38_TIMED_STEP_CED_2; s->next_tx_samples = s->samples + ms_to_samples(200); t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count); s->current_tx_data_type = T38_DATA_NONE; break; case T38_TIMED_STEP_CED_2: /* Initial 200ms delay over. Send the CED indicator */ s->next_tx_samples = s->samples + ms_to_samples(3000); s->timed_step = T38_TIMED_STEP_PAUSE; t38_core_send_indicator(&s->t38, T38_IND_CED, s->indicator_tx_count); s->current_tx_data_type = T38_DATA_NONE; break; case T38_TIMED_STEP_CNG: /* It seems common practice to start with a no signal indicator, though this is not a specified requirement. Since we should be sending 200ms of silence, starting the delay with a no signal indication makes sense. We do need a 200ms delay, as that is a specification requirement. */ s->timed_step = T38_TIMED_STEP_CNG_2; s->next_tx_samples = s->samples + ms_to_samples(200); t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count); s->current_tx_data_type = T38_DATA_NONE; break; case T38_TIMED_STEP_CNG_2: /* Initial short delay over. Send the CNG indicator */ s->timed_step = T38_TIMED_STEP_NONE; t38_core_send_indicator(&s->t38, T38_IND_CNG, s->indicator_tx_count); s->current_tx_data_type = T38_DATA_NONE; break; case T38_TIMED_STEP_PAUSE: /* End of timed pause */ s->timed_step = T38_TIMED_STEP_NONE; t30_send_complete(&s->t30_state); break; } return FALSE; }
void FFT(double *x_r,double *x_i,double *y_r,double *y_i,int N) { int i,j,k,t,p = 2,M = N; double theta,w_r,w_i,temp_r[4],temp_i[4]; bit_reverse(x_r,x_i,y_r,y_i,N); for(i = 1 ; i < N ; i*=p) { t = 0; if(M%2 == 0) p = 2; else { if(M%3 == 0) p =3; else p = 5; } theta = -2*M_PI/(p*i); while(t < N) { for(j = 0 ; j < i ; j++) { w_r = cos(j*theta); w_i = sin(j*theta); switch(p) { case 2: temp_r[0] = w_r*y_r[j+i+t] - w_i*y_i[j+i+t]; temp_i[0] = w_i*y_r[j+i+t] + w_r*y_i[j+i+t]; y_r[j+i+t] = y_r[j+t] - temp_r[0]; y_i[j+i+t] = y_i[j+t] - temp_i[0]; y_r[j+t]+=temp_r[0]; y_i[j+t]+=temp_i[0]; break; case 3: temp_r[0] = w_r*y_r[j+i+t] - w_i*y_i[j+i+t]; temp_i[0] = w_i*y_r[j+i+t] + w_r*y_i[j+i+t]; temp_r[1] = (w_r*w_r - w_i*w_i)*y_r[j+2*i+t] - 2*w_r*w_i*y_i[j+2*i+t]; temp_i[1] = 2*w_r*w_i*y_r[j+2*i+t] + (w_r*w_r - w_i*w_i)*y_i[j+i+t]; y_r[j+2*i+t] = y_r[j+t] - 0.5*(temp_r[0] + temp_r[1]) - 0.86602540378443864676372317075294*(temp_i[0] - temp_i[1]); y_i[j+2*i+t] = y_i[j+t] - 0.5*(temp_i[0] + temp_i[1]) + 0.86602540378443864676372317075294*(temp_r[0] - temp_r[1]); y_r[j+i+t] = y_r[j+t] - 0.5*(temp_r[0] + temp_r[1]) + 0.86602540378443864676372317075294*(temp_i[0] - temp_i[1]); y_i[j+i+t] = y_i[j+t] - 0.5*(temp_i[0] + temp_i[1]) - 0.86602540378443864676372317075294*(temp_r[0] - temp_r[1]); y_r[j+t] = y_r[j+t] + temp_r[0] + temp_r[1]; y_i[j+t] = y_i[j+t] + temp_i[0] + temp_i[1]; break; case 5: temp_r[0] = w_r*y_r[j+i+t] - w_i*y_i[j+i+t]; temp_i[0] = w_i*y_r[j+i+t] + w_r*y_i[j+i+t]; for(k = 2 ; k < 5 ; k++) { temp_r[k-1] = cos(j*k*theta)*y_r[j+k*i+t] - sin(j*k*theta)*y_i[j+k*i+t]; temp_i[k-1] = sin(j*k*theta)*y_r[j+k*i+t] + cos(j*k*theta)*y_i[j+k*i+t]; } y_r[j+4*i+t] = y_r[j+t] + 0.30901699437494745126286943559535*(temp_r[0]+temp_r[3]) - 0.95105651629515353118193843329209*(temp_i[0]-temp_i[3]) - 0.80901699437494734024056697307969*(temp_r[1]+temp_r[2]) - 0.58778525229247324812575925534475*(temp_i[1]-temp_i[2]); y_i[j+4*i+t] = y_i[j+t] + 0.30901699437494745126286943559535*(temp_i[0]+temp_i[3]) + 0.95105651629515353118193843329209*(temp_r[0]-temp_r[3]) - 0.80901699437494734024056697307969*(temp_i[1]+temp_i[2]) + 0.58778525229247324812575925534475*(temp_r[1]-temp_r[2]); y_r[j+3*i+t] = y_r[j+t] - 0.80901699437494734024056697307969*(temp_r[0]+temp_r[3]) - 0.58778525229247324812575925534475*(temp_i[0]-temp_i[3]) + 0.30901699437494745126286943559535*(temp_r[1]+temp_r[2]) + 0.95105651629515353118193843329209*(temp_i[1]-temp_i[2]); y_i[j+3*i+t] = y_i[j+t] - 0.80901699437494734024056697307969*(temp_i[0]+temp_i[3]) + 0.58778525229247324812575925534475*(temp_r[0]-temp_r[3]) + 0.30901699437494745126286943559535*(temp_i[1]+temp_i[2]) - 0.95105651629515353118193843329209*(temp_r[1]-temp_r[2]); y_r[j+2*i+t] = y_r[j+t] - 0.80901699437494734024056697307969*(temp_r[0]+temp_r[3]) + 0.58778525229247324812575925534475*(temp_i[0]-temp_i[3]) + 0.30901699437494745126286943559535*(temp_r[1]+temp_r[2]) - 0.95105651629515353118193843329209*(temp_i[1]-temp_i[2]); y_i[j+2*i+t] = y_i[j+t] - 0.80901699437494734024056697307969*(temp_i[0]+temp_i[3]) - 0.58778525229247324812575925534475*(temp_r[0]-temp_r[3]) + 0.30901699437494745126286943559535*(temp_i[1]+temp_i[2]) + 0.95105651629515353118193843329209*(temp_r[1]-temp_r[2]); y_r[j+i+t] = y_r[j+t] + 0.30901699437494745126286943559535*(temp_r[0]+temp_r[3]) + 0.95105651629515353118193843329209*(temp_i[0]-temp_i[3]) - 0.80901699437494734024056697307969*(temp_r[1]+temp_r[2]) + 0.58778525229247324812575925534475*(temp_i[1]-temp_i[2]); y_i[j+i+t] = y_i[j+t] + 0.30901699437494745126286943559535*(temp_i[0]+temp_i[3]) - 0.95105651629515353118193843329209*(temp_r[0]-temp_r[3]) - 0.80901699437494734024056697307969*(temp_i[1]+temp_i[2]) - 0.58778525229247324812575925534475*(temp_r[1]-temp_r[2]); y_r[j+t] = y_r[j+t] + temp_r[0] + temp_r[1] + temp_r[2] + temp_r[3]; y_i[j+t] = y_i[j+t] + temp_i[0] + temp_i[1] + temp_i[2] + temp_i[3]; break; } } t = t + p*i; } M = M/p; } return; }
void zn_array_mul_fft_dft (ulong* res, const ulong* op1, size_t n1, const ulong* op2, size_t n2, unsigned lgT, const zn_mod_t mod) { ZNP_ASSERT (mod->m & 1); ZNP_ASSERT (n2 >= 1); ZNP_ASSERT (n1 >= n2); if (lgT == 0) { // no layers of DFT; just call usual FFT routine int sqr = (op1 == op2) && (n1 == n2); ulong x = zn_array_mul_fft_fudge (n1, n2, sqr, mod); zn_array_mul_fft (res, op1, n1, op2, n2, x, mod); return; } unsigned lgM, lgK; // number of pmf_t coefficients for each input poly ulong m1, m2; // figure out how big the transform needs to be mul_fft_params (&lgK, &lgM, &m1, &m2, n1, n2); // number of pmf_t coefficients for output poly ulong m = m1 + m2 - 1; ulong M = 1UL << lgM; ulong K = 1UL << lgK; ptrdiff_t skip = M + 1; size_t n3 = n1 + n2 - 1; // Split up transform into length K = U * T, i.e. U columns and T rows. if (lgT >= lgK) lgT = lgK; unsigned lgU = lgK - lgT; ulong U = 1UL << lgU; ulong T = 1UL << lgT; // space for two input rows, and one partial row pmfvec_t in1, in2, part; pmfvec_init (in1, lgU, skip, lgM, mod); pmfvec_init (in2, lgU, skip, lgM, mod); pmfvec_init (part, lgU, skip, lgM, mod); // the virtual pmfvec_t that we use for the column DFTs virtual_pmfvec_t col; virtual_pmfvec_init (col, lgT, lgM, mod); // zero the output zn_array_zero (res, n3); long i, j, k; int which; // Write m = U * mT + mU, where 0 <= mU < U ulong mU = m & (U - 1); ulong mT = m >> lgU; // for each row (beginning with the last partial row if it exists).... for (i = mT - (mU == 0); i >= 0; i--) { ulong i_rev = bit_reverse (i, lgT); // for each input array.... for (which = 0; which < 2; which++) { pmfvec_struct* in = which ? in2 : in1; const ulong* op = which ? op2 : op1; size_t n = which ? n2 : n1; pmf_t p = in->data; for (j = 0; j < U; j++, p += in->skip) { // compute the i-th row of the j-th column as it would look after // the column FFTs, using naive DFT pmf_zero (p, M); ulong r = i_rev << (lgM - lgT + 1); for (k = 0; k < T; k++) { merge_chunk_to_pmf (p, op, n, (k * U + j) << (lgM - 1), M, mod); pmf_rotate (p, -r); } pmf_rotate (p, (i_rev * j) << (lgM - lgK + 1)); } // Now we've got the whole row; run FFT on the row pmfvec_fft (in, (i == mT) ? mU : U, U, 0); } if (i == mT) { // pointwise multiply the two partial rows pmfvec_mul (part, in1, in2, mU, i == 0); // remove fudge factor pmfvec_scalar_mul (part, mU, pmfvec_mul_fudge (lgM, 0, mod)); // zero remainder of the partial row; we will subsequently add // in contributions from the vertical IFFTs when we process the other // rows. for (j = mU; j < U; j++) pmf_zero (part->data + part->skip * j, M); } else { // pointwise multiply the two rows pmfvec_mul (in1, in1, in2, U, i == 0); // remove fudge factor pmfvec_scalar_mul (in1, U, pmfvec_mul_fudge (lgM, 0, mod)); // horizontal IFFT this row pmfvec_ifft (in1, U, 0, U, 0); // simulate vertical IFFTs with DFTs for (j = 0; j < U; j++) { virtual_pmfvec_reset (col); virtual_pmf_import (col->data[i], in1->data + in1->skip * j); virtual_pmfvec_ifft (col, mT + (j < mU), (j >= mU) && mU, j << (lgM + 1 - lgK)); if ((j >= mU) && mU) { // add contribution to partial row (only for rightmost columns) pmf_t src = virtual_pmf_export (col->data[mT]); if (src) pmf_add (part->data + part->skip * j, src, M, mod); } // add contributions to output for (k = 0; k < mT + (j < mU); k++) merge_chunk_from_pmf (res, n3, virtual_pmf_export (col->data[k]), (k * U + j) * M/2, M, mod); } } } // now finish off the partial row if (mU) { // horizontal IFFT partial row pmfvec_ifft (part, mU, 0, U, 0); // simulate leftmost vertical IFFTs for (j = 0; j < mU; j++) { virtual_pmfvec_reset (col); virtual_pmf_import (col->data[mT], part->data + part->skip * j); virtual_pmfvec_ifft (col, mT + 1, 0, j << (lgM + 1 - lgK)); // add contributions to output for (k = 0; k <= mT; k++) merge_chunk_from_pmf (res, n3, virtual_pmf_export (col->data[k]), (k * U + j) * M/2, M, mod); } } // normalise result zn_array_scalar_mul (res, res, n3, zn_mod_pow2 (-lgK, mod), mod); virtual_pmfvec_clear (col); pmfvec_clear (part); pmfvec_clear (in2); pmfvec_clear (in1); }