13

I'm currently working on a software for an graphic display, so I recreated it in TikZ for documentation purposes:

image of the display

I currently use this to set individual pixels on the display:

\setpixel{x}{y}

Where x and y are coordinates between 0 and 132/64.

The real display is separated into 8 pages, each 8 pixels high, and a byte sent to the display is displayed as a column. See this image for details.

Since I don't want to always calculate the individual pixels, I'd like the LaTeX variant to behave like the real display, that is, I want some command like

\dispbyte{0x01}
\dispbyte{0x03}
\dispbyte{0x07}
\dispbyte{0x0F}
\dispbyte{0x1F}
\dispbyte{0x3F}
\dispbyte{0x7F}
\dispbyte{0xFF}

(this would create one of the triangles above) I have an idea how I'd implement counting of the current column and page switching and all that -- shouldn't be hard with some counters after all -- but I just can't find out how to parse the hexadecimal values and then iterate over every bit inside them.

I've found fmtcount and binhex.tex, but they only display a LaTeX counter in another format, and I can't understand their code at all.

The finished source code (display.sty) and some examples are now available at http://cmpl.cc/downloads/disp/

6
  • That sounds fascinating. Do you intent to publish the source to the pixel -> TikZ conversion?
    – Alexander
    Apr 25, 2013 at 21:13
  • @Alexander I will release the complete source code in a few weeks, when the project I'm writing the documentation for is finished. Apr 26, 2013 at 7:37
  • 2
    It is not absolutely clear to me what you want, hence I write this as a comment: Take a look at the bitset package by Heiko Oberdiek. It provides the abstraction of bitsets of various lenght, which can be initialized from a hex value by \bitsetSetHex. Individual bits can be tested (\bitsetGet) or all set lists transformed into a comma-separated list (\bitsetGetSetBitList) to be then iterated with, e.g., \foreach.
    – Daniel
    Apr 26, 2013 at 10:07
  • 1
    Note also this related question.
    – Daniel
    Apr 26, 2013 at 10:09
  • @TheCompiler: For \foreach you just have to expand it first, e.g., with \edef. I have now posted this as an answer.
    – Daniel
    Apr 26, 2013 at 14:53

5 Answers 5

7

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}

enter image description here

1
  • That was by far the most easy to use way. Took me like 5 minutes to implement what I wanted based on that. Thanks! Apr 27, 2013 at 1:24
9

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}

enter image description here

5

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.

enter image description here

5

I didn't get exactly what you want to do but pgfmath already understands Hex syntax.

\documentclass{article}
\usepackage{tikz}

\begin{document}
\pgfmathparse{bin(0x1F)}
\pgfmathresult

\pgfmathparse{bin(0X1F)}
\pgfmathresult

\end{document}

Both leads to 11111

4

enter image description here

This loops over the binary digits from the hex, for testing it just prints them out (in reverse order to keep the code simple)

\documentclass{article}

\makeatletter
\def\dispbyte#1{\@displaybyte#1\relax}
\def\@displaybyte#1x#2\relax{\count@\string"#2\relax
\loop
  \fbox{\ifodd\count@ 1\else0\fi}%
\divide\count@\tw@
\ifnum\count@>\z@
\repeat}
\makeatother

\begin{document}

\dispbyte{0x17}

\end{document}
4
  • It can't:-) Do you have a non standard format making " active even if babel is notloaded? Apr 25, 2013 at 21:01
  • add \tracingall before \dispbyte and post the log (or email it me: google my name for my gmail account) Apr 25, 2013 at 21:03
  • I didn't try it yet, but two things come to mind by looking at it: 1) how would I use that with babel? Wouldn't " be active as well then? 2) shouldn't the second \makeatletter be a \makeatother? Apr 26, 2013 at 5:42
  • 1
    @TheCompiler you can use \string" to be safe if " is active and yes the second make... is a typo (although it doesn't really matter, I'll fix both:-) Apr 26, 2013 at 6:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .