Code 39 barcode encoder Write a function or program that encodes a string into a Code 39 format barcode, where each character is encoded as five bars separated by four gaps. Either two of the bars and one of the gaps are wide and others are narrow (10*4 codes), or three of the gaps are wide and none of the bars are (4 codes). This gives 44 different codes, from which one is a reserved code that is used to denote the start and end of the encoded string.
The challenge
The input is a string containing only characters from the set
1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ-. +/$%

The output is the string encoded as a barcode string. The narrow gap and intercharacter gaps are a single space and a wide gap is three spaces. The narrow bar is the UTF-8 byte sequence for the Unicode character &quot;Full block&quot;, █, i.e. 0xE2 0x96 0x88 and wide bar is three such byte sequences / characters (███). The full list of codes is:
      Spaces
      0100 0010 0001 1000 1011 1101 1110 0111
Bars
00000                       +    /    $   %
10001   1    A    K    U
01001   2    B    L    V
11000   3    C    M    W
00101   4    D    N    X
10100   5    E    O    Y
01100   6    F    P    Z
00011   7    G    Q    -
10010   8    H    R    .
01010   9    I    S  space          1=wide
00110   0    J    T  start/end      0=narrow

The bars and spaces are interleaved, starting at a bar, so for example Q is
bar   0 0 0  1     1 
code  █ █ █ ███   ███
space  0 0 0    1

After encoding all the characters, the string is delimited at both ends with █   █ ███ ███ █. The intercharacter gap, a single space, is inserted between every letter. Your solution may output trailing spaces and a trailing newline (in that order).
Examples
&quot;&quot;     → &quot;█   █ ███ ███ █ █   █ ███ ███ █&quot;

&quot;A&quot;    → &quot;█   █ ███ ███ █ ███ █ █   █ ███ █   █ ███ ███ █&quot;

&quot;C++&quot;  → &quot;█   █ ███ ███ █ ███ ███ █   █ █ █   █ █   █   █ █   █ █   █   █ █   █ ███ ███ █&quot;

&quot;GOLF&quot; → &quot;█   █ ███ ███ █ █ █ █   ███ ███ ███ █ ███ █   █ █ ███ █ █   ███ █ ███ ███   █ █ █   █ ███ ███ █&quot;

Standard input/output formats are allowed and standard loopholes are disallowed. This is code-golf, so the shortest code measured in bytes wins!
JavaScript (ES6), 225 212 bytes
Saved 4 bytes thanks to @l4m2
s=&gt;`#${s}#`.replace(/./g,c=&gt;'0202020202'.replace(/./g,(j,k)=&gt;[C='█',C+C+C,' ','   '][(i=&quot;%+/$U1AKV2BLW3CMX4DNY5EOZ6FP-7GQ.8HR 9IS#0JT&quot;.indexOf(c),[170,257,260,5,272,17,20,320,65,68,80][i&gt;&gt;2]^2&lt;&lt;i%4*2)&gt;&gt;k&amp;1|j]))

Try it online!
How?
The table can be rearranged such that the 9-bit binary mask of the character is quickly deduced from its row and column using the following formula:
n = m XOR (2 &lt;&lt; k)

with:
  m  | k: 0   2   4   6
-----+------------------      Examples:
 170 |    %   +   /   $
 257 |    U   1   A   K         'G' = 320 XOR (2 &lt;&lt; 4) = 320 XOR 32 = 352
 260 |    V   2   B   L
   5 |    W   3   C   M         '+' = 170 XOR (2 &lt;&lt; 2) = 170 XOR 8  = 162
 272 |    X   4   D   N
  17 |    Y   5   E   O
  20 |    Z   6   F   P
 320 |    -   7   G   Q
  65 |    .   8   H   R
  68 |   spc  9   I   S
  80 |    #   0   J   T