134 | | = Example: Interpretation of Byte Array = |
| 134 | |
| 135 | The following two sections show "real-world" examples from the [wiki:802.11 802.11 Reference Design] that use bit-fields. |
| 136 | |
| 137 | = Example: Interpretation of PHY Header Byte Array = |
| 138 | |
| 139 | The 802.11n specification of the HT (High Throughput) PHY designates many parameters as collections of bits in front of every MAC payload. For the purposes of this document, we refer to this collection of parameters as the "PHY header." Specifically, an HT packet includes: a 3-byte legacy SIGNAL (L-SIG) field, a 6-byte HT-SIGNAL (H-SIG) field, and finally a 2-byte SERVICE field. |
| 140 | |
| 141 | Each of these fields are actually made up of many parameters of varying bit widths. Bit-fields provide an excellent way of allowing code to interpret the underlying lying parameters that are packed into the PHY header. To begin, the following is an actual array of bytes that make up the PHY header of a received 802.11n waveform: |
| 142 | |
| 143 | {{{ |
| 144 | #!div style="font-size: 90%" |
| 145 | {{{#!C |
| 146 | u8 rx_bytes[] = { 0xab, 0x02, 0x00, 0x07, 0x64, 0x00, 0x07, 0x58, 0x03, 0x00, 0x00 }; |
| 147 | }}} |
| 148 | }}} |
| 149 | |
| 150 | {{{rx_bytes}}} is an 11-byte array that is composed of 3 bytes of L-SIG followed by 6 bytes of HT-SIG and finally 2 bytes of SERVICE. Our goal in this example is to use bit-fields to be able to interpret the underlying parameters in this array of bytes. Next, we define the bit-fields and structs that will allow us to perform this interpretation: |
| 151 | |
| 152 | {{{ |
| 153 | #!div style="font-size: 90%" |
| 154 | {{{#!C |
| 155 | // L-SIG Bit-field |
| 156 | typedef union{ |
| 157 | u8 raw_array[3]; |
| 158 | struct __attribute__ ((__packed__)){ |
| 159 | unsigned rate :4; //b[3:0] |
| 160 | unsigned reserved :1; //b[4] |
| 161 | unsigned length :12; //b[16:5] |
| 162 | unsigned parity :1; //b[17] |
| 163 | unsigned tail :6; //b[23:18] |
| 164 | }; |
| 165 | } l_sig_bf; |
| 166 | |
| 167 | // HT-SIG Bit-field |
| 168 | typedef union{ |
| 169 | u8 raw_array[6]; |
| 170 | struct __attribute__ ((__packed__)){ |
| 171 | unsigned mcs :7; //b[6:0] |
| 172 | unsigned bw :1; //b[7] |
| 173 | unsigned len :16; //b[23:8] |
| 174 | unsigned smoothing :1; //b[24] |
| 175 | unsigned not_sounding :1; //b[25] |
| 176 | unsigned reserved :1; //b[26] |
| 177 | unsigned agg :1; //b[27] |
| 178 | unsigned stbc :2; //b[29:38] |
| 179 | unsigned fec :1; //b[30] |
| 180 | unsigned short_gi :1; //b[31] |
| 181 | unsigned n_ess :2; //b[33:32] |
| 182 | unsigned crc :8; //b[41] |
| 183 | unsigned tail :6; //b[47] |
| 184 | }; |
| 185 | } ht_sig_bf; |
| 186 | |
| 187 | // PHY Header Struct |
| 188 | typedef struct __attribute__ ((__packed__)){ |
| 189 | l_sig_bf l_sig; //B[2:0] |
| 190 | ht_sig_bf ht_sig; //B[8:3] |
| 191 | u16 service; //B[10:9] |
| 192 | } phy_header; |
| 193 | }}} |
| 194 | }}} |
| 195 | |
| 196 | {{{phy_header}}} is a struct made up of two bit-fields ({{{l_sig_bf}}} and {{{ht_sig_bf}}}) followed by a 16-bit variable {{{service}}}. |