Bitácora · DCSS · Concepto

El mapper y el demapper

Unidad 4 · Transmisión en banda base y banda pasante · de bits a símbolos y de vuelta, el código Gray, la tabla compartida y el demapper blando

El mapper traduce bits a símbolos y el demapper los traduce de vuelta. Entre los dos no se pierde nada: son una tabla y su inversa. Lo que la tabla sí decide es qué grupo de bits queda al lado de cuál en la constelación, y como el slicer, cuando se equivoca, casi siempre elige un vecino, de eso depende cuántos bits cuesta cada error. La respuesta de siempre es el código Gray. Tiene dos letras chicas: hay constelaciones donde no existe, y sólo sirve si el demapper usa la misma tabla que el mapper.

01 · La definición

El mapper toma los bits bi de a grupos de b=log2M y le asigna a cada grupo uno de los M puntos del alfabeto 𝒜:

ak=μ(bkb,…,bkb+b−1),μ:{0,1}b→𝒜

Con 2b=M grupos posibles y M puntos, μ es una biyección: cada grupo tiene su punto y cada punto su grupo, la etiqueta del punto. El demapper es la inversa, aplicada a lo que decidió el slicer:

(b^kb,…,b^kb+b−1)=μ−1(a^k)

La cadena entera es bits → mapper → filtro Tx → canal → filtro Rx → slicer → demapper → bits. El demapper no decide nada: el que elige el punto es el slicer, y el demapper lee su etiqueta. Por eso los dos contadores de error se toman en lugares distintos: la SER a la salida del slicer, la BER a la salida del demapper.

Tablas posibles hay M!, una por cada manera de repartir las etiquetas entre los puntos: para 16-QAM son 16!≈2,09·1013. Todas dan la misma SER, porque la SER depende sólo de dónde están los puntos. La BER cambia de una a otra.

El simulador de la cátedra nunca arma los bits. transmisor_MQAM.m sortea enteros con randi([0 M-1]) y los pasa por qammod, y my_ber_checker.m le pide los bits a qamdemod(…, 'OutputType', 'bit') dos veces: sobre los símbolos mandados y sobre los decididos. El mapper de ese conteo es el propio demapper aplicado del lado del transmisor, así que la tabla es la misma de los dos lados por construcción. Cuando los bits vienen de afuera —de una fuente o de un codificador de canal—, mapper y demapper son dos piezas separadas, y que usen la misma tabla deja de estar garantizado (sección 05).

02 · El código Gray, paso a paso

Un código Gray es una lista de las 2b palabras de b bits en la que dos palabras consecutivas difieren en un solo bit. La construcción de siempre es la del código reflejado, y se hace de a un bit por vez.

Paso 1: arrancar con un bit. La lista es 0, 1.

Paso 2: reflejar. Debajo de la lista se escribe la misma lista al revés: 0, 1, 1, 0.

Paso 3: prefijar. A la primera mitad se le antepone un 0 y a la segunda un 1: 00, 01, 11, 10. Es el Gray de dos bits, el de la filmina de PAM-4. Repitiendo los pasos 2 y 3 sale el de tres:

000 001 011 010 │ 110 111 101 100

Funciona por inducción. Dentro de cada mitad, dos palabras vecinas tienen el mismo prefijo y la misma cola que en la lista anterior, donde ya diferían en un bit. En la costura, la reflexión pone una palabra al lado de sí misma —010 y 110 tienen la misma cola, 10— y lo único que cambia es el prefijo. Y por la misma razón la última y la primera también difieren en un bit: 100 y 000. El código reflejado es cíclico, y eso va a importar en PSK.

Paso 4: la forma cerrada. La etiqueta de la posición n es

g=n⊕⌊n/2⌋

el o exclusivo de n con él mismo corrido un lugar a la derecha, bitxor(n, bitshift(n, -1)). En MATLAB, la lista reflejada y la fórmula dan lo mismo para b de 1 a 8. Por qué el corrimiento produce un solo cambio está en La modulación PAM, con la posición contada desde el nivel más alto.

Paso 5: la inversa, que es la que usa el demapper. Bit por bit, la fórmula dice gi=ni⊕ni+1, con gb−1=nb−1 arriba de todo. Despejando, ni=gi⊕ni+1, y bajando desde el bit más significativo:

