Instrument Scratch Memory Map
Intricon (former RTI) Circuits

Map of Manufacturer's Reserved Space

Bits (Little Endian)Notes
15141312111009080706050403020100
Word1 / MDA 0Autofit 4 Autofit 3Audiogram
(top 2-bits, out of 50-bit)
Year Code used in Serial Number (6 bits)
Space specified by RTI
Clari-D only supports 8-bits
Word2 / MDA 1In Situ
(1 bit)
PrescriptionType
(4 bits)
UserVCPos
(3 bits)
Instrument Model Code (8 bits)
Space specified by RTI
Word3 / MDA 2Autofit 2 Autofit 1Serial Number - 1st part (upper 8-bits, out of 24-bit)
Space specified by RTI
Clari-D only supports 8-bits
Word4 / MDA 3Serial Number - 2nd part (lower 16-bits, out of 24-bit)
Space specified by RTI
Word5 / MDA 4Audiogram
(upper 16-bits, out of 50-bit)
N/A in Intuition2 & Clari-D
Word6 / MDA 5Audiogram
(mid 16-bits, out of 50-bit)
N/A in Intuition2 & Clari-D
Word7 / MDA 6Audiogram
(lower 16-bits, out of 50-bit)
N/A in Intuition2 & Clari-D
Word8 / MDA 7Company code
(7 bits)
Vent Size
(5-bits)
Tubing Type (OTE)
(upper 2-bits, out of 3-bit)
Has Directional Mic
(1-bit)
Tubing Type (OTE)
(former BTE Earhook)
(lower 1-bit, out of 3-bit)
N/A in Intuition2 & Clari-D
Word8 / MDA 7
(Sonetik only)
PGM file loaded
(16 bits)
Sonetik only
Word9 / MDA 8Acclimatization
(2-bits)
Dome Size
(4-bits)
Tubing Length
(4-bits)
Has Push Button/
Toggle Switch/None
(lower 2-bits)
Has Auto-TCoil
(1-bit)
Has TCoil
(1-bit)
Has Digital VC
(1-bit)
Has External VC
(1-bit)
N/A in Intuition2 & Clari-D
Word9 / MDA 8
(Sonetik only)
Work order number
(upper 16-bits, out of 32-bit)
Sonetik only
Word10 / MDA 9 SoftTouch (1 bit) Has Rocker VC
(1-bit)
Circuit Compatibility
Version
(3-bits)
N/A in Intuition2 & Clari-D
Word10 / MDA 9
(Sonetik only)
Work order number
(lower 16-bits, out of 32-bit)
Sonetik only
OnSemi (formerly Sound Design Technologies/Gennum) Circuits

Map of Scratch Memory (128-bit)

0 1 2 3 4 5 6 7
Byte 0 Serial Number (4 bytes)
Bytes 0 - 3
Encryption (16 bytes)
Bytes 4 - 19
Byte 8 Encryption
Bytes 4 - 19
Byte 16 Encryption
Bytes 4 - 19
ExternalVC
(Foundation/BTE478P)
Byte 20
Directional Microphone (Foundation)
Byte 21
Telecoil
(Foundation)
Byte 22
UserVC
(All Digitals
except Nueve)
Byte 23
Byte 24 PrescriptionType
(All Digitals except Nueve)
Byte 24
Impulse Protection
(Intellio)
Byte 25
Dome Size (4-bits)
Tubing Length (4-bits)
Byte 26
Acclimatization (2-bits)
Has Push Button/Toggle
Switch/None (2-bits)
Has Auto-TCoil (1-bit)
Has TCoil (1-bit)
Has Digital VC (1-bit) Has External VC (1-bit)
Byte 27
Company code (7 bits)
Has Directional Mic (1-bit)
Byte 28
Vent Size (5-bits)
Tubing Type (OTE) (3-bit)
Byte 29
Byte 32 Memory 1 Melody
(Intellio)
Byte 32
Memory 2 Melody
(Intellio)
Byte 33
Memory 3 Melody
(Intellio)
Byte 34
Memory 4 Melody
(Intellio)
Byte 35
Melody volume (1-50)
(Intellio)
Byte 36
Volume Change Melody
(Intellio)
Byte 37
Volume Min/Max Melody
(Intellio)
Byte 38
Low Battery Melody
(Intellio)
Byte 39
Byte 40
Byte 48
Byte 56
Byte 64
Byte 72
Byte 80
Byte 88 Sonetik - Stored Stock Program
Byte 88
Sonetik - Order Number
Bytes 89-92
Byte 96 flag isAutofitSaved (boolean)
Byte 96
Autofit Mem 1 (integer)
Byte 97
Autofit Mem 2 (integer)
Byte 98
Autofit Mem 3 (integer)
Byte 99
Autofit Mem 4 (integer)
Byte 100
Audiogram
(11 bytes: 1 byte for length, 10 bytes for data)
Bytes 101 - 111
Byte 104 Audiogram
Bytes 101 - 111
Byte 112 In Situ Audiogram (11 bytes: 1 byte for length, 10 bytes for data)
Bytes 112 - 122
Byte 120 In Situ Audiogram (continued)
Bytes 112 - 122
flag isUsingInSituAudiogram (boolean)
Byte 123
Manufacturer code
Byte 124
Circuit Compatibility Version
Byte 125

Methods for Serial Number Storage and Retrieval

To save the serial number to scratch memory:

