Andrew Que Sites list Photos
Projects Contact
Main

November 04, 2019

A Flexbox Example

At work this week I had to implement some CSS Flexible Boxes (flexbox), and I'm getting better at using them. The layout called for a fixed- height title bar, fixed-height lower bar with a variable height middle. And in the middle, a fixed-width left and right bar with a variable middle. This illustrates the layout I'm looking for:

Top
Left
Middle
Right
Bottom

The goal here is to have the middle box adjust to the remaining space available. CSS flexboxes are exactly what is needed, but they can be a little tricky to setup. The important thing to remember is that for a <div> to be flexible, it's parent must be marked as flex. The children then need to either specify their size, or be told to stretch. Let's start with a stripped down version of what is need. In this example, we need one fixed-sized <div> on the left, and a variable size <div> on the right that will take the remaining space.

Left
Right

Here is the code to accomplish this :

.body
{
  flex-direction: row;
  width: 400px;
  height: 50px;
  padding: 2px;
}

.left
{
  padding: 2px;
  margin-right: 2px;
  width: 50px;
  background-color: #A0A0A080;
}

.right
{
  padding: 2px;
  flex-grow : 1;
  background-color: #A0A0A080;
}

<div class="body">
  <div class="left">Left</div>
  <div class="right">Right</div>
</div>



Note that we can add boxes to the right and the center will still take the remaining space.

Left
Center
Right 1
Right 2
.body
{
  flex-direction: row;
  width: 400px;
  height: 50px;
  padding: 2px;
}

.left
{
  padding: 2px;
  margin-right: 2px;
  width: 50px;
  background-color: #A0A0A080;
}

.center
{
  padding: 2px;
  flex-grow : 1;
  background-color: #A0A0A080;
}

.right
{
  padding: 2px;
  margin-left: 2px;
  width: 50px;
  background-color: #A0A0A080;
}



<div class="body">
  <div class="left">Left</div>
  <div class="center">Center</div>
  <div class="right">Right 1</div>
  <div class="right">Right 2</div>
</div>

This takes care of the center portion of our request. Now about adding the top and bottom. Let's make a simple change to our setup so this is column based rather than row.

Top
Center
Bottom
.body
{
  flex-direction: column;
  width: 400px;
  height: 150px;
  padding: 2px;
}

.top
{
  padding: 2px;
  margin-bottom: 2px;
  height: 25px;
  background-color: #A0A0A080;
}

.center
{
  padding: 2px;
  flex-grow : 1;
  background-color: #A0A0A080;
}

.bottom
{
  padding: 2px;
  margin-top: 2px;
  height: 25px;
  background-color: #A0A0A080;
}



<div class="body">
  <div class="top">Top</div>
  <div class="center">Center</div>
  <div class="bottom">Bottom</div>
</div>

Now we combine the two setups, nesting the column-based set in the row- based set.

Top
Left
Middle
Right
Bottom
.body
{
  flex-direction: column;
  width: 400px;
  height: 150px;
  padding: 2px;
}

.top
{
  padding: 2px;
  margin-bottom: 2px;
  height: 25px;
  background-color: #A0A0A080;
}

.middle
{
  padding: 2px;
  flex-grow : 1;
  background-color: #A0A0A080;

  display: flex;
  flex-direction: row;
  padding: 4px;
  width: calc( 100% - 8px );
}

.bottom
{
  padding: 2px;
  margin-top: 2px;
  height: 25px;
  background-color: #A0A0A080;
}

.middleLeft
{
  padding: 2px;
  margin-right: 2px;
  width: 50px;
  background-color: #A0A0A080;
}

.middleCenter
{
  padding: 2px;
  flex-grow : 1;
  background-color: #A0A0A080;
}

.middleRight
{
  padding: 2px;
  margin-left: 2px;
  width: 50px;
  background-color: #A0A0A080;
}



<div class="body">
  <div class="top">Top</div>
  
  <div class="middle">
    <div class="middleLeft">Left</div>
    <div class="middleCenter">Middle</div>
    <div class="middleRight">Right</div>
  </div>
  
  <div class="bottom">Bottom</div>
</div>

A couple of items to note. We have two flexible parents, the outer body div, and the middle div. The middle div can both grow and is a flex parent. The middle also uses a bit of math on the width to account for the padding. It should take 100% of the cell, but account for the 8 pixels of padding, 4 on the left, and 4 on the right.

Let's allow the flex area to be resized. Try changing the size by dragging the bottom left corner around.

Top
Left
Middle
Right
Bottom

So it would appear we are done, however there is just one problem.

Top
Left
  • Value A
  • Value B
  • Value C
  • Value D
Bottom

The problem here may not be immediately obvious, but the right column has been shrunk. This happens because the content of the middle div is large and the left and right divs are allowed to shrink. However, we can prevent that.