ni=gb−1⊕gb−2⊕⋯⊕gi,n=g⊕⌊g/2⌋⊕⌊g/4⌋⊕⋯

Cada bit de la posición es la paridad de los bits de la etiqueta que tiene arriba. La ida es un solo o exclusivo; la vuelta, uno por bit.

03 · Por qué el orden importa

Sea h la cantidad de bits en que difieren la etiqueta mandada y la decidida, la distancia de Hamming entre las dos. Por definición, BER=SER·E[h∣error]/b: cada error de símbolo cuesta h bits de los b que llevaba. Toda la cuestión es cuánto vale ese promedio.

Con relación señal a ruido alta, casi todos los errores son a un vecino a distancia mínima, y todos esos pares son igual de probables: la probabilidad de cruzar la frontera depende sólo de la distancia, que es la misma para todos. Así que el promedio tiende al costo medio sobre el conjunto 𝒫 de los pares de puntos a distancia mínima, que depende sólo de la tabla:

h¯=1|𝒫|∑(i,j)∈𝒫dH(ei,ej),BER≈SER·h¯b

con ei la etiqueta del punto i. Gray es exactamente h¯=1, el mínimo posible, y de ahí la regla BER≈SER/b. Con el orden natural el costo del par depende de dónde está: en PAM es (2M−b−2)/(M−1), que está derivado en La modulación PAM. En 16-QAM natural los vecinos están en la misma fila o en la misma columna, así que cada error cambia un solo eje, y cada eje es una PAM-4 natural: h¯=4/3, con 8 de los 24 pares en dos bits.

Medido sobre la cadena entera —bits, qammod con 'gray' o 'bin', ruido blanco gaussiano, my_slicer.m de la cátedra y qamdemod con la misma opción—, con 10⁶ símbolos de 16-QAM y el mismo ruido para las dos tablas:

Eb/N0BER GrayberawgnBER naturalnatural ÷ GraySER GraySER natural
6 dB2,791·10⁻²2,787·10⁻²3,723·10⁻²1,3341,085·10⁻¹1,085·10⁻¹
8 dB9,202·10⁻³9,247·10⁻³1,233·10⁻²1,3403,648·10⁻²3,663·10⁻²
10 dB1,773·10⁻³1,754·10⁻³2,378·10⁻³1,3417,073·10⁻³7,128·10⁻³
12 dB1,292·10⁻⁴1,387·10⁻⁴1,727·10⁻⁴1,3375,170·10⁻⁴5,230·10⁻⁴

La columna de berawgn es el control: la BER con Gray cae a menos del 1,1 % de la teoría hasta 10 dB. A 12 dB queda un 7 % abajo con 517 bits errados, y el desvío de Poisson con tan pocos eventos es del 4,4 %. Las dos SER son la misma dentro de esa misma dispersión —517 contra 523 símbolos a 12 dB—, y la razón entre las BER se queda entre 1,334 y 1,341 en todo el barrido, contra el 4/3 de la cuenta. La tabla no cambió cuántos símbolos se decidieron mal: cambió cuántos bits costó cada uno. Que con Gray la razón SER/BER tarde en llegar a b cuando la constelación es grande está medido en BER y SER no son la misma curva.

04 · Gray en el plano

En una recta, Gray siempre existe: es la lista de la sección 02 puesta sobre los niveles. En el plano depende de la forma de la constelación, porque cada punto tiene más vecinos y todos tienen que diferir en un bit.

QAM cuadrada: Gray por eje. La etiqueta se parte en dos mitades, una para el nivel de I y otra para el de Q, y cada mitad es el Gray de una PAM de M niveles. Dos vecinos a distancia mínima comparten fila o columna: cambia un solo eje, en un nivel, y por lo tanto un bit. Es lo que hace qammod, y en qué sentido recorre cada eje está en La modulación QAM.