ScratchData[0] := SerialNum shr 24;
ScratchData[1] := (SerialNum shr 16) and 255;
ScratchData[2] := (SerialNum shr 8) and 255;
ScratchData[3] := SerialNum and 255;

To read the serial number from scratch memory (Gennum circuits):

SerialNo := 
  (ScratchData[0] shl 24) + 
  (ScratchData[1] shl 16) +
  (ScratchData[2] shl 8) + 
  ScratchData[3];

Operators

shl bitwise shift left
shr bitwise shift right
and bitwise AND
255 bitmask of 1111 1111 (i.e. all 8 bits on)
Instrument Model Code

Instrument Model Code is selected from this table:

Instructions:

Use the lower 8 bits of Word 2 to indicate all of the models. Make each combination of shell size and circuit to be a unique model number.

This method works nicely because each model has a set of associated transducer curves. This scheme allows 256 model combinations if we only use the lower 8 bits of word 2, but we could use all 16 bits, if necessary, and not have any practical limitation on the number of models into the future.

Starting with ezFIT 4.20, supporting the Ethos circuit, model codes start at 00 for every new circuit. Previous circuits are kept with the original notations, for backwards compatibility. Basically, instruments are uniquely identified by the CircuitID + ProductID + StyleID. See Guaranteeing Unique Circuit Instrument References for a more detailed explanation.

Circuit ID

Circuit IDs for Intricon (former RTI) products

Circuit ID Description
ci_None 0 none
ci_Unknown 0 unknown
ci_DigitalOne2TestBox 0 legacy code
ci_DigitalOne2ITE 1 legacy code
ci_DigitalOne2CT 2 DigitalOne2CT (Change Tones): Intuition 2, Simplex 2P BTE
ci_DigitalOne4AFC 5 DigitalOne4AFC: Clari-D
ci_DigitalOne4NRPlus 6 DigitalOne4NR+: Intuition 4, Clari-D NR, Sparo, TransEar
ci_Essential 18 Essential 150: Simplex 2P+, BTE 478P+, BTE 675DP+
ci_Audion4 21 Audion 4: Flx 4
ci_Audion6 20 Audion 6: Intuition 6, Flx 6, BTE D6P, BTE 6AD
ci_Audion8 23 Audion 8: Octane 12
ci_Intune 7 InTune: Intuition 4AD, Intuition 4+, IRIC 4, Sparo AD
ci_Spin 9 Spin: Intuition 2FC, Sparo 2
ci_SpinNR 16 SpinNR: Intuition 2+, Intuition 2FC+, Intuition 2ER, Sparo 2ER
ci_Ethos 10 Ethos: Intuition 12, Sparo 12, Flx, Clik
ci_EthosOvertus 10 Overtus (circuit based on Ethos): Cue
ci_Other 999 Other (non-zero) undefined circuit ID

Ordered by Circuit

