/*
 Converts data address as specified in LHCb-2003-041
 into the straw numbering scheme used by the OT reconstruction

 The conversion is performed by means of an algorithm
 based on the channel address (quarter, layer, otis, otis_channel)
 that is carried by the data itself (see https://edms.cern.ch/document/833984)
 As such, it is intrinsically unreliable. A lookup table, implemented
 elsewhere, is certainly to be preferred.

 More details on numbering schemes can be found on the OT web page
 http://www.nikhef.nl/pub/experiments/bfys/lhcb/outerTracker/NamingConventions/FE-Channels/
 */
#ifndef _CH_ALGO_H
#define _CH_ALGO_H    1

#include	<stdlib.h>

inline unsigned int ch_algo(
	const unsigned int quarter, const unsigned int layer,
	const unsigned int module,
	const unsigned int otis, const unsigned int o_chan
)
{
	int q	= (quarter & 0x3) / 0x2 ;	// top or bottom ??
	int l	= (layer & 0x3) & 0x1 ;	// lower Z or higher Z ??
	int o	= otis & 0x3 ;
	int c	= o_chan & 0x1f ;

	// re-arrange OTIS sequence according to whether
	int os	= (o&0x1) - ((1-o)&0x1) ;
	int wo	= o / 2 ; // OTIS 0|1 or 2|3 ??
	int wq	= q * (1-wo) + (1-q) * wo ;

	int o_lu = (1-l) * (o - wq * os) + l * (3 - (o - wq * os)) ;

	// small modules only use OTIS 0 and 3
	if ( ((quarter & 0x1) == 0) && module == 9 )
		o_lu /= 2 ;

	// re-number channels
	int r = abs(q - l) ;	// layer/quadrant combination

	unsigned int c_lu = o_lu * 32 +		// offset
	((1-r) * wo + r * (1-wo)) * (32-c) +	// reverse numbering
	((1-r) * (1-wo) + r * wo) * (c+1) ;	// direct numbering

	// small modules only use OTIS 0 and 3
	if ( ((quarter & 0x1) == 0) && module == 9  && (otis==1 || otis==2))
		c_lu = 999 ;

	return(c_lu) ;
}

#endif /* ch_algo.h */