PSK: Gray alrededor del círculo. Los M puntos tienen dos vecinos cada uno, y la vuelta cierra: el último es vecino del primero. Ahí es donde sirve que el código reflejado sea cíclico, y con la etiqueta g(m) en el punto de fase 2πm/M todos los pares quedan en un bit. Es la tabla de pskmod(…, 'gray'). El natural, en cambio, paga la vuelta entera en el último par —111 contra 000 en 8-PSK— y su costo medio es (2M−2)/M: los 2M−b−2 bits del tramo abierto, como en PAM, más los b del cierre.

La 32-QAM en cruz: no hay Gray. Con cinco bits no hay cuadrado; la cruz es una grilla de 6 × 6 sin las cuatro esquinas, con 52 pares a distancia mínima. Las filas no tienen todas el mismo largo, así que no se puede repartir la etiqueta por eje, y la filmina de la Unidad 5 lo dice a su manera: los mappers de las constelaciones en cruz son más complicados. Es más que eso. Una búsqueda exhaustiva —fijando la etiqueta de un punto, porque cualquier tabla Gray sigue siéndolo si se le invierte un bit a todas las etiquetas, y probando para cada vecino las etiquetas a un bit de las ya puestas— recorre 14 727 asignaciones parciales y no encuentra ninguna tabla con los 52 pares en un bit. La misma búsqueda encuentra una enseguida para la grilla rectangular de 8 × 4 y para 16-QAM, que es el control. qammod(…, 32) deja 8 pares en dos bits, todos entre las filas de los brazos y la fila siguiente: h¯=60/52≈1,154. No es lo mejor que se puede hacer: un recocido simulado de 40 arranques encontró tablas de 56/52≈1,077, con dos pares en tres bits, y ninguna con menos de dos pares malos.

Todo junto, contando los pares a distancia mínima sobre las tablas de MATLAB; «malos» son los pares en más de un bit:

constelaciónparesGray, malosGray, h¯natural, malosnatural, h¯
PAM-4301,00011,333
PAM-8701,00031,571
16-QAM2401,00081,333
64-QAM11201,000481,571
8-PSK801,00041,750
16-PSK1601,00081,875
32-QAM en cruz5281,154241,654
128-QAM en cruz232161,069961,741

Las columnas de Gray de las constelaciones cuadradas, de PAM y de PSK son un uno exacto por construcción, y no se miden: se verifican. Las del natural son cuentas cerradas y la tabla las reproduce: 64-QAM natural cuesta lo mismo que PAM-8 natural porque cada eje es una. La que hay que medir es la cruz, y la de 128 puntos, con más pares interiores, se acerca más al uno que la de 32.

Simulación Las etiquetas de los vecinos — la constelación con la etiqueta de cada punto; las líneas unen los vecinos a distancia mínima, en rojo los que difieren en más de un bit, con cuántos. Tocá un punto y después otro para intercambiar sus etiquetas; con el teclado, flechas y Enter. Arranca en PAM-2, donde no hay nada que elegir.
Constelación
Etiquetado
bits por símbolo — pares a distancia mínima — pares en más de un bit — peor par — costo medio de un error al vecino — BER ÷ SER a SNR alta —

En PAM-4 natural el par del medio se pone rojo, y con un solo intercambio —10 por 11— la tabla pasa a ser Gray. En 8-PSK natural los dos rojos más caros cuestan tres bits: el del medio, 011 contra 100, y el que cierra el círculo, 111 contra 000. En la cruz se puede intentar a mano: cualquier rojo que se arregla en el borde de un brazo aparece en otro lado, y ninguna secuencia de intercambios deja los 52 pares en azul, porque esa tabla no existe.

05 · Cualquier Gray sirve, si es el mismo de los dos lados

Que una tabla sea Gray depende de qué etiquetas quedan vecinas, no de cuáles son. Invertir un bit en todas las etiquetas, permutar las posiciones de los bits o recorrer un eje al revés da otra tabla igual de Gray. Lo último es la propiedad de la reflexión: la lista reflejada leída de atrás para adelante es la misma lista con el bit más significativo invertido. Para dos bits, 10 11 01 00 contra 00 01 11 10.

Por eso conviven varias convenciones y ninguna está mal. La filmina de PAM-4 pone 00 en el nivel más alto. qammod recorre el eje Q igual, de arriba abajo, y el eje I de izquierda a derecha. pammod pone el 00 abajo: es el espejo de la filmina, como está medido en La modulación PAM. Y las notas de la Unidad 5, como la de BER y SER, recorren los dos ejes de abajo arriba, que es la constelación de qammod espejada en Q. Las cuatro tienen h¯=1 y la misma BER.