Circuit Instrument Model Style Model Code
ci_Unknown Optitrim BTE 00
ci_DigitalOne2 Intuition 2 BTE 03
ci_DigitalOne2 Intuition 2 Full Shell 04
ci_DigitalOne2 Intuition 2 ITC 05
ci_DigitalOne2 Intuition 2 CIC 21
ci_DigitalOne2 Intuition 2 Half Shell 22
ci_DigitalOne2 Intuition 2 Mini Canal 23
ci_DigitalOne2 Intuition 2 Canal 24
ci_DigitalOne2 Intuition 2 Super60 25
ci_DigitalOne2 Simplex 2P BTE 53
ci_DigitalOne4AFC Clari-D FSS 14
ci_DigitalOne4AFC Clari-D CIC 15
ci_DigitalOne4AFC Clari-D Half Shell 16
ci_DigitalOne4AFC Clari-D Mini Canal 17
ci_DigitalOne4AFC Clari-D Canal 18
ci_DigitalOne4AFC Clari-D Super60 19
ci_DigitalOne4AFC Clari-D Mini CIC 20
ci_DigitalOne4NRPlus Intuition 4 BTE 01
ci_DigitalOne4NRPlus Intuition 4D BTE 02
ci_DigitalOne4NRPlus Intuition 4 Full Shell 06
ci_DigitalOne4NRPlus Intuition 4 ITC 07
ci_DigitalOne4NRPlus Intuition 4 CIC 08
ci_DigitalOne4NRPlus Intuition 4 Half Shell 09
ci_DigitalOne4NRPlus Intuition 4 Mini Canal 10
ci_DigitalOne4NRPlus Intuition 4 Canal 11
ci_DigitalOne4NRPlus Intuition 4 Super60 12
ci_DigitalOne4NRPlus Intuition 4 ezHear 13
ci_DigitalOne4NRPlus Intuition 4 Mini CIC 14
ci_DigitalOne4NRPlus Sparo OTE 26
ci_DigitalOne4NRPlus TransEar TransEar 27
ci_DigitalOne4NRPlus nVe 4 RIC 60
ci_Ethos Intuition 8/12 CIC 01
ci_Ethos Intuition 8/12 CIC + Power 02
ci_Ethos Intuition 8/12 Mini Canal 03
ci_Ethos Intuition 8/12 Mini Canal + Power 04
ci_Ethos Intuition 8/12 Canal 05
ci_Ethos Intuition 8/12 Canal + Power 06
ci_Ethos Intuition 8/12 Half Shell 07
ci_Ethos Intuition 8/12 Half Shell + Power 08
ci_Ethos Intuition 8/12 Full Shell 09
ci_Ethos Intuition 8/12 Full Shell + Power 10
ci_Ethos Intuition 8/12 Super60 11
ci_Ethos Intuition 8/12 ezHear 12
ci_Ethos Flx OTE 13
ci_Ethos Sparo 8/12 OTE 14
ci_Ethos Clik OTE 15
ci_Ethos Loon OTE 16
ci_Ethos Pluros OTE 17
ci_EthosOvertus Cue Mini CIC 18
ci_EthosOvertus Cue CIC 19
ci_Ethos Intuition 8/12 Mini CIC 20
ci_Ethos Intuition 8/12 BTE 21
ci_Ethos Intuition 8/12 BTE + Power 22
ci_Ethos TransEar 12 BTE 23
ci_Ethos IRIC 12 RIC 26
ci_EthosOvertus Cue mRIC w/o SoftTouch 210
ci_EthosOvertus Cue mRIC 211
ci_EthosOvertus Cue mRIC w/ Tcoil 212
ci_Intune Sparo AD OTE 29
ci_Intune Intuition 4AD Full Shell 30
ci_Intune Intuition 4AD Half Shell 31
ci_Intune Intuition 4AD Super60 32
ci_Intune Intuition 4AD BTE 33
ci_Intune TransEar+ OTE 37
ci_Intune Intuition 4+ CIC 45
ci_Intune Intuition 4+ Mini Canal 46
ci_Intune Intuition 4+ Canal 47
ci_Intune Intuition 4+ Half Shell 48
ci_Intune Intuition 4+ Full Shell 49
ci_Intune Intuition 4+ Super60 50
ci_Intune Intuition 4+ ezHear 51
ci_Intune Intuition 4+ BTE 52
ci_Intune Intuition 4+ Mini CIC 52
ci_Intune Intuition 4+ CIC + Power 55
ci_Intune Intuition 4+ Mini Canal + Power 56
ci_Intune Intuition 4+ Canal + Power 57
ci_Intune Intuition 4+ Half Shell + Power 58
ci_Intune Intuition 4+ Full Shell + Power 59
ci_Intune Intuition 4+ Mini CIC + Power 60
ci_Intune nVe AD RIC 62
ci_Intune IRIC 4 RIC 63
ci_Spin Sparo 2 OTE 28
ci_Spin Intuition 2FC Full Shell 38
ci_Spin Intuition 2FC CIC 39
ci_Spin Intuition 2FC Half Shell 40
ci_Spin Intuition 2FC Mini Canal 41
ci_Spin Intuition 2FC Canal 42
ci_Spin Intuition 2FC Super60 43
ci_Spin Intuition 2FC BTE 44
ci_Spin Intuition 2FC Mini CIC 45
ci_Spin Intuition 2FC Security 54
ci_Spin nVe 2 RIC 61
ci_SpinNR Intuition 2ER Full Shell 01
ci_SpinNR Intuition 2ER Full Shell + Power 02
ci_SpinNR Intuition 2ER CIC 03
ci_SpinNR Intuition 2ER CIC + Power 04
ci_SpinNR Intuition 2ER Half Shell 05
ci_SpinNR Intuition 2ER Half Shell + Power 06
ci_SpinNR Intuition 2ER Mini Canal 07
ci_SpinNR Intuition 2ER Mini Canal + Power 08
ci_SpinNR Intuition 2ER Canal 09
ci_SpinNR Intuition 2ER Canal + Power 10
ci_SpinNR Intuition 2ER Super60 11
ci_SpinNR Intuition 2ER BTE 12
ci_SpinNR Intuition 2ER ezHear 13
ci_SpinNR Sparo 2ER OTE 14
ci_SpinNR Intuition 2FC+ Mini CIC 19
ci_SpinNR Intuition 2FC+ CIC 20
ci_SpinNR Intuition 2FC+ CIC + Power 21
ci_SpinNR Intuition 2FC+ Mini Canal 22
ci_SpinNR Intuition 2FC+ Mini Canal + Power 23
ci_SpinNR Intuition 2FC+ Canal 24
ci_SpinNR Intuition 2FC+ Canal + Power 25
ci_SpinNR Intuition 2FC+ Half Shell 26
ci_SpinNR Intuition 2FC+ Half Shell + Power 27
ci_SpinNR Intuition 2FC+ Full Shell 28
ci_SpinNR Intuition 2FC+ Full Shell + Power 29
ci_SpinNR Intuition 2FC+ Super60 30
ci_SpinNR Intuition 2FC+ BTE 31
ci_SpinNR Intuition 2FC+ ezHear 32
ci_SpinNR Intuition 2+ Mini CIC 33
ci_SpinNR Intuition 2+ CIC 34
ci_SpinNR Intuition 2+ CIC + Power 35
ci_SpinNR Intuition 2+ Mini Canal 36
ci_SpinNR Intuition 2+ Mini Canal + Power 37
ci_SpinNR Intuition 2+ Canal 38
ci_SpinNR Intuition 2+ Canal + Power 39
ci_SpinNR Intuition 2+ Half Shell 40
ci_SpinNR Intuition 2+ Half Shell + Power 41
ci_SpinNR Intuition 2+ Full Shell 42
ci_SpinNR Intuition 2+ Full Shell + Power 43
ci_SpinNR Intuition 2+ Super60 44
ci_SpinNR Intuition 2+ BTE 45
ci_SpinNR Intuition 2+ ezHear 46
ci_SpinNR IRIC 2 RIC 47
ci_Essential Simplex 2P+ Mini CIC 01
ci_Essential Simplex 2P+ CIC 02
ci_Essential Simplex 2P+ CIC + Power 03
ci_Essential Simplex 2P+ Mini Canal 04
ci_Essential Simplex 2P+ Mini Canal + Power 05
ci_Essential Simplex 2P+ Canal 06
ci_Essential Simplex 2P+ Canal + Power 07
ci_Essential Simplex 2P+ Half Shell 08
ci_Essential Simplex 2P+ Half Shell + Power 09
ci_Essential Simplex 2P+ Full Shell 10
ci_Essential Simplex 2P+ Full Shell + Power 11
ci_Essential Simplex 2P+ Super60 12
ci_Essential Simplex 2P+ BTE 13
ci_Essential Simplex 2P+ ezHear 14
ci_Essential 478P+ BTE 15
ci_Essential 675DP+ BTE 16
ci_Audion4 Flx 4 OTE 13
ci_Audion6 Intuition 6 CIC 01
ci_Audion6 Intuition 6 CIC + Power 02
ci_Audion6 Intuition 6 Mini Canal 03
ci_Audion6 Intuition 6 Mini Canal + Power 04
ci_Audion6 Intuition 6 Canal 05
ci_Audion6 Intuition 6 Canal + Power 06
ci_Audion6 Intuition 6 Half Shell 07
ci_Audion6 Intuition 6 Half Shell + Power 08
ci_Audion6 Intuition 6 Full Shell 09
ci_Audion6 Intuition 6 Full Shell + Power 10
ci_Audion6 Intuition 6 Super 60 11
ci_Audion6 Flx 6 OTE 13
ci_Audion6 Intuition 6 Mini CIC 16
ci_Audion6 IRIC 6 RIC 27
ci_Audion6 BTE D6P BTE 28
ci_Audion6 BTE 6AD BTE 29
ci_Audion6 BTE D6HP BTE 30