Top
Left
  • Value A
  • Value B
  • Value C
  • Value D
Bottom
.top
{
  padding: 2px;
  margin-bottom: 2px;
  height: 25px;
  background-color: #A0A0A080;
  flex-shrink: 0;
}

.middle
{
  padding: 2px;
  flex-grow : 1;
  background-color: #A0A0A080;

  display: flex;
  flex-direction: row;
  padding: 4px;
  width: calc( 100% - 8px );
}

.bottom
{
  flex-shrink: 0;
  padding: 2px;
  margin-top: 2px;
  height: 25px;
  background-color: #A0A0A080;
}

.middleLeft
{
  flex-shrink: 0;
  padding: 2px;
  margin-right: 2px;
  width: 50px;
  background-color: #A0A0A080;
}

.middleCenter
{
  padding: 2px;
  flex-grow : 1;
  flex-shrink: 1;
  background-color: #A0A0A080;
}

.middleRight
{
  flex-shrink: 0;
  padding: 2px;
  margin-left: 2px;
  width: 50px;
  background-color: #A0A0A080;
}

While that fixes the column width, it is easy to see that there is a problem with overflow. To fix this we need to address overflow in two location: the middle parent div, and the middle child. The parent can be marked to hide overflow, and the child can either hide or use scroll bars.

Top
Left
  • Value A
  • Value B
  • Value C
  • Value D
Bottom
.top
{
  padding: 2px;
  margin-bottom: 2px;
  height: 25px;
  background-color: #A0A0A080;
  flex-shrink: 0;
}

.middle
{
  padding: 2px;
  flex-grow : 1;
  background-color: #A0A0A080;

  display: flex;
  flex-direction: row;
  padding: 4px;
  width: calc( 100% - 8px );
  overflow: hidden;
}

.bottom
{
  flex-shrink: 0;
  padding: 2px;
  margin-top: 2px;
  height: 25px;
  background-color: #A0A0A080;
}

.middleLeft
{
  flex-shrink: 0;
  padding: 2px;
  margin-right: 2px;
  width: 50px;
  background-color: #A0A0A080;
}

.middleCenter
{
  padding: 2px;
  flex-grow : 1;
  flex-shrink: 1;
  background-color: #A0A0A080;
  
  overflow: auto;
}

.middleRight
{
  flex-shrink: 0;
  padding: 2px;
  margin-left: 2px;
  width: 50px;
  background-color: #A0A0A080;
}

When all of this is done we can get a complex layout that sizes how we want. With the demo below try resizing the content to see how the layout allows the middle box to take the remaining room.

Title of Fixed Area

  • Value A
  • Value B
  • Value C
  • Value D
  • Value E
  • Value F
  • Value G
  • Value H
  • Value I
  • Value J
  • Value K
  • Value L
  • Value M
  • Value N
  • Value O
  • Value P
  • Value Q
  • Value R
  • Value S
  • Value T
  • Value U
  • Value V
  • Value W
  • Value X
  • Value Y
  • Value Z
Column A Column B Column C Column D
Value AValue BValue CValue D
Value AValue BValue CValue D
Value AValue BValue CValue D
Value AValue BValue CValue D
A C D

There you have it. I find it helps to build a page layout in steps so you can get the complexities of items such as flex boxes and overflows.

September 29, 2019

Poor Man's Semaphore Mistake

On small embedded systems that don’t use an operating system, there is often a mix of a main loop and system interrupts for controlling the system. One problem with interrupts is spelled out in their name: they interrupt normal code. This can change variables being used by other code, while they are being used. This can be useful if you are waiting for an event. For example:

bool volatile hasInterruptOccured = false;

void someInterruptFunction()
{
   hasInterruptOccured = true;
}

while ( ! hasInterruptOccured );

Assume someInterruptFunction is called by an interrupt routine and the while loop is in the program’s main function. One important note here is that hasInterruptOccured is marked volatile. That tells the compiler the value could change at any time. Otherwise, the optimizer will assume that since the while loop never changes hasInterruptOccured then it never needs to check it again. Being volatile means the optimizer will make no such assumptions.

The above is a useful example of variable being changed by interrupts, but it can be problematic.

Consider this code below. A function is called periodically to make calculations from x, but x is changed from an interrupt source.

y = a * x * x + b * x + c;

Now consider what happens if x can change at any time. The equation might actually result in the following:

y = a * x1 * x2 + b * x3 + c;

Where only two of the set of xn are equal. We never know when an interrupt might occur, and should plan that is can occur anywhere. One solution to the above is to use an intermediate to hold the value of x.

xHold = x;
y = a * xHold * xHold + b * xHold + c;