Lo que no se puede es mezclarlas. Si el mapper usa una tabla y el demapper otra, el demapper traduce bien el punto equivocado de la tabla: el slicer acierta y los bits salen mal igual. Con 16-QAM de qammod en el transmisor y 10⁶ símbolos, cambiando sólo la tabla del demapper:

Eb/N0SERBER, misma tablaBER, Q al revésBER, natural en el receptor
sin ruido000,250000,24979
10 dB7,025·10⁻³1,759·10⁻³0,251150,25093
6 dB1,085·10⁻¹2,788·10⁻²0,268500,25938

Sin ruido no hay un solo error de símbolo y la BER es un cuarto. Las dos columnas rojas valen un cuarto por razones distintas. Con Q al revés la cuenta es exacta: en cada símbolo se invierte el bit más significativo de Q, uno de cuatro, siempre; por eso da 0,25000 clavado. Con el natural en el receptor, cada eje se lee bien en sus dos primeros niveles y con un bit cambiado en los otros dos, o sea dos bits malos de cada ocho, y el 0,24979 es ese cuarto con la dispersión de los datos sorteados. Con ruido el piso no baja: a 10 dB la BER buena es 1,8·10⁻³ y las desparejas siguen en un cuarto. Una BER que no baja con la relación señal a ruido mientras la constelación recibida se ve limpia es una tabla, no un canal.

Con PAM-4 el efecto es el doble. Los bits mapeados con la tabla de la filmina y recuperados con pamdemod(…, 'gray') salen con BER 0,5000: el primer bit está mal en todos los símbolos y el segundo en ninguno. Es la reflexión otra vez, el espejo de un Gray reflejado es el mismo Gray con el bit de arriba invertido.

06 · El orden de los bits

Hay una segunda convención escondida en el mismo lugar: cuál de los b bits del grupo es el más significativo de la etiqueta. Las tablas de la filmina se escriben con el primer bit adelante, y así leen int2bit y bit2int, y así agrupa qammod(…, 'InputType', 'bit'). de2bi y bi2de, las funciones viejas, por omisión ponen el menos significativo primero; la diferencia entre bi2de([1 0]) y bit2int([1; 0], 2) está en La modulación PAM. Para el canal es una tabla distinta más. Con PAM-4, si el mapper agrupa con bit2int y el demapper devuelve los bits con de2bi, las etiquetas 01 y 10 se intercambian y la BER sin ruido es 0,5016: la mitad, con la dispersión de los datos. Leída al revés, una tabla Gray sigue siendo Gray; el problema, otra vez, es que no es la misma.

07 · El demapper blando

El demapper de las secciones anteriores es duro: recibe un punto ya decidido y devuelve bits. Si después viene un decodificador de canal, conviene más un demapper blando, que mira la muestra y antes del slicer y devuelve por cada bit cuánto cree en un 0 contra un 1. Es el cociente de log-verosimilitudes, el LLR, ahora con un alfabeto de M puntos. Con símbolos equiprobables y ruido blanco gaussiano de varianza N0 en el plano:

Λj=lnP(bj=0∣y)P(bj=1∣y)=ln∑a∈𝒜j0e−|y−a|2/N0−ln∑a∈𝒜j1e−|y−a|2/N0

donde 𝒜j0 son los puntos cuya etiqueta tiene un 0 en el bit j, y 𝒜j1 los que tienen un 1. La tabla del mapper entra acá, en ese reparto: el demapper blando también tiene que usar la misma. Si de cada suma se conserva sólo el término más grande, queda la aproximación max-log:

Λj≈mina∈𝒜j1|y−a|2−mina∈𝒜j0|y−a|2N0

Uno de los dos mínimos es la distancia al punto más cercano, el que elige el slicer, así que el signo del max-log es el bit que devuelve el demapper duro. Lo que el blando agrega es el módulo: cuánto más lejos está el mejor punto del bando contrario. En PAM-2, con a=±A y N0=2σ2, cada suma tiene un solo término y la fórmula exacta queda Λ=2Ay/σ2, el LLR de la decisión blanda de la Unidad 3.