Product and Style ID: Methods for Storage and Retrieval

To save the field ProdAndStyleID manufacturer's reserved space:

procedure TEzNzBase.SetFieldProdAndStyleID(ProdAndStyleID: integer; var Word2: word);
var
  BitMask: word;
begin
  // word2 format in bits: xPPP PVVV IIII IIII (x=UsingInSitu, P=prescription, V=VCpos, I=ProdAndStyleID)
 
  // store ProdAndStyleID code:
  // 1. clear ProdAndStyleID field using bitmask.
  // 2. store ProdAndStyleID field (and preserve other data in Word2).
 
  BitMask := 255;   // 0000 0000 1111 1111
  Word2 := (Word2 and not BitMask) {clear field} xor ProdAndStyleID {store};
end;

To read the field ProdAndStyleID from manufacturer's reserved space:

function TEzNzBase.GetFieldProdAndStyleID(word2: word): integer;
var
  BitMask: word;
begin
   // word2 format in bits: xPPP PVVV IIII IIII (x=UsingInSitu, P=prescription, V=VCpos, I=ProdAndStyleID)
   BitMask := 255; {bitmask of 8-bits}
   result  := (Word2 and BitMask);
end;

Serial Number: Methods for Storage and Retrieval

Serial Number storage format:

SerialNumber = 05108567 (Format: YearCode + Serial Upper 8-bits + Serial Lower 16-bits)
YearCode = CalendarYear - 2000

To save the serial number to manufacturer's reserved space:

  procedure SetRTISerialNum(SerialNum: integer; var Word1, Word3, Word4: word);
  var
      BitMask: word;
      YearCode: string;
      PlainSerialNumStr: string;
      PlainSerialNum: integer;
  begin
      YearCode          := Copy( Format('%.8d',[SerialNum]), 1, 2);  // extract yearcode
      PlainSerialNumStr := Copy( Format('%.8d',[SerialNum]), 3, 6);  // extract just serial number (no yearcode included)
      PlainSerialNum    := StrToInt(PlainSerialNumStr);
 
      // store yearcode used in serial number:
      // 1. clear yearcode field using bitmask.
      // 2. store yearcode field (and preserve other data in Word1).
      BitMask := 65472;   // binary equiv: 1111 1111 1100 0000
      Word1 := (Word1 and Bitmask {clear field}) xor StrToInt(YearCode) {store};
 
      // store serial number by spliting its 24-bit content between Word3 and Word4
      //Word3 := PlainSerialNum shr 16;       // strip lower 16-bits & store only upper 8-bits (shift right 16 places (bits) of this 24-bit code)
      BitMask := 65280;   // binary equiv: 1111 1111 0000 0000
      Word3 := (Word3 and Bitmask {clear field}) xor (PlainSerialNum shr 16);       // strip lower 16-bits & store only upper 8-bits (shift right 16 places (bits) of this 24-bit code)
      Word4 := PlainSerialNum and 65535;    // store in entire word4 (bitmask 65535 has all 32 bits on)
  end;

To read the serial number from manufacturer's reserved space:

function GetRTISerialNum(word1, word3, word4: word): integer;
var
    YearCode: string;
    SerialNum: integer;
