Parsing hexadecimal numbers to binary and iterating over bits
Not sure this is robust, it only works within the limited numerical range of PGFMath, and clearly I've gone for something a bit more over-the-top than the requirements.
EDIT: following Daniels example of the bitset
package the code has been updated to be a bit more like that.
\documentclass[border=5pt]{standalone}
\usepackage{tikz}
\newcount\bitcount
\tikzset{
zeros/.style={
draw=black,
insert path={
(-\nbit-1/2, -1/2) rectangle ++(1,1)
}
},
ones/.style={
draw=black,
fill=gray,
insert path={
(-\nbit-1/2, -1/2) rectangle ++(1,1)
}
},
max bits/.store in=\maxbits,
max bits=0
}
\newcommand\dispbyte[2][]{%
\begingroup%
\tikzset{#1}%
\pgfmathsetcount\bitcount{#2}%
\pgfmathparse{int(\maxbits)}\let\maxbits=\pgfmathresult%
\pgfmathloop%
\ifnum\bitcount>0\relax%
\ifodd\bitcount%
\expandafter\def\csname bit\pgfmathcounter\endcsname{1}%
\else%
\expandafter\let\csname
bit\pgfmathcounter\endcsname=\relax%
\fi%
\divide\bitcount by2\relax%
\repeatpgfmathloop%
\pgfmathparse{int(\maxbits>\pgfmathcounter?\maxbits+1:\pgfmathcounter+1)}%
\let\nbits=\pgfmathresult%
\pgfmathloop%
\ifnum\pgfmathcounter=\nbits\relax%
\else%
\let\nbit=\pgfmathcounter%
\expandafter\ifx\csname bit\pgfmathcounter\endcsname\relax%
\path [zeros];
\else%
\path [ones];
\fi%
\repeatpgfmathloop%
\endgroup%
}
\begin{document}
\begin{tikzpicture}[x=10pt, y=10pt]
\foreach \d [count=\c from 0, evaluate={\x=floor(\c/8)*8; \y=-mod(\c,8);}]
in
{%
0x7f,0x49,0x08,0x08,0x08,0x08,0x08,0x1c,
0x00,0x00,0x08,0x00,0x18,0x08,0x08,0x1c,
0x08,0x08,0x10,0x12,0x14,0x28,0x24,0x22,
0x7f,0x02,0x04,0x08,0x08,0x10,0x20,0x7f}{
\dispbyte[max bits=8,shift={(\x,\y)}]{\d}
}
\foreach \d [count=\c from 0, evaluate={\x=floor(\c/8)*8; \y=-mod(\c,8);}]
in
{%
0x7f,0x49,0x08,0x08,0x08,0x08,0x08,0x1c,
0x00,0x00,0x08,0x00,0x18,0x08,0x08,0x1c,
0x08,0x08,0x10,0x12,0x14,0x28,0x24,0x22,
0x7f,0x02,0x04,0x08,0x08,0x10,0x20,0x7f}{
\dispbyte[zeros/.style={},
ones/.style={
fill=gray,
insert path={
(-\nbit-3/8, -3/8) rectangle ++(0.75,0.75)
}
},shift={(\x,\y-9)}]{\d}
}
\foreach \d [count=\c from 0, evaluate={\x=floor(\c/8)*8; \y=-mod(\c,8);}]
in
{%
0x7f,0x49,0x08,0x08,0x08,0x08,0x08,0x1c,
0x00,0x00,0x08,0x00,0x18,0x08,0x08,0x1c,
0x08,0x08,0x10,0x12,0x14,0x28,0x24,0x22,
0x7f,0x02,0x04,0x08,0x08,0x10,0x20,0x7f}{
\dispbyte[max bits=8,
zeros/.style={
fill=black,
insert path={
(-\nbit, 0) circle [radius=0.5]
}
},
ones/.style={
fill=orange,
insert path={
(-\nbit, 0) circle [radius=0.5]
}
},shift={(\x,\y-18)}]{\d}
}
\end{tikzpicture}
\end{document}
The following is less impressive than the other answers from the visual point of view (Mark, I like yours!), but addresses the actual question of the OP: Bit-wise iteration over hexadecimal values, which becomes fairly easy when using the bitset
package by Heiko Oberdiek:
\documentclass{article}
\usepackage{bitset}
\usepackage{pgf,pgffor}
\begin{document}
\bitsetSetHex{mybitset}{AA}
% use \bitsetGetSetBitList
% expand first
\edef\mybits{\bitsetGetSetBitList{mybitset}}
\noindent
\foreach \bit in \mybits {%
Bit \bit{} is set! \\
}
% just itereate all bits
\noindent
\foreach \i in {0,...,7} {%
Bit \i: \bitsetGet{mybitset}{\i} \\
}
\end{document}
You can use LaTeX3 that has a function for converting integers to binary. Instead of \fbox
use your preferred macro.
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\dispbyte}{m}
{
\compiler_dispbyte:n { #1 }
}
\tl_new:N \l_compiler_bits_tl
\tl_new:N \l_compiler_byte_tl
\cs_new_protected:Npn \compiler_dispbyte:n #1
{
% we need to remove the 0x
\tl_set:Nn \l_compiler_byte_tl { #1 }
\tl_remove_once:Nn \l_compiler_byte_tl { 0x }
% convert the number to a string of bits
\tl_set:Nx \l_compiler_bits_tl
{ \int_to_binary:n { "\l_compiler_byte_tl } }
% loop through the list of bits
\tl_map_inline:Nn \l_compiler_bits_tl
{ \fbox{ ##1 } }
}
\ExplSyntaxOff
\begin{document}
\dispbyte{0x01}
\dispbyte{0x03}
\dispbyte{0x07}
\dispbyte{0x0F}
\dispbyte{0x11}
\dispbyte{0x13}
\dispbyte{0x17}
\dispbyte{0x1F}
\end{document}
If you need the bits in reverse order, just add
\tl_set:Nx \l_compiler_bits_tl
{ \tl_reverse:V \l_compiler_bits_tl }
before the \tl_map_inline:Nn
line.