Medido en 16-QAM a 8 dB, sobre 8·10⁵ bits: el LLR de qamdemod(…, 'OutputType', 'llr') coincide con la suma de arriba hecha a mano con diferencia máxima de 4,3·10⁻¹⁴; el signo del exacto y el del max-log coinciden con el demapper duro en todos los bits, ninguno distinto. Y el módulo separa: la mediana de |Λ| es 12,11 en los bits que el demapper duro acertó y 1,16 en los que erró. Los bits malos llegan marcados como dudosos, y el demapper duro les borra la marca. Un decodificador de canal que recibe los LLR puede pesar cada bit por su confianza; uno que recibe bits, no. Que la información para no equivocarse puede estar en las muestras y perderse en la decisión está medido, para el caso de la ISI, en El slicer tira información que está ahí.

08 · El análisis en MATLAB

El script arma el Gray, cuenta los pares de vecinos sobre las tablas de pammod, qammod y pskmod, corre la cadena con las dos tablas y con tablas desparejas, y saca los LLR. Usa my_slicer.m de la carpeta de scripts de la Unidad 4. Lo que figura como comentario es la salida real de correrlo en R2026a.

%% El mapper y el demapper: Gray contra natural, y tablas desparejas
clear; close all; clc;

%% 1. El código Gray: reflejado, y por la fórmula cerrada
g = 0;
for j = 1:4
    g = [g, bitor(fliplr(g), 2^(j-1))];   % reflejar la lista y prender el bit nuevo
end
n = 0:15;
fprintf('b = 3: %s\n', strjoin(cellstr(dec2bin(g(1:8), 3)), ' '))
fprintf('reflejado == n xor (n>>1): %d\n', isequal(g, bitxor(n, bitshift(n, -1))))
x = g; s = bitshift(g, -1);                % la inversa, la que usa el demapper:
while any(s), x = bitxor(x, s); s = bitshift(s, -1); end   % n = g xor (g>>1) xor (g>>2) ...
fprintf('inversa: %d\n', isequal(x, n))
% b = 3: 000 001 011 010 110 111 101 100
% reflejado == n xor (n>>1): 1
% inversa: 1

%% 2. Cuántos bits cuesta un error al vecino, con 'gray' y con 'bin'
casos = {'PAM-4',4,'pam'; 'PAM-8',8,'pam'; '16-QAM',16,'qam'; '64-QAM',64,'qam'; ...
         '8-PSK',8,'psk'; '16-PSK',16,'psk'; '32-QAM',32,'qam'; '128-QAM',128,'qam'};
fprintf('            pares   gray: >1 bit  medio    bin: >1 bit  medio\n')
for c = 1:size(casos, 1)
    M = casos{c,2}; k = (0:M-1).'; r = zeros(2, 2);
    for e = 1:2
        et = {'gray', 'bin'}; et = et{e};
        switch casos{c,3}
            case 'pam', p = pammod(k, M, 0, et);
            case 'qam', p = qammod(k, M, et);
            case 'psk', p = pskmod(k, M, 0, et);
        end
        [h, np] = costo_vecino(p, k);
        r(e,:) = [sum(h > 1), mean(h)];
    end
    fprintf('%-8s %6d   %10d  %7.4f  %10d  %7.4f\n', casos{c,1}, np, r(1,1), r(1,2), r(2,1), r(2,2))
end
%             pares   gray: >1 bit  medio    bin: >1 bit  medio
% PAM-4         3            0   1.0000           1   1.3333
% PAM-8         7            0   1.0000           3   1.5714
% 16-QAM       24            0   1.0000           8   1.3333
% 64-QAM      112            0   1.0000          48   1.5714
% 8-PSK         8            0   1.0000           4   1.7500
% 16-PSK       16            0   1.0000           8   1.8750
% 32-QAM       52            8   1.1538          24   1.6538
% 128-QAM     232           16   1.0690          96   1.7414