begin
    //--------------------------------------------
    //      1111 1111 11xx xxxx  (Word1)
    //  AND 0000 0000 0011 1111  (63 bitmask)  YearCode can be max 2063 (i.e. 63)
    //  -----------------------
    //      0000 0000 00xx xxxx  (YearCode)
    //--------------------------------------------
    YearCode  := format('%.2d', [Word1 and 63] );                    // 63 = bitmask 111111 (6-bits)
    SerialNum := ((Word3 and 255 {upper 8-bits}) shl 16 ) + Word4 {lower 16-bits}; // create basic serial number
    SerialNum := StrToInt(format('%s%.6d', [YearCode, SerialNum]));  // add yearcode to serial number
    result    := SerialNum;
end;

Audiogram: Methods for Storage and Retrieval

Set the audiogram data in the scratch memory. 10 frequencies are stored in 50 bits, representing each value as a 5 bit number. The value stored is the hearing threshold divided by 5. This is rounded to the nearest 5, so 26 becomes 5 and 48 becomes 10. The minimum stored value is 0, the maximum stored value is 150.

//------------------------------------------------------------------------------
// Procedure  : SetScratchMemAudiogram
// Description: To save the audiogram to manufacturer's reserve space (RTI circuits)
// Arguments  : Autofit: integer; var Word3: word
// Result     : None
//------------------------------------------------------------------------------
procedure TEzNzBase.SetScratchMemAudiogram(AnAudiogram: TAudiogram;
             var Word1: word; var Word5: word; var Word6: word; var Word7: word);
var
  BitMask: word;
  CompressedAudiogram: array [0..6] of Byte;
  i, BytePos, BitPos, BitPosInByte, FreqIdx, Overflow: integer;
  CompressedGainVal: Byte;
begin
  if FHasAudiogram then begin       // only store to hearing aid if Audiogram exist
    for i:=0 to high(CompressedAudiogram) do begin
      CompressedAudiogram[i] := 0;  // clear all bits
    end;
 
    // encode audiogram
    for FreqIdx := 0 to AnAudiogram.Highest {9} do begin
      BitPos       := FreqIdx * 5;
      BitPosInByte := BitPos mod 8;
      BytePos      := BitPos div 8;
      Overflow     := (5 {field size in bits} - (8 {bitsperbyte} - BitPosInByte {good bits}));
      BitMask      := 31;                                // binary equiv: 0000 0000 0001 1111
      BitMask      := (not (BitMask shl BitPosInByte));  // binary equiv: 1111 1111 1110 0000 (if BitPosInType = 0)
 
      // let's calculate compressed gain value
      if AnAudiogram.FOriginal[FreqIdx] <> -1 then begin       // if Gain in current frequency is not empty (-1) ...
        CompressedGainVal := (AnAudiogram.FOriginal[FreqIdx] div 5);
      end else begin
        CompressedGainVal := 31;   // code for empty field (-1)
      end;
 
      // store first part of freq value (gain index, actually)
      // gain index = (gain value @ freq) / 5
      // Gain in current frequency is not empty (-1). Let's store it
      CompressedAudiogram[BytePos] := (CompressedAudiogram[BytePos] and BitMask {clear field}) xor
                                      (CompressedGainVal shl BitPosInByte) {store};
 
      // store overflow bits in next byte (second part of freq value, if there is overflow in previous storage unit)
      if Overflow > 0 then begin
        //BitMask := GetBitMask(5 {field size in bits} - (8 {bitsperbyte} - Overflow));  // get count of missing bits that need storing
        //GetBitMask(Overflow);              // get bitmask based on count of missing bits that need storing
        BitMask := 65535 shl Overflow; // get bitmask based on count of missing bits that need storing
        CompressedAudiogram[BytePos+1] := (CompressedAudiogram[BytePos+1] and BitMask {clear field}) xor
                                          (CompressedGainVal shr (5 {fieldsize} - Overflow) {store}); {store only missing bits}
      end; {endif}
    end; {endfor}
 
    // store compressed audiogram:
    // 1. clear audiogram field using bitmask.
    // 2. store audiogram field (and preserve other data in Word1 and Word5..Word7).
    //BitMask := 65343;               // binary equiv: 1111 1111 0011 1111
    BitMask := (3 shl 6);             // binary equiv: 0000 0000 1100 0000
    BitMask := not BitMask;           // binary equiv: 1111 1111 0011 1111
    Word1   := (Word1 and BitMask {clear field}) xor (CompressedAudiogram[6] shl 6 {store});  // upper 2-bits
    Word5   := (Word5 and 0 {clear field}) xor CompressedAudiogram[4] {store} xor (CompressedAudiogram[5] shl 8) {store};   // upper 16-bits
    Word6   := (Word6 and 0 {clear field}) xor CompressedAudiogram[2] {store} xor (CompressedAudiogram[3] shl 8) {store};   // mid 16-bits
    Word7   := (Word7 and 0 {clear field}) xor CompressedAudiogram[0] {store} xor (CompressedAudiogram[1] shl 8) {store};   // lower 16-bits
  end; //endif
 
end;

Get the audiogram data from the scratch memory:

//------------------------------------------------------------------------------
// Procedure  : GetScratchMemAudiogram
// Description: To read the audiogram from manufacturer's reserve space (RTI circuits)
// Arguments  : Word1, Word5, Word6, Word7: word; var AnAudiogram: array of integer;
// Result     : void
//------------------------------------------------------------------------------
function TEzNzBase.GetScratchMemAudiogram(Word1, Word5, Word6, Word7: word;
                               var AnAudiogram: array of integer): Boolean;
