LCOV - code coverage report
Current view: top level - src/MIDI_Inputs - BankableMIDIMatcherHelpers.hpp (source / functions) Hit Total Coverage
Test: 169c36a3797bc662d84b5726f34a3f37d3c58247 Lines: 83 91 91.2 %
Date: 2024-11-09 15:32:27 Functions: 13 13 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <Banks/Bank.hpp>
       4             : #include <Banks/BankConfig.hpp>
       5             : #include <Def/MIDIAddress.hpp>
       6             : 
       7             : BEGIN_CS_NAMESPACE
       8             : 
       9             : namespace BankableMIDIMatcherHelpers {
      10             : 
      11             : /**
      12             :  * @brief   Check whether a given address is within a range of given length
      13             :  *          starting from the given base address.
      14             :  * 
      15             :  * @param   tgt
      16             :  *          The address to check
      17             :  * @param   base
      18             :  *          The base address, start of the range.
      19             :  * @param   length
      20             :  *          The length of the range.
      21             :  */
      22          10 : inline bool inRange(uint8_t tgt, uint8_t base, uint8_t length) {
      23          10 :     return (base <= tgt) && (tgt - base < length);
      24             : }
      25             : 
      26             : /**
      27             :  * @brief   Check if the given address is part of the bank relative to the
      28             :  *          base address.
      29             :  * 
      30             :  * Consider the following example:  
      31             :  * A Bank with 4 tracks per bank (T), 2 bank settings (N), 
      32             :  * and a base address of 3.
      33             :  * 
      34             :  * ~~~
      35             :  * 0   1   2   3   4   5   6   7   8   9  10  11  12  ...
      36             :  * ☐   ☐   ☐   ☒   ☐   ☐   ☐   ☒   ☐   ☐   ☐   ☐   ☐  ...
      37             :  * ~~~
      38             :  * 
      39             :  * Addresses before the base adddress are not matched (0, 1, 2).  
      40             :  * Addresses after N * T are not matched (8, 9, 10, 11, 12).  
      41             :  * Addresses with a distance to the base address that is not a multiple of N
      42             :  * are not matched (4, 5, 6).
      43             :  * 
      44             :  * @param   tgt 
      45             :  *          The address to check.
      46             :  * @param   base
      47             :  *          The base address (the address of bank setting 0).
      48             :  * @param   bank
      49             :  *          The bank to match the address in.
      50             :  * 
      51             :  * @note    Equivalent to `matchBankableInRange(toMatch, base, 1)`.
      52             :  */
      53             : template <uint8_t BankSize>
      54          26 : bool matchBankable(uint8_t tgt, uint8_t base, const Bank<BankSize> &bank) {
      55          26 :     const uint8_t N = BankSize;
      56          26 :     const uint8_t B = bank.getTracksPerBank();
      57          26 :     const int8_t F = bank.getSelectionOffset();
      58          26 :     const uint8_t m = tgt;
      59          26 :     const uint8_t b = base;
      60          26 :     uint8_t diff = m - b - F * B;
      61          51 :     return m >= b + F * B && //
      62          50 :            diff < N * B &&   //
      63          50 :            diff % B == 0;
      64             : }
      65             : 
      66             : /// @see @ref matchBankableInRange(MIDIAddress,MIDIAddress,BaseBankConfig<BankSize>,uint8_t)
      67             : template <uint8_t BankSize>
      68          18 : bool matchBankableInRange(uint8_t tgt, uint8_t base, const Bank<BankSize> &bank,
      69             :                           uint8_t rangeLen) {
      70          18 :     const uint8_t R = rangeLen;
      71          18 :     const uint8_t N = BankSize;
      72          18 :     const uint8_t B = bank.getTracksPerBank();
      73          18 :     const int8_t F = bank.getSelectionOffset();
      74          18 :     const uint8_t m = tgt;
      75          18 :     const uint8_t b = base;
      76          18 :     uint8_t diff = m - b - F * B;
      77          32 :     return m >= b + F * B && //
      78          30 :            diff < N * B &&   //
      79          30 :            diff % B < R;
      80             : }
      81             : 
      82             : /// @see @ref getRangeIndex(MIDIAddress,MIDIAddress,BaseBankConfig<BankSize>)
      83             : template <uint8_t BankSize>
      84           8 : uint8_t getRangeIndex(uint8_t tgt, uint8_t base, const Bank<BankSize> &bank) {
      85           8 :     const uint8_t B = bank.getTracksPerBank();
      86           8 :     const int8_t F = bank.getSelectionOffset();
      87           8 :     const uint8_t m = tgt;
      88           8 :     const uint8_t b = base;
      89           8 :     uint8_t diff = m - b - F * B;
      90           8 :     return diff % B;
      91             : }
      92             : 
      93             : /// @see @ref getBankIndex(MIDIAddress,MIDIAddress,BaseBankConfig<BankSize>)
      94             : template <uint8_t BankSize>
      95          32 : uint8_t getBankIndex(uint8_t tgt, uint8_t base, const Bank<BankSize> &bank) {
      96          32 :     const uint8_t B = bank.getTracksPerBank();
      97          32 :     const int8_t F = bank.getSelectionOffset();
      98          32 :     const uint8_t m = tgt;
      99          32 :     const uint8_t b = base;
     100          32 :     uint8_t diff = m - b - F * B;
     101          32 :     return diff / B;
     102             : }
     103             : 
     104             : /**
     105             :  * @brief   Check whether a given address is part of the bank relative to
     106             :  *          the base address.
     107             :  * 
     108             :  * @param   tgt 
     109             :  *          The address to check.
     110             :  * @param   base
     111             :  *          The base address (the address of bank setting 0).
     112             :  * @param   config
     113             :  *          The bank configuration.
     114             :  */
     115             : template <uint8_t BankSize>
     116          20 : bool matchBankable(MIDIAddress tgt, MIDIAddress base,
     117             :                    BaseBankConfig<BankSize> config) {
     118          20 :     if (!tgt.isValid() || !base.isValid())
     119           0 :         return false;
     120          20 :     switch (config.type) {
     121          14 :         case BankType::ChangeAddress: {
     122          98 :             return tgt.getChannel() == base.getChannel() &&
     123          98 :                    tgt.getCableNumber() == base.getCableNumber() &&
     124          14 :                    matchBankable(tgt.getAddress(), base.getAddress(),
     125          28 :                                  config.bank);
     126             :         }
     127           3 :         case BankType::ChangeChannel: {
     128          12 :             return tgt.getAddress() == base.getAddress() &&
     129          21 :                    tgt.getCableNumber() == base.getCableNumber() &&
     130           3 :                    matchBankable(tgt.getRawChannel(), base.getRawChannel(),
     131           6 :                                  config.bank);
     132             :         }
     133           3 :         case BankType::ChangeCable: {
     134          12 :             return tgt.getAddress() == base.getAddress() &&
     135          21 :                    tgt.getChannel() == base.getChannel() &&
     136           3 :                    matchBankable(tgt.getRawCableNumber(),
     137           6 :                                  base.getRawCableNumber(), config.bank);
     138             :         }
     139             :         default: return false; // LCOV_EXCL_LINE
     140             :     }
     141             : }
     142             : 
     143             : /**
     144             :  * @brief   Check whether a given address is part of the bank relative to
     145             :  *          the base address and within a range with a given length.
     146             :  * 
     147             :  * @param   tgt 
     148             :  *          The address to check.
     149             :  * @param   base
     150             :  *          The base address (the address of bank setting 0).
     151             :  * @param   config
     152             :  *          The bank configuration.
     153             :  * @param   length
     154             :  *          The length of the range.
     155             :  */
     156             : template <uint8_t BankSize>
     157          30 : bool matchBankableInRange(MIDIAddress tgt, MIDIAddress base,
     158             :                           BaseBankConfig<BankSize> config, uint8_t length) {
     159          30 :     if (!tgt.isValid() || !base.isValid())
     160           0 :         return false;
     161          30 :     switch (config.type) {
     162          20 :         case ChangeAddress:
     163         134 :             return tgt.getChannel() == base.getChannel() &&
     164         134 :                    tgt.getCableNumber() == base.getCableNumber() &&
     165          18 :                    matchBankableInRange(tgt.getAddress(), base.getAddress(),
     166          38 :                                         config.bank, length);
     167          10 :         case ChangeChannel:
     168          28 :             return inRange(tgt.getAddress(), base.getAddress(), length) &&
     169          54 :                    tgt.getCableNumber() == base.getCableNumber() &&
     170           6 :                    matchBankable(tgt.getRawChannel(), base.getRawChannel(),
     171          16 :                                  config.bank);
     172           0 :         case ChangeCable:
     173           0 :             return inRange(tgt.getAddress(), base.getAddress(), length) &&
     174           0 :                    tgt.getChannel() == base.getChannel() &&
     175           0 :                    matchBankable(tgt.getRawCableNumber(),
     176           0 :                                  base.getRawCableNumber(), config.bank);
     177           0 :         default: return false;
     178             :     }
     179             : }
     180             : 
     181             : /**
     182             :  * @brief   Calculate the bank setting of a given MIDI address, relative to
     183             :  *          a base address.
     184             :  * 
     185             :  * @param   target 
     186             :  *          The MIDI address to calculate the bank setting of.
     187             :  * @param   base
     188             :  *          The base address to compare it to (the address of bank setting 0).
     189             :  * @param   config
     190             :  *          The bank configuration to determine the index.
     191             :  */
     192             : template <uint8_t BankSize>
     193          32 : uint8_t getBankIndex(MIDIAddress target, MIDIAddress base,
     194             :                      BaseBankConfig<BankSize> config) {
     195          32 :     switch (config.type) {
     196          22 :         case BankType::ChangeAddress:
     197          22 :             return getBankIndex(target.getAddress(), base.getAddress(),
     198          44 :                                 config.bank);
     199           7 :         case BankType::ChangeChannel:
     200           7 :             return getBankIndex(target.getRawChannel(), base.getRawChannel(),
     201          14 :                                 config.bank);
     202           3 :         case BankType::ChangeCable:
     203           3 :             return getBankIndex(target.getRawCableNumber(),
     204           6 :                                 base.getRawCableNumber(), config.bank);
     205             :         default: return 0; // LCOV_EXCL_LINE
     206             :     }
     207             : }
     208             : 
     209             : /**
     210             :  * @brief   Calculate the index in the address range of a given MIDI address,
     211             :  *          relative to a base address.
     212             :  * 
     213             :  * @param   tgt 
     214             :  *          The MIDI address to calculate the bank setting of.
     215             :  * @param   base
     216             :  *          The base address to compare it to (beginning of the range for bank
     217             :  *          setting 0).
     218             :  * @param   config
     219             :  *          The bank configuration to determine the index.
     220             :  */
     221             : template <uint8_t BankSize>
     222          12 : uint8_t getRangeIndex(MIDIAddress tgt, MIDIAddress base,
     223             :                       BaseBankConfig<BankSize> config) {
     224          12 :     return config.type == BankType::ChangeAddress
     225           8 :                ? getRangeIndex(tgt.getAddress(), base.getAddress(), config.bank)
     226          20 :                : tgt.getAddress() - base.getAddress();
     227             : }
     228             : 
     229             : } // namespace BankableMIDIMatcherHelpers
     230             : 
     231             : END_CS_NAMESPACE

Generated by: LCOV version 1.15