This would seem to solve all our problems, but it might not. Consider this code on an 8-bit processor:

uint16_t xHold = x;
y = a * xHold * xHold + b * xHold + c;

You might think that xHold will capture the value of x, but it may not. That is because on an 8-bit system, storing the value of a 16-bit integer takes 2x 8-bit operations, any one of which might be interrupted. This means xHold could change in horrible ways.

Consider x=256 or 0x0100, and an interrupt will change the value to 255 (0x00FF). Now if the assembly code starts the copy with the most-significant byte, then gets interrupted, the result in xHold will be 511 (0x01FF). That’s because it read the most-significant byte when that was set to 0x01, and after the interrupt read the least-significant byte which was now 0xFF.

The typical solution to avoiding such issues is simply to disable interrupts when reading volatile variables.

DisableInterrupts();
uint16_t xHold = x;
RestoreInterrupts();
y = a * xHold * xHold + b * xHold + c;

Now there is no way for x to change when reading.

There is a second way to accomplish the same thing without disabling interrupts.

uint16_x xHold;
do
{
   xHold = x;
} while ( xHold != x );

What’s going on here is that we check to see if x matches what we just read. If it doesn’t, x changed either during the storing, or the reading check. In either case, we simply try again. This works great for things such as system timers, and doesn’t require disabling every interrupt in the system just to get a value. It is my preferred way to fetch a single volatile value, and I usually call this the poor man’s semaphore as the same type of scenarios happens with threaded tasks. With threads you can simply use a semaphore or mutex to wrap the reading area, but you could use the same do-while trick.

Now for how to mess this up. In many projects I use a micro-controller timer as a system clock that counts in milliseconds or tens or hundreds of milliseconds per tick. The interrupt for the timer is very simple:

static uint32_t volatile systemTime = 0;
void timerInterrupt()
{
   systemTime += 1;
}

Then I make a function to get the system time.

uint32_t getSystemTime()
{
   uint32_t result;
   do
   {
      result = systemTime;
   }
   while ( result != systemTime );
   
   return result;
}

The other day I found I had made a mistake in implementing this function. Here is what I had instead:

uint32_t getSystemTime()
{
   uint32_t result;
   do
   {
      result = systemTime;
   }
   while ( result != systemTime );
   return systemTime;
}

The difference is very subtle, but messed up all the work done to ensure the value didn’t change. If the above code were to run on an 8-bit micro-controller, the function could return bad times. I got lucky. In my case, the system was a 32-bit micro-controller with 1 ms ticks and the system time was a 64-bit value. The timer only modifies the upper 32-bit once every 49 days. So the chances for reading an incorrect timer value is very low. Still, a stupid mistake.

January 07, 2019

64-bit CRC support to A.Q. CRC

This weekend I completed the major changes needed for the CRC site to support 64-bit CRC generation. The reason this could not happen right away has to do with how Javascript handles numbers. In Javascript, all numbers are 64-bit (double-precision) floating-point. You can do bit manipulation, but it is done on floating-point values. An IEEE double-precision float has 1 sign bit, 11-bits of exponent and 52-bits of mantissa. In theory one could store 52-bits in a double without loss of precision. That means Javascript cannot directly hold a 64-bit CRC in a single word, and that makes implementation more difficult.

We cannot use a single word to hold results, but we can use multiple words. So the first step in generating larger CRCs inside Javascript is to create an arbitrary length word. Although we technically can use 52-bits/word, it is easier to work with 32-bit words. I created a unit that can do bit manipulation on words of arbitrary length. In reality I only need 64-bit words, but it was about as easy to use make this size arbitrary. The unit needed to support basic bit operations: AND, OR, XOR, shifts, bit reversal, etc., and converting to/from strings.

After a large word unit was implemented I needed to make the CRC class use it. The large words are significantly slower than small, so I kept the original class and simply duplicated the functionality with a large class.

It took a few passes but I worked out all the bugs and now have a functional CRC class that can generate 64-bit CRCs. The system can do the 82-bit CRC, but the C implementation system only supports up to 64-bit word sizes.

January 04, 2019

Verifying Javascript Output

My CRC website creates C source code using Javascript and I needed a method to verify the generated code. As an engineer I am pretty lazy and I didn’t want anything manual so I went in search of a tool that could help. I found system called PhantomJS which seems to be designed to test Javascript rich websites, and it seems to be exactly what I was looking for. I was able to use it to run a test script that generated C code for every possible CRC output combination, along with test C code. The code is then saved to disk where it can be compiled and verified. The results: all good. CRC code for each combination generates the correct CRC for the test vector.

Temp were above 40°F/4°C this afternoon and made for a very pleasant ride home.  Temperatures are forecast to stay warm through the weekend and I have a feeling the snowman I'm standing with will not be around on my next ride.