var
  CompressedAudiogram: array [0..6] of Byte;
  AudiogramFromInstrument: array [0..9] of integer;
  BitMask: word;
  i, BytePos, BitPos, BitPosInByte, GainIdx, GainVal, FreqIdx, Overflow: integer;
  AudiogramExists: Boolean;
begin
  AudiogramExists := False;
  for i:=0 to high(CompressedAudiogram) do begin
    CompressedAudiogram[i] := 0;  // clear all bits
  end;
 
  // unpack data
  CompressedAudiogram[0] := (Word7 and (255 shl 0)) shr 0; // lower freq
  CompressedAudiogram[1] := (Word7 and (255 shl 8)) shr 8;
  CompressedAudiogram[2] := (Word6 and (255 shl 0)) shr 0; // mid freq
  CompressedAudiogram[3] := (Word6 and (255 shl 8)) shr 8;
  CompressedAudiogram[4] := (Word5 and (255 shl 0)) shr 0; // upper freq
  CompressedAudiogram[5] := (Word5 and (255 shl 8)) shr 8;
  CompressedAudiogram[6] := (Word1 and (3   shl 6)) shr 6; // remaining upper 2-bits
 
  // check whether we have an audiogram
  for i:=0 to High(CompressedAudiogram) do begin
    if CompressedAudiogram[i] <> 0 then begin
      AudiogramExists := True;   // we have an audiogram stored
    end;
  end;
 
  if AudiogramExists then begin
    // decode audiogram (stored in bitmap)
    BitMask := 31;  {Bitmask = 11111}
    for FreqIdx := 0 to 9 do begin
      // init variables
      BitPos       := (FreqIdx * 5);
      BitPosInByte := BitPos mod 8;
      BytePos      := BitPos div 8;
      Overflow     := (5 {field size in bits} - (8 {bitsperbyte} - BitPosInByte {good bits}));
 
      // get gain value for current frequency
      GainIdx := (CompressedAudiogram[BytePos] and
                 (BitMask shl BitPosInByte) {extract}) shr BitPosInByte {store as Int};
      if Overflow > 0 then begin
        GainIdx := GainIdx xor
                   (CompressedAudiogram[BytePos+1] and
                   (BitMask shr (8 {bitsperbyte} - BitPosInByte {good bits})) {extract}) shl
                   (8 {bitsperbyte} - BitPosInByte) {store as Int};
      end;
      if (GainIdx <> 31) and (GainIdx <> 0) then begin
        GainVal := GainIdx * 5;  // get gain value (based on gain index)
      end else begin
        GainVal := -1;           // gain value is empty (-1)
      end;
      AudiogramFromInstrument[FreqIdx] := GainVal;
    end;
 
    for i:=0 to high(AudiogramFromInstrument) do begin
      AnAudiogram[i] := AudiogramFromInstrument[i];
    end;
 
  end;
 
  result := AudiogramExists;
 
end;

Prescription Type: Methods for Storage and Retrieval

Name Code Value Description
Unassigned presc_Unassigned 0 Unassigned prescription.
FIG6 Audina v.1 2001 presc_FIG6AudinaV1 1 Audina Prescription version 1 (2001), based on FIG6.
FIG6 Audina v.2 2006 presc_FIG6AudinaV2 2 Audina Prescription version 2 (2006), based on FIG6.
NAL-NL1 presc_NALNL1 3 NAL-NL1 Prescription.
FIG6 Audina v.3 2009 presc_FIG6AudinaV3 4 Audina Prescription version 3 (2009), based on FIG6 and Steve Armstrong's algorithms.

To save the prescription type to manufacturer's reserved space:

procedure TEzNzBase.SetFieldPrescriptionType(Prescription: TNZPrescriptionType; var Word2: word);
var
  ValToStore, BitMask: word;
begin
  // word2 format in bits: xPPP PVVV IIII IIII (x=UsingInSitu, P=prescription, V=VCpos, I=ProdAndStyleID)
 
  //                                                                        0xx xx|<-----------
  // Move data (prescription) to correct location by shifting-left 11 bits: 0XXX X000 0000 0000.
  ValToStore := (integer(Prescription) shl 11 {move});
 
  // Note: we only suport up to 15 possible prescriptions, i.e. we only save
  //       4 bits of Prescription. The bitmask takes care of that.
  BitMask := 34815;  // binary equivalent: 1000 0111 1111 1111
 
  // Clear Prescription field, then store new value while preserving old data in Word1
  // Eg: 1. Clear field:   x001 0xxx xxxx xxxx --> x000 0xxx xxxx xxxx
  //     2. Store value 5: x000 0xxx xxxx xxxx --> x010 1xxx xxxx xxxx (and preseve other data)
  Word2 := (Word2 and Bitmask {clear field}) xor ValToStore {store};
end;

To read the prescription type from manufacturer's reserved space:

  function GetFieldPrescriptionType(word2: word): TNZPrescriptionType;
  begin
     // move 11 bits to right, and extract 4 bits (bitmask 15(dec)=1111(bin))
     result := TNZPrescriptionType( (Word2 shr 11) and 15 );
  end;

Autofit Settings: Methods for Storage and Retrieval

