#ifndef mac_common_tonemap_h #define mac_common_tonemap_h /* Cesar project {{{ * * Copyright (C) 2007 Spidcom * * <<>> * * }}} */ /** * \file mac/common/tonemap.h * \brief Tone maps handling functions. * \ingroup mac_common * * Tone maps are shared between PB Processing, Channel Access and control * plane. */ #include "hal/phy/defs.h" #include "lib/blk.h" #include "lib/list.h" /** * Tone map indexes (TMI). */ enum tonemap_index_t { /** First tone map index negotiated. */ TONEMAP_INDEX_NEGOTIATED_FIRST = 4, /** Number of possible TMI (including, the first four). */ TONEMAP_INDEX_NB = 32, /** Invalid index. */ TONEMAP_INDEX_NULL = 32, /** Initial state for a tonemap set. */ TONEMAP_INDEX_INITIAL_START = 0xfd, /** Error state for a tonemap set. */ TONEMAP_INDEX_INITIAL_ERROR = 0xfc, /** SOUND complete state for a tonemap set. */ TONEMAP_INDEX_INITIAL_SOUND_COMPLETE = 0xf0, /** Unavailable interval. */ TONEMAP_INDEX_INTERVAL_UNAVAILABLE = 0xfe, /** Unusable interval. */ TONEMAP_INDEX_INTERVAL_UNUSABLE = 0xff, /** SOUND complete state for an interval. */ TONEMAP_INDEX_INTERVAL_SOUND_COMPLETE = 0xf0, }; /** * Is the tone map index is a negotiated one? * \param tmi the tone map index to check. * \return true if the tone map index is a negotiated one, false otherwise. */ #define TONEMAP_INDEX_IS_NEGOTIATED(tmi) \ ((tmi >= TONEMAP_INDEX_NEGOTIATED_FIRST) && (tmi< TONEMAP_INDEX_NB)) /** Sound reason code. */ enum tonemap_sound_reason_code_t { TONEMAP_SRC_TMI_MIN = 0x04, TONEMAP_SRC_TMI_MAX = 0x1f, TONEMAP_SRC_ERROR = 0xfc, TONEMAP_SRC_INITIAL = 0xfd, TONEMAP_SRC_INTERVAL_UNAVAILABLE = 0xfe, TONEMAP_SRC_INTERVAL_UNUSABLE = 0xff, /** Invalid SRC. */ TONEMAP_SRC_NULL = 0, }; typedef enum tonemap_sound_reason_code_t tonemap_sound_reason_code_t; /** Maximum number of tonemap intervals. */ #define TONEMAP_INTERVAL_NB 32 /** Maximum number of active tone maps. */ #define TONEMAP_MAX 7 /** Maximum number of bits per symbol with the best possible tonemask and * modulation. */ #define TONEMAP_BITS_PER_SYMBOL_MAX (10 * PHY_CARRIER_NB) /** Tonemaps life duration since last refresh before it becomes stale */ #define TONEMAPS_LIFE_DURATION_S 30 /** * Position of the header of the tone map in the allocated data. * To store a tone map, two blocks of 512 bytes are required. The structure is * store on the second half of the second blocks. * This position is an absolute position in the second block. */ #define TONEMAP_HEADER_POS_BYTE (BLK_SIZE / 2) /** * Number of frames sound to receive before the PBProc send a sound complete * flag to the peer. */ #define TONEMAP_SOUND_FRAME_COUNTER 22 /** * Tone map in use flag. */ #define TONEMAP_IN_USE -1 /** * Default time to wait before deleting a tone map. * This time is not exact and the value setted is the maximum time that will * be taken to remove the tone map and the value minus one is the minimum time * to wait. */ #define TONEMAP_RELEASE_TIMER_S 2 /** * Default PB error rate used for BLE computation. */ #define TONEMAP_P_PBERROR_DEFAULT_UF32 CONST_UF32 (0.0) /** Define a tone map interval. */ struct tonemap_interval_t { /** Interval end offset. */ u16 end_offset_atu; /** Interval TMI, 0-31, unavailable, unusable or sound complete. */ u8 tmi; }; typedef struct tonemap_interval_t tonemap_interval_t; /** * A set of intervals. */ struct tonemap_intervals_t { /** * Intervals version. * This purpose of this field is to have a system for the synchronisation * between the PBProc and the CE. A change in the intervals list done by * the CE will create a new version. * This change is handle by the mac_interval_commit_changes function which * will update the version while swapping intervals list. */ u8 version; /** * Count of intervals. * 0 is a valid number (0 intervals). * 32 is maximum value of this field. * Note that if the value is different from zero, you need to remove 1 to * have the correct index in the table of intervals. */ u8 intervals_nb; /** Intervals. */ tonemap_interval_t interval[TONEMAP_INTERVAL_NB]; }; typedef struct tonemap_intervals_t tonemap_intervals_t; /** Define a tone map. */ struct tonemap_t { /** Can be used in the contention period. */ bool cpf; /** FEC type, 1/2 or 16/21. */ phy_fecrate_t fecrate; /** Guard interval. */ phy_gil_t gil; /** Computed BLE in FC format. */ u8 ble; /** Block descriptors to be used with TM DMA for the first block. The * others blocks are referenced by the \c next field. */ blk_t *tmdma_desc_head; /** Number of bits per data symbol. */ uint bits_per_symbol; /** Number of bits per PB. */ uint bits_per_pb[PHY_PB_SIZE_NONE]; /** Data length of a frame with one PB. */ uint one_pb_data_tck; /** Phy parameters (modulation, FEC rate, PB size). */ u32 phy_combo_params[PHY_PB_SIZE_NONE]; /** Number of TCC half iterations for PB 520. */ uint tcc_halfit; /** * Tone map marked as released. * This flag is used in the CE RX. When the CE RX decides to stop using a * tone map, it marks it as released and send a MME to the peer to notify * it. But the peer can still use it. This flag will let the PBProc still * uses it but prevents the CE RX to use it. * If set to TONEMAP_IN_USE, the tone map is in use. If set to a different * value, it corresponds to the number of second remaining before * deletion. When this value reaches 0, the tone map should be deleted. */ s8 released; /** * BER target the tone map should respect (input BER target of the bit * loading algorithm). */ u64 ber_target; /** * BER target reached by the tone map (output BER target of the bit * loading algorithm). */ u64 ber_target_reached; /** * Number of frames handled by this tone map. * This counter can overflow. It also count only frame handled by the CE * for this tone map (the CE can drop some frames if memory is too low). */ u32 nb_frame; /** * Number of PB handled by this tone map. * This counter can overflow. It also count only PB handled by the CE for * this tone map, even the one with a CRC false (the CE can drop some * measures if memory is too low). */ u32 nb_pb; /** * Node to link the tonemaps in the release list. */ list_node_t release_link; }; typedef struct tonemap_t tonemap_t; /** Define a set of tone maps and channel adaptation parameters. */ struct tonemaps_t { /** Maximum FL_AV, [0x07a2, 0x0fff]. */ uint max_fl_av; /** RIFS for one symbol. Use default RIFS_AV_default for zero symbols. * Values should be in interval [0x18, 0x7d]. */ uint rifs_av_one_sym_tck; /** RIFS for two symbols. */ uint rifs_av_two_sym_tck; /** RIFS for more than two symbols. */ uint rifs_av_g2_sym_tck; /** Maximum tone maps the receiver can support on this channel. */ uint max_tm; /** Default TMI for contention period, 0-31, start, error or sound * complete. */ uint default_tmi; /** Use default tone map instead of sending sound in CP. */ bool scl_cp; /** Use default tone map instead of sending sound in CFP. */ bool scl_cfp; /** Remaining seconds before expirations of the tone maps. */ uint expiration_s; /** Defined tone maps or NULL if invalid. */ tonemap_t *tm[TONEMAP_INDEX_NB]; /** SOUND complete bitmap for tone maps. If the tone map is not valid, a * one in the bitmap means that sound is complete for this tone map. */ u32 tm_sound_complete_bitmap; /** * They are two intervals lists : one which is the current used one (which * can not be modified) and the temporary one (for modification). * In fact, when you commit new changes (using * mac_interval_commit_changes), the role of lists inverts itself : * pointers are swapped in order to make an atomic changes. */ tonemap_intervals_t swap_intervals[2]; /** * Current intervals list. * The content of the pointer can not be changed. * You must change the content of the intervals_temp and then use the * mac_interval_commit_changes to atomically swap the intervals lists. */ tonemap_intervals_t *intervals; /** * Temporary list of intervals. * The content of this pointer can be change, until you use the function * mac_interval_commit_changes to commit your changes. After, you must use * the new value of intervals_temp. */ tonemap_intervals_t *intervals_temp; /** * Timer handler to refresh timer expiration. */ uint refresh_counter_s; /** * Sound frame counter. * This variable is shared between the CE RX and the PBProc to know how * many sound frames we want. It is is initialized to a predefined value * when allocating the tone maps and decremented by the PBProc each time a * sound frame is received. When it reach zero, the PBProc send a sound * complete flag to stop receiving sound frames. * In iterative mode, it should be reseted to the predefined value when we * want to receive some sounds frame. */ u8 sound_frame_counter; }; typedef struct tonemaps_t tonemaps_t; /** Context of the tonemaps to be released. */ typedef list_t tonemap_release_list_t; BEGIN_DECLS /** * Allocate a tone map. * \return a pointer to the newly allocated tone map. */ tonemap_t * tonemap_alloc (void); /** * Free a tone map. * \param tm tone map to free. * This function immediately releases the memory used by a tonemap. It must * only be used for tonemaps that has not been recorded in a station set of * tonemaps. */ void tonemap_free (tonemap_t *tm); /** * Mark a tone map as need to be released. * \param tms set of tone maps. * \param tmi tone map index to release. * This function simply mark a tone map as been released. The tone map will be * deleted later (when it is "not in use any more" - after garbage cleaning). */ void tonemap_disable (tonemaps_t *tms, u8 tmi); /** * Remove tone map from station set and add it to release list. * \param tms set of tone maps * \param tmi tone map index to remove * \param tm_release_list where to add the removed tone map */ void tonemap_release (tonemaps_t *tms, u8 tmi, tonemap_release_list_t *tm_release_list); /** * Initialize a release list. * \param tm_release_list the list to initialize */ extern inline void tonemap_release_list_init (tonemap_release_list_t *tm_release_list) { list_init (tm_release_list); } /** * Parse the release list to free the expired tonemaps. * \param tm_release_list release list to clean * \return true if list is now empty */ bool tonemap_release_list_clean (tonemap_release_list_t *tm_release_list); /** * Copy one tone map to another. * \param dst an empty tone map to copy tone map to (it should be * allocated). * \param src the tone map to copy. */ void tonemap_copy (tonemap_t *dst, tonemap_t *src); /** * Get a tone map from its TMI. * \param tms set of tone maps. * \param tmi tone map index to get. * \return the tone map corresponding to the TMI, or NULL if it does not * exist or marked as released. * It is better to use this function to access a specific tone map rather than * using the table. It will correctly handle the released flag. */ tonemap_t * tonemap_get (tonemaps_t *tms, u8 tmi); /** * Get the number of allocated tone map. * \param tms tone maps structure where to count for allocated tone map. * \return count of tone map allocated. */ u8 tonemaps_allocated_count (const tonemaps_t *tms); /** * Macros to go through a tone map for read/write access. * \param tonemap the tone map to read (tonemap_t). * \param tonemask the tone map to read (u32 *). * See and use TONEMAP_READ_BEGIN and TONEMAP_WRITE_BEGIN and * TONEMAP_READ_WRITE_BEGIN. */ #define TONEMAP_ACCESS_BEGIN(tonemap, tonemask) \ do { \ /* Store tone map. */ \ tonemap_t *tonemap_ = (tonemap); \ /* Index in the tone map in term of tone words. */ \ uint tm_tone_word_index_; \ /* Maximum index in the tone map in term of tone words. \ * This will evolve during the loop (because the block will change). */ \ uint tm_tone_word_max_; \ /* Index by group of 8 tones. A mask is stored on 1 bit. Every 32 bits, \ * of tone masks, we have 32 tones. A tone is stored on 4 bits. On a \ * word of tone map, we have 8 tones. This index represents the current \ * words (of 8 tones) of the tone map by group of 4. */ \ uint tm_tone_group_by_word_mask_; \ /* Pointer to the current word of 4 tones of the tone map. */ \ u32 *tm_; \ /* Pointer to the current word of 32 tones mask. */ \ u32 *tk_; \ \ /* Initialization. */ \ tm_ = (u32 *) tonemap_->tmdma_desc_head->data; \ tk_ = (tonemask); \ \ /* This loop will go through each block. So basically, it will be run \ * only two times. */ \ for (tm_tone_word_index_ = 0, tm_tone_word_max_ = BLK_SIZE / 4; \ tm_tone_word_index_ < PHY_TONEMAP_WORDS; \ /* After the list loop is over, second loop must be called until no \ * more word remains. */ \ tm_tone_word_max_ = PHY_TONEMAP_WORDS) \ { \ /* Loop on the whole current block until we have read all the words \ of tone. */ \ for (; tm_tone_word_index_ < tm_tone_word_max_;) \ { \ /* Current 32 masks. */ \ u32 tk_cur_ = *tk_; \ /* This loop goes through each word of tone map by group of 4. \ */ \ for (tm_tone_group_by_word_mask_ = 0; \ tm_tone_group_by_word_mask_ < 4; \ /* Increase tm_tone_word_index_ too. */ \ tm_tone_group_by_word_mask_++, tm_tone_word_index_++) \ { #define TONEMAP_ACCESS_MIDDLE \ } \ /* Next group of 32 masks. */ \ tk_++; #define TONEMAP_ACCESS_END \ } \ /* Get next block. */ \ tm_ = (u32 *) tonemap_->tmdma_desc_head->next->data; \ } \ } while (0) /** * Macro to through each tone of a tone map, using a mask and read a tone. * \param tonemap the tone map to read (tonemap_t). * \param tonemask the tone map to read (u32 *). * \param tone the tone read. * This macro is divided in two macros. Here is an example of how to use it. * \code * tonemap_t *tm; * tonemask_info_t ti; * uint tone; * TONEMAP_READ_BEGIN (tm, ti.tonemask, tone) * { * printf ("%d\n", tone); * } * TONEMAP_READ_END; * \endcode */ #define TONEMAP_READ_BEGIN(tonemap, tonemask, tone) \ TONEMAP_ACCESS_BEGIN ((tonemap), (tonemask)) \ { \ /* Index of a tone in a word of tones. */ \ uint tm_tone_index_; \ /* The 8 tones of the word. */ \ u32 tm_tone_ = *tm_; \ for (tm_tone_index_ = 8; \ tm_tone_index_ > 0; \ tm_tone_index_--) \ { \ if (!(tk_cur_ & 0x1)) \ { \ (tone) = tm_tone_ & 0xF; #define TONEMAP_READ_END \ } \ /* Next tone. */ \ tm_tone_ >>= 4; \ /* Next tone mask bit. */ \ tk_cur_ >>= 1; \ } \ /* Next group of tone (grouped by word). */ \ tm_++; \ } \ TONEMAP_ACCESS_MIDDLE \ TONEMAP_ACCESS_END /** * Macro to through each tone of a tone map, using a mask and write a tone. * \param tonemap the tone map to read (tonemap_t). * \param tonemask the tone map to read (u32 *). * This macro is divided in three macros. Here is an example of how to use it. * \code * tonemap_t *tm; * tonemask_info_t ti; * uint tone; * TONEMAP_WRITE_BEGIN (tm, ti.tonemask) * { * TONEMAP_WRITE_MOD = 1; * } * TONEMAP_WRITE_END; * \endcode * * If you do not write anything in the loop, everything will be set to 0. */ #define TONEMAP_WRITE_BEGIN(tonemap, tonemask) \ TONEMAP_ACCESS_BEGIN ((tonemap), (tonemask)) \ { \ /* Index of a tone in a word of tones. */ \ uint tm_tone_index_; \ /* The 8 tones of the word. */ \ u32 tm_word_tone_ = 0; \ for (tm_tone_index_ = 0; \ tm_tone_index_ < 32; \ tm_tone_index_ += 4) \ { \ /* The current tone. */ \ if (!(tk_cur_ & 0x1)) \ { \ #define TONEMAP_WRITE_MOD(mod) \ do \ { \ /* Write tone. */ \ tm_word_tone_ |= (mod) << (tm_tone_index_); \ } while (0) #define TONEMAP_WRITE_END \ } \ /* Next tone mask bit. */ \ tk_cur_ >>= 1; \ } \ *tm_ = tm_word_tone_; \ /* Next group of tone (grouped by word). */ \ tm_++; \ } \ TONEMAP_ACCESS_MIDDLE \ TONEMAP_ACCESS_END /** * Macro to through each unmasked tone of a tone map and read/write a tone. * \param tonemap the tone map to read (tonemap_t). * \param tonemask the tone map to read (u32 *). * \param tone the tone read. * This macro is divided in three macros. Here is an example of how to use it. * \code * tonemap_t *tm; * tonemask_info_t ti; * uint tone; * TONEMAP_READ_WRITE_BEGIN (tm, ti.tonemask, mod) * { * if (tone = 1) * TONEMAP_READ_WRITE_MOD (2); * } * TONEMAP_READ_WRITE_END; * \endcode */ #define TONEMAP_READ_WRITE_BEGIN(tonemap, tonemask, tone) \ TONEMAP_ACCESS_BEGIN ((tonemap), (tonemask)) \ { \ /* Index of a tone in a word of tones. */ \ uint tm_tone_index_; \ /* The 8 tones of the word. */ \ u32 tm_tone_ = *tm_; \ u32 tm_word_tone_ = tm_tone_; \ for (tm_tone_index_ = 0; \ tm_tone_index_ < 32; \ tm_tone_index_ += 4) \ { \ if (!(tk_cur_ & 0x1)) \ { \ (tone) = tm_tone_ & 0xF; #define TONEMAP_READ_WRITE_MOD(mod) \ do \ { \ /* Write tone. */ \ tm_word_tone_ &= ~(0xf << (tm_tone_index_)); \ tm_word_tone_ |= (mod) << (tm_tone_index_); \ } while (0) #define TONEMAP_READ_WRITE_END \ } \ /* Next tone. */ \ tm_tone_ >>= 4; \ /* Next tone mask bit. */ \ tk_cur_ >>= 1; \ } \ *tm_ = tm_word_tone_; \ /* Next group of tone (grouped by word). */ \ tm_++; \ } \ TONEMAP_ACCESS_MIDDLE \ TONEMAP_ACCESS_END /** * Get the value of a tone. * \param tm the tone map. * \param index the index of the tone to get. * \param word_ptr pointer to the word where the tone is stored. * * This function is not optimized when accessing value one by one. It is a * random access. */ u8 tonemap_get_tone (tonemap_t *tm, uint index, u32 **word_ptr); /** * Get a pointer to the corresponding word where the tone is. * \param tm the tone map. * \param index the index of the tone. * \return the word where the tone is stored. */ extern inline u32 * tonemap_get_tone_word (tonemap_t *tm, uint index) { /* Check parameters. */ dbg_assert (tm); dbg_assert (index < PHY_CARRIER_NB); /* Get the block where the tone is stored. */ blk_t *blk = tm->tmdma_desc_head; if (index >= BLK_SIZE * 2) { blk = blk->next; index -= BLK_SIZE * 2; } dbg_assert (blk); u32 *data = (u32 *) blk->data; return &data[index / 8]; } /** * Write a tone into a word. * \param word_ptr a pointer to the word. * \param index the tone index. * \param tone the tone value to write. */ void tonemap_write_tone_to_word (u32 *word_ptr, uint index, uint tone); /** * Write a tone into a tone map. * \param tm the tone map. * \param index the index of the tone to write. * \param tone the tone value to write. */ void tonemap_write_tone (tonemap_t *tm, uint index, uint tone); /** * Decrease modulation of a tone in a tone map. * \param tonemap tonemap to use. * \param index index of the tone in the tone map. * \return true if decrease succeeded, false otherwise. * * The decrease may fail if the tone is already set at the minimal value. * \warning The given index must be in the tone map. * The function will assert otherwise. */ bool tonemap_decrease_tone (tonemap_t *tonemap, uint index); /** * Increase modulation of a tone in a tone map. * \param tonemap tonemap to use. * \param index index of the tone in the tone map. * \return true if increase succeeded, false otherwise. * * The increase fail if the tone is already set at the maximal value. * \warning The given index must be in the tone map. * The function will assert otherwise. */ bool tonemap_increase_tone (tonemap_t *tonemap, uint index); /** * Compute the number of bits per Physical Block. * \param mod tone map kind used. * \param fecrate FEC encoding rate. * \param pb_size PB size. * \param bits_per_symbol number of bits per data symbol, used for ROBO * modulations only. * \return the number of bits per PB. */ uint tonemap_bits_per_pb (phy_mod_t mod, phy_fecrate_t fecrate, phy_pb_size_t pb_size, uint bits_per_symbol); /** * Compute number of half iterations for the given tonemap characteristics. * \param bits_per_symbol number of bits per data symbol * \param bits_per_pb number of bits per Physical Block * \param gil guard interval * \return TCC half iteration number to be used by hardware */ uint tonemap_tcc_halfit (uint bits_per_symbol, uint bits_per_pb, phy_gil_t gil); /** * Convert ble in FC representation to floating point representation. * \param ble ble in FC representation (5 bits mantissa, 3 bits exponent) * \return ble in floating point representation (real value << 5) */ uint tonemap_ble_mant_2_uf5 (u8 ble); /** * Convert ble in floating point representation to FC representation. * \param ble ble in floating point representation (real value << 5) * \return ble in FC representation (5 bits mantissa, 3 bits exponent) */ u8 tonemap_ble_uf5_2_mant (uint ble); /** * Compute floating point representation of BLE for frame control field. * \param bits_per_symbol number of bits per symbol * \param fecrate FEC encoding rate * \param p_pberror_uf32 32 bit fixed point PB error rate * \param gil guard interval * \return encoded BLE value * * BLE encoding format: 5 bit-mantissa and 3 bit-exponent, with the mantissa * in the MSB. * * BLE is given by: * * BLE = (mant + 32) * 2^(exp-4) + 2^(exp-5) * * Max value is 0b111111100 = 508 (mant = 31, exp = 7), min value is * 0b10.00001 ~= 2.03125 (mant = exp = 0). * * BLE largest fractional part, including rounding: 5 bits. I.e., result from * converting BLE floating point notation used in frame controls to a number * yield at most 5 bits of fractional part. */ u8 tonemap_ble (uint bits_per_symbol, phy_fecrate_t fecrate, u32 p_pberror_uf32, phy_gil_t gil); /** * Update pre-computed tone map parameters. * \param tm the tone map to update * \param p_pberror_uf32 32 bit fixed point PB error rate (see tonemap_ble) * * This function should be called every time a modification is done on a tone * map to update fields used by lower layers. */ void tonemap_update (tonemap_t *tm, u32 p_pberror_uf32); /** * Find the interval corresponding to an offset. * \param tonemaps the set of tone maps where to look for the interval * offset. * \param offset_atu the offset of the interval (in ATU). */ extern inline uint tonemap_interval_find (const tonemaps_t *tonemaps, uint offset_atu) { uint a, b, m; tonemap_intervals_t *intervals = tonemaps->intervals; /* Dichotomy search. */ a = 0; b = intervals->intervals_nb; while (a != b) { m = (a + b) / 2; if (offset_atu < intervals->interval[m].end_offset_atu) b = m; else a = m + 1; } return a; } /** * Allocate a new set of tone map and initialize it * \return A pointer to the new set of tone map. */ tonemaps_t * tonemaps_alloc (void); /** * Release all tonemap in the set of tonemaps, and release it. * \param tms Set of tonemaps to release. */ void tonemaps_release (tonemaps_t *tms); /** * Decrease tone map release counter and clean all tone maps marked as * to be released now in a station set. * \param tms the set of tone maps to clean. * \return the number of tone maps really deleted. * This function parse every tone maps and delete the one marked as released. * It also decreased the tone map release counter. * This function must be called every one second. */ u8 tonemaps_disabled_clean (tonemaps_t *tms); /** * Release all tone maps and reset default TMI to default value. * \param tms the set of tone maps to reset * \param tm_release_list given to tonemap_release * * The purpose of this function is to reset the tone maps structure to sane * values to restart using them without deleting and re-allocating the pointer * (preventing some concurrency bugs). */ void tonemaps_reset (tonemaps_t *tms, tonemap_release_list_t *tm_release_list); /** * Get the list of tone maps enabled. * \param tms the set of tone map where we want the list of enabled tone * maps. * \return a bit field list with a one when the tone is enabled and zero when * it is disabled. */ u32 tonemaps_get_tonemap_enabled_list (tonemaps_t *tms); /** * Set the tone map to the first free TMI (not in use) into a tone maps * structure. * \param tms the set of tone map where to look for a TMI not in use. * \param tm tone map to set. * \return the tone map index where the tone map has been set. In case of * error, its value is 0. */ u8 tonemaps_set_first_free_tmi (tonemaps_t *tms, tonemap_t *tm); /** * Get a TMI which is not in use to store a tone map. * \param tms the set of tone map where to look for a TMI not in use. * \return an empty TMI, or zero if there is no more. */ u8 tonemaps_get_first_free_tmi (tonemaps_t *tms); END_DECLS #endif /* mac_common_tonemap_h */