%% 3. La cadena: bits -> mapper -> ruido -> slicer -> demapper
M = 16; b = log2(M); L = 1e6; rng(1)
fprintf('\nEbN0   BER gray   berawgn    BER bin    bin/gray   SER gray   SER bin    bits mal (gray, bin)\n')
for EbN0 = 6:2:12
    bits = randi([0 1], L*b, 1);
    N0 = 10 / (b * 10^(EbN0/10));             % Ea = 10 para 16-QAM sin normalizar
    w = sqrt(N0/2) * (randn(L, 1) + 1j*randn(L, 1));
    r = zeros(2, 3);
    for e = 1:2
        et = {'gray', 'bin'}; et = et{e};
        a  = qammod(bits, M, et, 'InputType', 'bit');      % mapper
        ah = my_slicer(a + w, M);                          % slicer de la cátedra
        bh = qamdemod(ah, M, et, 'OutputType', 'bit');     % demapper, con la misma tabla
        r(e,:) = [mean(bh ~= bits), mean(ah ~= a), sum(bh ~= bits)];
    end
    fprintf('%3d   %.3e  %.3e  %.3e  %.4f     %.3e  %.3e  %d, %d\n', EbN0, r(1,1), ...
            berawgn(EbN0, 'qam', M), r(2,1), r(2,1)/r(1,1), r(1,2), r(2,2), r(1,3), r(2,3))
end
% EbN0   BER gray   berawgn    BER bin    bin/gray   SER gray   SER bin    bits mal (gray, bin)
%   6   2.791e-02  2.787e-02  3.723e-02  1.3340     1.085e-01  1.085e-01  111646, 148932
%   8   9.202e-03  9.247e-03  1.233e-02  1.3401     3.648e-02  3.663e-02  36808, 49326
%  10   1.773e-03  1.754e-03  2.378e-03  1.3412     7.073e-03  7.128e-03  7092, 9512
%  12   1.292e-04  1.387e-04  1.727e-04  1.3366     5.170e-04  5.230e-04  517, 691

%% 4. El demapper con otra tabla
rng(2)
fprintf('\nEbN0   SER       BER misma   BER conj(Q)   BER bin en Rx\n')
for EbN0 = [Inf 10 6]
    bits = randi([0 1], L*b, 1);
    a = qammod(bits, M, 'InputType', 'bit');
    w = 0;
    if isfinite(EbN0), N0 = 10/(b*10^(EbN0/10)); w = sqrt(N0/2)*(randn(L,1) + 1j*randn(L,1)); end
    ah = my_slicer(a + w, M);
    b1 = qamdemod(ah, M, 'OutputType', 'bit');              % la misma tabla
    b2 = qamdemod(conj(ah), M, 'OutputType', 'bit');        % Q recorrido al revés
    b3 = qamdemod(ah, M, 'bin', 'OutputType', 'bit');       % natural en el receptor
    fprintf('%4g   %.3e   %.3e   %.5f       %.5f\n', EbN0, mean(ah ~= a), ...
            mean(b1 ~= bits), mean(b2 ~= bits), mean(b3 ~= bits))