ezFIT 4.x Name Code Value Description
Normal WDRC autofit_NormalWDRC 0 Normal using Wide Dynamic Range Compression (WDRC).
AGC-o autofit_AGCo 1 Automatic Gain Control - Output.
Linear autofit_Linear 2 Linear.
Restaurant / Party autofit_RestaurantParty 3 Restaurant, or Party.
Telephone / Acoustic Telephone / Induction Loop autofit_TelephoneInductionLoop 4 Telephone, Acoustic Telephone, or Induction Loop (FM Loops, etc.).
Music autofit_Music 5 Music or other pure tones.
Television autofit_HomeOfficeTV 6 Television.
Theatre / Place of Worship autofit_TheatrePlaceWorship 7 Automatic Gain Control - Output.
Intense Noise autofit_IntenseNoise 8 Intense Noise.
AutoAdapt autofit_AutoAdapt 9 Auto adapt with Adaptive Directionality technology.
AutoSceneDetection autofit_AutoSceneDetect 10 Auto scene detection using iSceneDetect or similar technology.
ezFIT 5.x Name Code Value Description
Normal WDRC autofit_NormalWDRC 0 Normal using Wide Dynamic Range Compression (WDRC).
AGC-o autofit_AGCo 1 Automatic Gain Control - Output.
Linear autofit_Linear 2 Linear.
Restaurant / Party autofit_RestaurantParty 3 Restaurant, or Party.
Telephone / Acoustic Telephone / Induction Loop autofit_TelephoneInductionLoop 4 Telephone (Telecoil), Acoustic Telephone (No Telecoil), or Induction Loop (FM Loops, etc.).
Music autofit_Music 5 Music or other pure tones.
Home / Office / TV autofit_HomeOfficeTV 6 Home, Office, or TV.
Theatre / Place of Worship autofit_TheatrePlaceWorship 7 Theatre, or Place of Worship.
Intense Noise autofit_IntenseNoise 8 Intense Noise.
AutoAdapt autofit_AutoAdapt 9 Auto adapt with Adaptive Directionality technology.
AutoSceneDetection autofit_AutoSceneDetect 10 Auto scene detection using iSceneDetect or similar technology.
Speech Optimizer autofit_SpeechOptimizer 11 Speech Optimizer.
Background Noise / Car / Machines autofit_BackgroundNoiseCarMachines 12 Background Noise, car/traffic, machines.
Loop System autofit_Loop 13 Induction Loop Systems (FM Loops, etc.).

To save the Autofit Settings to manufacturer's reserved space:

procedure TEzNzBase.SetFieldAutofitSettings(Autofit: TAutofitSettings; var Word1: word; var Word3: word);
var
  BitMask: word;
begin
  // store autofit code:
  // 1. clear autofitcode field using bitmask.
  // 2. store autofitcode field (and preserve other data in Word1 and Word3).
 
  BitMask := 15;   // 0000 0000 0000 1111
  Word3 := (Word3 and not (BitMask shl  8) {clear field}) xor (Autofit.MemoryA shl  8) {store};
  Word3 := (Word3 and not (BitMask shl 12) {clear field}) xor (Autofit.MemoryB shl 12) {store};
  Word1 := (Word1 and not (BitMask shl  8) {clear field}) xor (Autofit.MemoryC shl  8) {store};
  Word1 := (Word1 and not (BitMask shl 12) {clear field}) xor (Autofit.MemoryD shl 12) {store};
 
end;

To read the prescription type from manufacturer's reserved space:

procedure TEzNzBase.GetFieldAutofitSettings(Word1, Word3: word; var Autofit: TAutofitSettings);
var
  BitMask: integer;
begin
  // get field values (each 6-bit long)
  BitMask := 15;   // 0000 0000 0000 1111
  Autofit.MemoryA := (Word3 and (BitMask shl  8)) shr  8;
  Autofit.MemoryB := (Word3 and (BitMask shl 12)) shr 12;
  Autofit.MemoryC := (Word1 and (BitMask shl  8)) shr  8;
  Autofit.MemoryD := (Word1 and (BitMask shl 12)) shr 12;
end;

Using In Situ Audiogram: Methods for Storage and Retrieval

To save the field UsingInSituAudiogram to manufacturer's reserved space:

procedure TEzNzBase.SetFieldUsingInSituAudiogram(UsingInSituAudiogram: Boolean; var Word2: word);
var
  BitMask: word;
begin
  // store UsingInSituAudiogram code:
  // 1. clear UsingInSituAudiogram field using bitmask.
  // 2. store UsingInSituAudiogram field (and preserve other data in Word2).
 
  BitMask := 1;   // 0000 0000 0000 0001
  Word2 := (Word2 and not (BitMask shl  15) {clear field}) xor (integer(UsingInSituAudiogram) shl 15) {store};
end;

To read the field UsingInSituAudiogram from manufacturer's reserved space:

function TEzNzBase.GetFieldUsingInSituAudiogram(Word2: word): Boolean;
var
  BitMask: integer;
begin
  // word2 format in bits: xPPP PVVV IIII IIII (x=UsingInSitu, P=prescription, V=VCpos, I=ProdAndStyleID)
  // get UsingInSituAudiogram  setting (upper bit in word)
  BitMask := 1;   // 0000 0000 0000 0001
  result := ( ((Word2 and (BitMask shl  15)) shr  15) = 1 );
end;

VC Pos: Methods for Storage and Retrieval

To save the field VCPos manufacturer's reserved space:

procedure TEzNzBase.SetFieldVCPos(VCPos: integer; var Word2: word);
var
  BitMask: word;