end
% PAM-4: la tabla de la filmina (00 arriba) leída con pamdemod (00 abajo)
bits = randi([0 1], 2e5, 1);
k = bit2int(bits, 2);
tabla = [3 1 -3 -1];                         % etiquetas 00 01 10 11 -> +3 +1 -3 -1
bh = int2bit(pamdemod(tabla(k+1).', 4, 0, 'gray'), 2);
fprintf('filmina -> pamdemod: BER %.4f   primer bit %.4f   segundo %.4f\n', ...
        mean(bh ~= bits), mean(bh(1:2:end) ~= bits(1:2:end)), mean(bh(2:2:end) ~= bits(2:2:end)))
% EbN0   SER       BER misma   BER conj(Q)   BER bin en Rx
%  Inf   0.000e+00   0.000e+00   0.25000       0.24979
%   10   7.025e-03   1.759e-03   0.25115       0.25093
%    6   1.085e-01   2.788e-02   0.26850       0.25938
% filmina -> pamdemod: BER 0.5000   primer bit 1.0000   segundo 0.0000

%% 5. El orden de los bits
bh = reshape(de2bi(k, 2).', [], 1);          % de2bi entrega el bit menos significativo primero
fprintf('bit2int -> de2bi: BER %.4f\n', mean(bh ~= bits))
% bit2int -> de2bi: BER 0.5016

%% 6. El demapper blando: un LLR por bit
rng(3); L = 2e5; EbN0 = 8;
bits = randi([0 1], L*b, 1);
a = qammod(bits, M, 'InputType', 'bit');
N0 = 10/(b*10^(EbN0/10));
y = a + sqrt(N0/2)*(randn(L,1) + 1j*randn(L,1));
llr  = qamdemod(y, M, 'OutputType', 'llr', 'NoiseVariance', N0);        % ln P(0)/P(1)
mlog = qamdemod(y, M, 'OutputType', 'approxllr', 'NoiseVariance', N0);  % max-log
dura = qamdemod(my_slicer(y, M), M, 'OutputType', 'bit');
P = qammod((0:M-1).', M); E = reshape(int2bit((0:M-1).', b), b, M).';
d2 = abs(y - P.').^2 / N0;
mio = zeros(L, b);
for j = 1:b                                  % la suma de la definición, a mano
    mio(:,j) = log(sum(exp(-d2(:, E(:,j) == 0)), 2)) - log(sum(exp(-d2(:, E(:,j) == 1)), 2));
end
mio = reshape(mio.', [], 1);
fprintf('max |llr - a mano| = %.1e\n', max(abs(llr - mio)))
fprintf('signo distinto de la dura: max-log %d, exacto %d (de %d bits)\n', ...
        sum((mlog < 0) ~= dura), sum((llr < 0) ~= dura), numel(dura))
ok = dura == bits;
fprintf('mediana de |LLR|: bits bien %.2f, bits mal %.2f\n', median(abs(llr(ok))), median(abs(llr(~ok))))
% max |llr - a mano| = 4.3e-14
% signo distinto de la dura: max-log 0, exacto 0 (de 800000 bits)
% mediana de |LLR|: bits bien 12.11, bits mal 1.16

%% La distancia de Hamming entre vecinos a distancia mínima
function [h, np] = costo_vecino(p, k)
    D = abs(p - p.');
    dmin = min(D(D > 1e-9));
    [i1, i2] = find(triu(abs(D - dmin) < 1e-6*dmin));
    h = arrayfun(@(q) sum(dec2bin(bitxor(k(i1(q)), k(i2(q)))) == '1'), 1:numel(i1));
    np = numel(i1);
end

Cuatro detalles que muerden si no se los conoce:

Para tener a mano

  1. Mapper: grupos de b=log2M bits a un punto de 𝒜, una biyección. Demapper: su inversa sobre la salida del slicer. La SER se cuenta a la salida del slicer y la BER a la del demapper.
  2. La tabla no cambia la SER; cambia cuántos bits cuesta cada error. A SNR alta, BER≈SER·h¯/b, con h¯ el costo medio de los pares a distancia mínima.
  3. Gray reflejado: reflejar la lista y prefijar 0 y 1. Forma cerrada g=n⊕⌊n/2⌋; inversa, ni=gb−1⊕⋯⊕gi. Es cíclico.
  4. Gray da h¯=1 en PAM, en QAM cuadrada (por eje) y en PSK (porque es cíclico). En la 32-QAM en cruz no existe: qammod deja 8 de 52 pares en dos bits, h¯≈1,154.
  5. Natural: (2M−b−2)/(M−1) en PAM, (2M−2)/M en PSK. En 16-QAM, 4/3, y la BER medida sale 1,33 a 1,34 veces la de Gray.
  6. Cualquier Gray sirve si mapper y demapper usan el mismo. Espejar un eje invierte su bit más significativo: con tablas desparejas la BER se clava en 1/b o más, sin errores de símbolo y sin bajar con la SNR.
  7. El orden de los bits es parte de la tabla: int2bit/bit2int ponen el más significativo primero, de2bi/bi2de no.
  8. Demapper blando: un LLR por bit. El signo es el bit del demapper duro; el módulo es la confianza, y es lo que aprovecha un decodificador de canal.
← Anterior Siguiente → Inicio
Relacionados El slicer La modulación PAM La modulación QAM BER y SER no son la misma curva