begin
  // word2 format in bits: xPPP PVVV IIII IIII (x=UsingInSitu, P=prescription, V=VCpos, I=ProdAndStyleID)
 
  // store FUserVCAutofittedPos code:
  // 1. clear FUserVCAutofittedPos field using bitmask.
  // 2. store FUserVCAutofittedPos field (and preserve other data in Word2).
 
  BitMask := 7;   // 0000 0000 0000 0111
  Word2 := (Word2 and not (BitMask shl  8) {clear field}) xor (VCPos shl 8) {store};
end;

To read the field VCPos from manufacturer's reserved space:

function TEzNzBase.GetFieldVCPos(word2: word): integer;
begin
   // word2 format in bits: xPPP PVVV IIII IIII (x=UsingInSitu, P=prescription, V=VCpos, I=ProdAndStyleID)
   // move 8 bits to right, and extract 3 bits (bitmask 15(dec)=1111(bin))
   result := (Word2 shr 8) and 7 {bitmask};
end;

BTE Earhook (deprecated in favor of TubingType): Methods for Storage and Retrieval

To save the field BTEEarhook manufacturer's reserved space:

procedure TEzNzBase.SetFieldBTEEarhook(BTEEarhook : boolean; var Word8: word);
var
  BitMask: word;
begin
  // store BTEEarhook code:
  // 1. clear BTEEarhook field using bitmask.
  // 2. store BTEEarhook field (and preserve other data in Word8).
 
  BitMask := 1;   // 0000 0000 0000 0001
  Word8 := (Word8 and not BitMask) {clear field} xor ifthen(BTEEarhook,1,0) {store};
end;

To read the field BTEEarhook from manufacturer's reserved space:

function TEzNzBase.GetFieldBTEEarhook(word8: word): Boolean;
var
  BitMask: word;
begin
   BitMask := 1; {bitmask of 1-bits}
   result  := (Word8 and BitMask)=1;
end;

Tubing Type: Methods for Storage and Retrieval

To save the field TubingType manufacturer's reserved space:

procedure TEzNzBase.SetFieldTubingType(TubingType: TTubingType; var Word8: word);
var
  BitMask: word;
begin
   // this field is split in two:
   //  - Lower 1-bit is in Word8.bit00
   //  - Upper 2-bits are in Word8.bit02 & bit03
 
  // store TubingType code:
  // 1. clear lower 1-bit TubingType field using bitmask.
  // 2. store lower 1-bit TubingType field (and preserve other data in Word8).
  // 3. clear upper 2-bits TubingType field using bitmask.
  // 4. store upper 2-bits TubingType field (and preserve other data in Word8).
 
  // lower 1-bit
  BitMask := 1;   // 0000 0000 0000 0001
  //Word8   := (Word8 and not BitMask) {clear field} xor ifthen(TubingType,1,0) {store};
  Word8   := (Word8 and not BitMask) {clear field} xor (integer(TubingType) and Bitmask) {store};
 
  // upper 2-bits
  BitMask := 4;   // 0000 0000 0000 0011
  Word8   := (Word8 and not (BitMask shl 2)) {clear field} xor
             ((integer(TubingType) and (Bitmask shl 1 {mask for upper 2-bits}) {grab 2-bits}) and
             (Bitmask shl 2)) {store};
end;

To read the field TubingType from manufacturer's reserved space:

function TEzNzBase.GetFieldTubingType(word8: word): TTubingType;
var
  BitMask: word;
  lower1bit, upper2bits: word;
begin
   // this field is split in two:
   //  - Lower 1-bit is in Word8.bit00
   //  - Upper 2-bits are in Word8.bit02 & bit03
 
   // get lower 1-bit
   BitMask    := 1; {bitmask of 1-bits}
   lower1bit  := (Word8 and BitMask);
 
   // get upper 2-bits
   BitMask    := 4; {bitmask of 2-bits}
   upper2bits := (Word8 and (BitMask shl 2));
 
   result     := TTubingType((upper2bits shr 1 {move to correct position}) and lower1bit);
end;

Has Directional Mic: Methods for Storage and Retrieval

To save the field HasDirMic manufacturer's reserved space:

procedure TEzNzBase.SetFieldHasDirMic(UsingInSituAudiogram: Boolean; var Word8: word);
var
  BitMask: word;
begin
  // store HasDirMic code:
  // 1. clear HasDirMic field using bitmask.
  // 2. store HasDirMic field (and preserve other data in Word8).
 
  BitMask := 1;   // 0000 0000 0000 0001
  Word8 := (Word8 and not (BitMask shl 1) {clear field}) xor (integer(HasDirMic) shl 1) {store};
end;

To read the field HasDirMic from manufacturer's reserved space:

function TEzNzBase.GetFieldHasDirMic(Word8: word): Boolean;
var
  BitMask: integer;
begin
  // word8 format in bits: 0000 0000 0000 00DB (D=HasDirMic, B=BTE Earhook)
 
  // get HasDirMic setting (2nd low bit in word)
  BitMask := 1;   // 0000 0000 0000 0001
  result := ( ((Word8 and (BitMask shl 1)) shr 1) = 1 );
end;

Operators

shl bitwise shift left (usually, move to position before storing)
shr bitwise shift right (usually, move to position before retrieving)
and bitwise AND (to store)
or bitwise OR
xor bitwise XOR (to store new data, and preserve other old data in same data structure, or reverse bits)
63 bitmask of 111111 (i.e. all 6 bits on)
65535 bitmask of 11111111 11111111 (i.e. all 16 bits on)